Loading src/crypto/curve25519.cpp +45 −20 Original line number Diff line number Diff line Loading @@ -89,9 +89,20 @@ FieldElement operator*(int32_t scalar, const FieldElement& fe) { } bool FieldElement::operator==(const FieldElement& other) const { return limbs == other.limbs; auto ct_is_zero_u64=[](uint64_t x) { // returns 1 if x == 0 else 0 (constant-time) return (uint32_t)(1 ^ ((x | (0ULL - x)) >> 63)); }; uint64_t diff = 0; for (size_t i = 0; i < 16; ++i) { diff |= (uint64_t)(limbs[i] ^ other.limbs[i]); } return ct_is_zero_u64(diff); } void FieldElement::zero() { std::fill(limbs.begin(), limbs.end(), 0); } void FieldElement::one() { zero(); limbs[0] = 1; } Loading Loading @@ -197,20 +208,35 @@ std::vector<uint8_t> FieldElement::to_bytes() const { s[31] = (uint8_t)(h[9] >> 18); return s; } bool scalarmult_curve25519(std::vector<uint8_t> &out, const std::vector<uint8_t> &scalar, const std::vector<uint8_t> &point_u) { // Lambda for conditional swap auto swap = [&](FieldElement& p, FieldElement& q, int swap) { int64_t t,c = ~(swap -1); void FieldElement::cswap(FieldElement& other, int b) { int64_t t; int64_t c = ~( (int64_t)b - 1 ); // b=0 => c=0, b=1 => c=-1 (all bits 1) for (size_t i = 0; i < 16; ++i) { t = c & (limbs[i] ^ other.limbs[i]); limbs[i] ^= t; other.limbs[i] ^= t; } } void FieldElement::sel25519(FieldElement& q, int b) { b &= 1; // safety: ensure b is 0 or 1 int64_t t; int64_t c = ~((int64_t)b - 1); // b=0 => 0x0, b=1 => 0xFFFF...FFFF for (size_t i = 0; i < 16; ++i) { t=c&(p.limbs[i]^q.limbs[i]); p.limbs[i]^=t; t = c & (limbs[i] ^ q.limbs[i]); limbs[i] ^= t; q.limbs[i] ^= t; } return; }; } bool scalarmult_curve25519(std::vector<uint8_t> &out, const std::vector<uint8_t> &scalar, const std::vector<uint8_t> &point_u) { auto pack = [&](std::vector<uint8_t> &out,const FieldElement &in){ out.resize(32); Loading @@ -229,7 +255,7 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, m.limbs[15]=t.limbs[15]-0x7FFF-((m.limbs[14]>>16) &1); carry=(m.limbs[15]>>16) & 1; m.limbs[14] &=0xFFFF; swap(t,m,1-carry); t.cswap(m,1-carry); } for(size_t i = 0; i <16; ++i){ out[2*i] = t.limbs[i] & 0xFF; Loading @@ -254,8 +280,8 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, a.limbs[0]=d.limbs[0] = 1; for(size_t i=254; i!=std::string::npos; --i){ bit=(clamped[i >>3 ] >> (i & 7)) & 1; swap(a,b,bit); swap(c,d,bit); a.sel25519(b, bit); c.sel25519(d, bit); e=a+c; a=a-c; c=b+d; Loading @@ -274,8 +300,8 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, a=d*f; d=b*x; b=e*e; swap(a,b,bit); swap(c,d,bit); a.sel25519(b, bit); c.sel25519(d, bit); } c=c.invert(); a=a*c; Loading @@ -287,9 +313,8 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, bool scalarmult_curve25519_base(std::vector<uint8_t> &out, const std::vector<uint8_t> &scalar) { // The Curve25519 base point (u = 9, little-endian 32 bytes) std::vector<uint8_t> base_point; base_point.resize(32); std::fill(base_point.begin(),base_point.end(),9); std::vector<uint8_t> base_point(32,0); base_point[0]=9; // Delegate to the main scalar multiplication function return scalarmult_curve25519(out, scalar, base_point); } Loading src/crypto/curve25519.h +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ public: void zero(); void one(); FieldElement invert() const; void cswap(FieldElement& other, int b); void sel25519(FieldElement& q, int b); std::vector<uint8_t> to_bytes() const; void from_bytes(std::vector<uint8_t> in); Loading Loading
src/crypto/curve25519.cpp +45 −20 Original line number Diff line number Diff line Loading @@ -89,9 +89,20 @@ FieldElement operator*(int32_t scalar, const FieldElement& fe) { } bool FieldElement::operator==(const FieldElement& other) const { return limbs == other.limbs; auto ct_is_zero_u64=[](uint64_t x) { // returns 1 if x == 0 else 0 (constant-time) return (uint32_t)(1 ^ ((x | (0ULL - x)) >> 63)); }; uint64_t diff = 0; for (size_t i = 0; i < 16; ++i) { diff |= (uint64_t)(limbs[i] ^ other.limbs[i]); } return ct_is_zero_u64(diff); } void FieldElement::zero() { std::fill(limbs.begin(), limbs.end(), 0); } void FieldElement::one() { zero(); limbs[0] = 1; } Loading Loading @@ -197,20 +208,35 @@ std::vector<uint8_t> FieldElement::to_bytes() const { s[31] = (uint8_t)(h[9] >> 18); return s; } bool scalarmult_curve25519(std::vector<uint8_t> &out, const std::vector<uint8_t> &scalar, const std::vector<uint8_t> &point_u) { // Lambda for conditional swap auto swap = [&](FieldElement& p, FieldElement& q, int swap) { int64_t t,c = ~(swap -1); void FieldElement::cswap(FieldElement& other, int b) { int64_t t; int64_t c = ~( (int64_t)b - 1 ); // b=0 => c=0, b=1 => c=-1 (all bits 1) for (size_t i = 0; i < 16; ++i) { t = c & (limbs[i] ^ other.limbs[i]); limbs[i] ^= t; other.limbs[i] ^= t; } } void FieldElement::sel25519(FieldElement& q, int b) { b &= 1; // safety: ensure b is 0 or 1 int64_t t; int64_t c = ~((int64_t)b - 1); // b=0 => 0x0, b=1 => 0xFFFF...FFFF for (size_t i = 0; i < 16; ++i) { t=c&(p.limbs[i]^q.limbs[i]); p.limbs[i]^=t; t = c & (limbs[i] ^ q.limbs[i]); limbs[i] ^= t; q.limbs[i] ^= t; } return; }; } bool scalarmult_curve25519(std::vector<uint8_t> &out, const std::vector<uint8_t> &scalar, const std::vector<uint8_t> &point_u) { auto pack = [&](std::vector<uint8_t> &out,const FieldElement &in){ out.resize(32); Loading @@ -229,7 +255,7 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, m.limbs[15]=t.limbs[15]-0x7FFF-((m.limbs[14]>>16) &1); carry=(m.limbs[15]>>16) & 1; m.limbs[14] &=0xFFFF; swap(t,m,1-carry); t.cswap(m,1-carry); } for(size_t i = 0; i <16; ++i){ out[2*i] = t.limbs[i] & 0xFF; Loading @@ -254,8 +280,8 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, a.limbs[0]=d.limbs[0] = 1; for(size_t i=254; i!=std::string::npos; --i){ bit=(clamped[i >>3 ] >> (i & 7)) & 1; swap(a,b,bit); swap(c,d,bit); a.sel25519(b, bit); c.sel25519(d, bit); e=a+c; a=a-c; c=b+d; Loading @@ -274,8 +300,8 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, a=d*f; d=b*x; b=e*e; swap(a,b,bit); swap(c,d,bit); a.sel25519(b, bit); c.sel25519(d, bit); } c=c.invert(); a=a*c; Loading @@ -287,9 +313,8 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, bool scalarmult_curve25519_base(std::vector<uint8_t> &out, const std::vector<uint8_t> &scalar) { // The Curve25519 base point (u = 9, little-endian 32 bytes) std::vector<uint8_t> base_point; base_point.resize(32); std::fill(base_point.begin(),base_point.end(),9); std::vector<uint8_t> base_point(32,0); base_point[0]=9; // Delegate to the main scalar multiplication function return scalarmult_curve25519(out, scalar, base_point); } Loading
src/crypto/curve25519.h +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ public: void zero(); void one(); FieldElement invert() const; void cswap(FieldElement& other, int b); void sel25519(FieldElement& q, int b); std::vector<uint8_t> to_bytes() const; void from_bytes(std::vector<uint8_t> in); Loading