Loading src/crypto/curve25519.cpp +60 −102 Original line number Diff line number Diff line Loading @@ -130,83 +130,34 @@ void FieldElement::from_bytes(std::vector<uint8_t> in){ } std::vector<uint8_t> FieldElement::to_bytes() const { int64_t h[10]; for (int i = 0; i < 16; ++i) h[i] = limbs[i]; // --------------------------------------------------------------------- // Canonical reduction: ensure 0 <= h < p // (this is standard ref10 carry + conditional subtraction) // --------------------------------------------------------------------- int64_t q = (19 * h[9] + (1LL << 24)) >> 25; q = (h[0] + q) >> 26; q = (h[1] + q) >> 25; q = (h[2] + q) >> 26; q = (h[3] + q) >> 25; q = (h[4] + q) >> 26; q = (h[5] + q) >> 25; q = (h[6] + q) >> 26; q = (h[7] + q) >> 25; q = (h[8] + q) >> 26; q = (h[9] + q) >> 25; h[0] += 19 * q; int64_t carry0 = h[0] >> 26; h[1] += carry0; h[0] -= carry0 << 26; int64_t carry1 = h[1] >> 25; h[2] += carry1; h[1] -= carry1 << 25; int64_t carry2 = h[2] >> 26; h[3] += carry2; h[2] -= carry2 << 26; int64_t carry3 = h[3] >> 25; h[4] += carry3; h[3] -= carry3 << 25; int64_t carry4 = h[4] >> 26; h[5] += carry4; h[4] -= carry4 << 26; int64_t carry5 = h[5] >> 25; h[6] += carry5; h[5] -= carry5 << 25; int64_t carry6 = h[6] >> 26; h[7] += carry6; h[6] -= carry6 << 26; int64_t carry7 = h[7] >> 25; h[8] += carry7; h[7] -= carry7 << 25; int64_t carry8 = h[8] >> 26; h[9] += carry8; h[8] -= carry8 << 26; int64_t carry9 = h[9] >> 25; h[0] += carry9 * 19; h[9] -= carry9 << 25; int64_t carry0b = h[0] >> 26; h[1] += carry0b; h[0] -= carry0b << 26; // --------------------------------------------------------------------- // Pack into 32 bytes little-endian (canonical ref10 mapping) // --------------------------------------------------------------------- std::vector<uint8_t> s; s.assign(32, 0); s[0] = (uint8_t)(h[0] >> 0); s[1] = (uint8_t)(h[0] >> 8); s[2] = (uint8_t)(h[0] >> 16); s[3] = (uint8_t)((h[0] >> 24) | (h[1] << 2)); s[4] = (uint8_t)(h[1] >> 6); s[5] = (uint8_t)(h[1] >> 14); s[6] = (uint8_t)((h[1] >> 22) | (h[2] << 3)); s[7] = (uint8_t)(h[2] >> 5); s[8] = (uint8_t)(h[2] >> 13); s[9] = (uint8_t)((h[2] >> 21) | (h[3] << 5)); s[10] = (uint8_t)(h[3] >> 3); s[11] = (uint8_t)(h[3] >> 11); s[12] = (uint8_t)((h[3] >> 19) | (h[4] << 6)); s[13] = (uint8_t)(h[4] >> 2); s[14] = (uint8_t)(h[4] >> 10); s[15] = (uint8_t)(h[4] >> 18); s[16] = (uint8_t)(h[5] >> 0); s[17] = (uint8_t)(h[5] >> 8); s[18] = (uint8_t)(h[5] >> 16); s[19] = (uint8_t)((h[5] >> 24) | (h[6] << 1)); s[20] = (uint8_t)(h[6] >> 7); s[21] = (uint8_t)(h[6] >> 15); s[22] = (uint8_t)((h[6] >> 23) | (h[7] << 3)); s[23] = (uint8_t)(h[7] >> 5); s[24] = (uint8_t)(h[7] >> 13); s[25] = (uint8_t)((h[7] >> 21) | (h[8] << 4)); s[26] = (uint8_t)(h[8] >> 4); s[27] = (uint8_t)(h[8] >> 12); s[28] = (uint8_t)((h[8] >> 20) | (h[9] << 6)); s[29] = (uint8_t)(h[9] >> 2); s[30] = (uint8_t)(h[9] >> 10); s[31] = (uint8_t)(h[9] >> 18); return s; FieldElement t = *this; FieldElement m; // 3 carries wie in ref10 t.carry25519(); t.carry25519(); t.carry25519(); for (int j = 0; j < 2; ++j) { m.limbs[0] = t.limbs[0] - 0xFFED; for (int i = 1; i < 15; ++i) { m.limbs[i] = t.limbs[i] - 0xFFFF - ((m.limbs[i-1] >> 16) & 1); m.limbs[i-1] &= 0xFFFF; } m.limbs[15] = t.limbs[15] - 0x7FFF - ((m.limbs[14] >> 16) & 1); int carry = (m.limbs[15] >> 16) & 1; m.limbs[14] &= 0xFFFF; // constant-time select: t.sel25519(m, 1 - carry); } std::vector<uint8_t> out(32); for (int i = 0; i < 16; ++i) { out[2*i] = (uint8_t)(t.limbs[i] & 0xFF); out[2*i + 1] = (uint8_t)((t.limbs[i] >> 8) & 0xFF); } return out; } void FieldElement::cswap(FieldElement& other, int b) { Loading Loading @@ -263,7 +214,6 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, } }; std::array<uint8_t,32> clamped; int64_t bit; FieldElement _12665; _12665.limbs={0xDB41,1}; FieldElement a,b,c,d,e,f,x; Loading @@ -278,10 +228,16 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, d.limbs[i]=a.limbs[i] = c.limbs[i] =0; } a.limbs[0]=d.limbs[0] = 1; for(size_t i=254; i!=std::string::npos; --i){ bit=(clamped[i >>3 ] >> (i & 7)) & 1; a.sel25519(b, bit); c.sel25519(d, bit); int swapbit = 0; for (int i = 254; i >= 0; --i) { int bit = (clamped[i >> 3] >> (i & 7)) & 1; swapbit ^= bit; a.sel25519(b, swapbit); c.sel25519(d, swapbit); swapbit = bit; e = a + c; a = a - c; c = b + d; Loading @@ -300,9 +256,11 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, a = d * f; d = b * x; b = e * e; a.sel25519(b, bit); c.sel25519(d, bit); } a.sel25519(b, swapbit); c.sel25519(d, swapbit); c=c.invert(); a=a*c; pack(out,a); Loading Loading
src/crypto/curve25519.cpp +60 −102 Original line number Diff line number Diff line Loading @@ -130,83 +130,34 @@ void FieldElement::from_bytes(std::vector<uint8_t> in){ } std::vector<uint8_t> FieldElement::to_bytes() const { int64_t h[10]; for (int i = 0; i < 16; ++i) h[i] = limbs[i]; // --------------------------------------------------------------------- // Canonical reduction: ensure 0 <= h < p // (this is standard ref10 carry + conditional subtraction) // --------------------------------------------------------------------- int64_t q = (19 * h[9] + (1LL << 24)) >> 25; q = (h[0] + q) >> 26; q = (h[1] + q) >> 25; q = (h[2] + q) >> 26; q = (h[3] + q) >> 25; q = (h[4] + q) >> 26; q = (h[5] + q) >> 25; q = (h[6] + q) >> 26; q = (h[7] + q) >> 25; q = (h[8] + q) >> 26; q = (h[9] + q) >> 25; h[0] += 19 * q; int64_t carry0 = h[0] >> 26; h[1] += carry0; h[0] -= carry0 << 26; int64_t carry1 = h[1] >> 25; h[2] += carry1; h[1] -= carry1 << 25; int64_t carry2 = h[2] >> 26; h[3] += carry2; h[2] -= carry2 << 26; int64_t carry3 = h[3] >> 25; h[4] += carry3; h[3] -= carry3 << 25; int64_t carry4 = h[4] >> 26; h[5] += carry4; h[4] -= carry4 << 26; int64_t carry5 = h[5] >> 25; h[6] += carry5; h[5] -= carry5 << 25; int64_t carry6 = h[6] >> 26; h[7] += carry6; h[6] -= carry6 << 26; int64_t carry7 = h[7] >> 25; h[8] += carry7; h[7] -= carry7 << 25; int64_t carry8 = h[8] >> 26; h[9] += carry8; h[8] -= carry8 << 26; int64_t carry9 = h[9] >> 25; h[0] += carry9 * 19; h[9] -= carry9 << 25; int64_t carry0b = h[0] >> 26; h[1] += carry0b; h[0] -= carry0b << 26; // --------------------------------------------------------------------- // Pack into 32 bytes little-endian (canonical ref10 mapping) // --------------------------------------------------------------------- std::vector<uint8_t> s; s.assign(32, 0); s[0] = (uint8_t)(h[0] >> 0); s[1] = (uint8_t)(h[0] >> 8); s[2] = (uint8_t)(h[0] >> 16); s[3] = (uint8_t)((h[0] >> 24) | (h[1] << 2)); s[4] = (uint8_t)(h[1] >> 6); s[5] = (uint8_t)(h[1] >> 14); s[6] = (uint8_t)((h[1] >> 22) | (h[2] << 3)); s[7] = (uint8_t)(h[2] >> 5); s[8] = (uint8_t)(h[2] >> 13); s[9] = (uint8_t)((h[2] >> 21) | (h[3] << 5)); s[10] = (uint8_t)(h[3] >> 3); s[11] = (uint8_t)(h[3] >> 11); s[12] = (uint8_t)((h[3] >> 19) | (h[4] << 6)); s[13] = (uint8_t)(h[4] >> 2); s[14] = (uint8_t)(h[4] >> 10); s[15] = (uint8_t)(h[4] >> 18); s[16] = (uint8_t)(h[5] >> 0); s[17] = (uint8_t)(h[5] >> 8); s[18] = (uint8_t)(h[5] >> 16); s[19] = (uint8_t)((h[5] >> 24) | (h[6] << 1)); s[20] = (uint8_t)(h[6] >> 7); s[21] = (uint8_t)(h[6] >> 15); s[22] = (uint8_t)((h[6] >> 23) | (h[7] << 3)); s[23] = (uint8_t)(h[7] >> 5); s[24] = (uint8_t)(h[7] >> 13); s[25] = (uint8_t)((h[7] >> 21) | (h[8] << 4)); s[26] = (uint8_t)(h[8] >> 4); s[27] = (uint8_t)(h[8] >> 12); s[28] = (uint8_t)((h[8] >> 20) | (h[9] << 6)); s[29] = (uint8_t)(h[9] >> 2); s[30] = (uint8_t)(h[9] >> 10); s[31] = (uint8_t)(h[9] >> 18); return s; FieldElement t = *this; FieldElement m; // 3 carries wie in ref10 t.carry25519(); t.carry25519(); t.carry25519(); for (int j = 0; j < 2; ++j) { m.limbs[0] = t.limbs[0] - 0xFFED; for (int i = 1; i < 15; ++i) { m.limbs[i] = t.limbs[i] - 0xFFFF - ((m.limbs[i-1] >> 16) & 1); m.limbs[i-1] &= 0xFFFF; } m.limbs[15] = t.limbs[15] - 0x7FFF - ((m.limbs[14] >> 16) & 1); int carry = (m.limbs[15] >> 16) & 1; m.limbs[14] &= 0xFFFF; // constant-time select: t.sel25519(m, 1 - carry); } std::vector<uint8_t> out(32); for (int i = 0; i < 16; ++i) { out[2*i] = (uint8_t)(t.limbs[i] & 0xFF); out[2*i + 1] = (uint8_t)((t.limbs[i] >> 8) & 0xFF); } return out; } void FieldElement::cswap(FieldElement& other, int b) { Loading Loading @@ -263,7 +214,6 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, } }; std::array<uint8_t,32> clamped; int64_t bit; FieldElement _12665; _12665.limbs={0xDB41,1}; FieldElement a,b,c,d,e,f,x; Loading @@ -278,10 +228,16 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, d.limbs[i]=a.limbs[i] = c.limbs[i] =0; } a.limbs[0]=d.limbs[0] = 1; for(size_t i=254; i!=std::string::npos; --i){ bit=(clamped[i >>3 ] >> (i & 7)) & 1; a.sel25519(b, bit); c.sel25519(d, bit); int swapbit = 0; for (int i = 254; i >= 0; --i) { int bit = (clamped[i >> 3] >> (i & 7)) & 1; swapbit ^= bit; a.sel25519(b, swapbit); c.sel25519(d, swapbit); swapbit = bit; e = a + c; a = a - c; c = b + d; Loading @@ -300,9 +256,11 @@ bool scalarmult_curve25519(std::vector<uint8_t> &out, a = d * f; d = b * x; b = e * e; a.sel25519(b, bit); c.sel25519(d, bit); } a.sel25519(b, swapbit); c.sel25519(d, swapbit); c=c.invert(); a=a*c; pack(out,a); Loading