Commit b860bfa6 authored by jan.koester's avatar jan.koester
Browse files

test

parent d1e781c8
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -2,8 +2,8 @@
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x14\x00l\x00i\x00b\x00n\x00e\x00t\x00p\x00l\x00u\x00s)

[CMake]
Build Directory Count=2
Current Build Directory Index-Host System=0
Build Directory Count=3
Current Build Directory Index-Host System=2
Current Build Directory Index-Host-System=1
Temporary Build Directory Index=1

@@ -25,7 +25,7 @@ CMake Executable=/usr/bin/cmake
Environment Profile=
Extra Arguments=
Install Directory=/usr/local
Runtime=Host-System
Runtime=Host System

[MakeBuilder]
Make Binary=ninja
+128 −235
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ FieldElement::FieldElement(int v) {

FieldElement::FieldElement(const std::vector<int32_t>& v) {
    limbs.fill(0);
    for (size_t i = 0; i < 10 && i < v.size(); ++i)
    for (size_t i = 0; i < 16 && i < v.size(); ++i)
        limbs[i] = v[i];
}

@@ -26,110 +26,60 @@ FieldElement::FieldElement(const FieldElement& src) : limbs(src.limbs) {}

FieldElement& FieldElement::operator=(const std::vector<int32_t>& v) {
    limbs.fill(0);
    for (size_t i = 0; i < 10 && i < v.size(); ++i)
    for (size_t i = 0; i < 16 && i < v.size(); ++i)
        limbs[i] = v[i];
    return *this;
}

FieldElement FieldElement::operator+(const FieldElement& other) const {
    FieldElement r;
    for (int i = 0; i < 10; ++i)
    for (int i = 0; i < 16; ++i)
        r.limbs[i] = limbs[i] + other.limbs[i];
    return r;
}

FieldElement FieldElement::operator-(const FieldElement& other) const {
    FieldElement r;
    for (int i = 0; i < 10; ++i)
    for (int i = 0; i < 16; ++i)
        r.limbs[i] = limbs[i] - other.limbs[i];
    return r;
}

FieldElement FieldElement::operator*(const FieldElement& g) const {
    const int64_t* f = limbs.data();
    const int64_t* h = g.limbs.data();

    int64_t f0 = f[0];
    int64_t f1 = f[1];
    int64_t f2 = f[2];
    int64_t f3 = f[3];
    int64_t f4 = f[4];
    int64_t f5 = f[5];
    int64_t f6 = f[6];
    int64_t f7 = f[7];
    int64_t f8 = f[8];
    int64_t f9 = f[9];

    int64_t g0 = h[0];
    int64_t g1 = h[1];
    int64_t g2 = h[2];
    int64_t g3 = h[3];
    int64_t g4 = h[4];
    int64_t g5 = h[5];
    int64_t g6 = h[6];
    int64_t g7 = h[7];
    int64_t g8 = h[8];
    int64_t g9 = h[9];

    int64_t g1_19 = 19 * g1;
    int64_t g2_19 = 19 * g2;
    int64_t g3_19 = 19 * g3;
    int64_t g4_19 = 19 * g4;
    int64_t g5_19 = 19 * g5;
    int64_t g6_19 = 19 * g6;
    int64_t g7_19 = 19 * g7;
    int64_t g8_19 = 19 * g8;
    int64_t g9_19 = 19 * g9;

    int64_t f1_2 = 2 * f1;
    int64_t f3_2 = 2 * f3;
    int64_t f5_2 = 2 * f5;
    int64_t f7_2 = 2 * f7;
    int64_t f9_2 = 2 * f9;

    int64_t h0 = f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19;
    int64_t h1 = f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19;
    int64_t h2 = f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19;
    int64_t h3 = f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19;
    int64_t h4 = f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19;
    int64_t h5 = f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19;
    int64_t h6 = f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19;
    int64_t h7 = f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19;
    int64_t h8 = f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19;
    int64_t h9 = f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0;

    // carry propagation
    int64_t carry0 = (h0 + (1LL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
    int64_t carry1 = (h1 + (1LL<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
    int64_t carry2 = (h2 + (1LL<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
    int64_t carry3 = (h3 + (1LL<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
    int64_t carry4 = (h4 + (1LL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
    int64_t carry5 = (h5 + (1LL<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
    int64_t carry6 = (h6 + (1LL<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
    int64_t carry7 = (h7 + (1LL<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
    int64_t carry8 = (h8 + (1LL<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
    int64_t carry9 = (h9 + (1LL<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
void FieldElement::carry25519(){
    int64_t cry;
    for(size_t i=0; i<16; ++i){
        cry =limbs[i] >> 16;
        limbs[i]-=cry << 16;
        i < 15 ? limbs[i+1]+=cry : limbs[0] += 38 * cry;
    }
    return;
};

    carry0 = (h0 + (1LL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
FieldElement FieldElement::operator*(const FieldElement& g) const {
    std::array<int64_t,31> prod;
    std::fill(prod.begin(),prod.end(),0);
    FieldElement out;

    FieldElement r;
    r.limbs[0] = h0;
    r.limbs[1] = h1;
    r.limbs[2] = h2;
    r.limbs[3] = h3;
    r.limbs[4] = h4;
    r.limbs[5] = h5;
    r.limbs[6] = h6;
    r.limbs[7] = h7;
    r.limbs[8] = h8;
    r.limbs[9] = h9;
    return r;
    for(size_t i=0; i< 16; ++i){
        for(size_t j=0; j<16; ++j){
            prod[i+j]+=this->limbs[i] * g.limbs[j];
        }
    }
    for(size_t i=0; i< 15; ++i){
        prod[i] += 38 * prod[i+16];
    }
    for(size_t i=0; i <16; ++i){
        out.limbs[i]=prod[i];
    }
    out.carry25519();
    out.carry25519();
    return out;
}

FieldElement FieldElement::operator*(int32_t scalar) const {
    FieldElement r;
    int64_t sc = scalar;
    for (int i = 0; i < 10; ++i)
    for (int i = 0; i < 16; ++i)
        r.limbs[i] = limbs[i] * sc;
    return r;
}
@@ -148,73 +98,29 @@ void FieldElement::one() { zero(); limbs[0] = 1; }

// Add to FieldElement class:
FieldElement FieldElement::invert() const {
    FieldElement z2;   // z^2
    FieldElement z9;   // z^9
    FieldElement z11;  // z^11
    FieldElement z2_5_0;
    FieldElement z2_10_0;
    FieldElement z2_20_0;
    FieldElement z2_50_0;
    FieldElement z2_100_0;
    FieldElement t;

    // 2
    z2 = (*this) * (*this);

    // 4
    t = z2 * z2;

    // 8
    t = t * t;

    // 9
    z9 = t * (*this);

    // 11
    z11 = z9 * z2;

    // 2^5 - 2^0 = 31
    z2_5_0 = z11;
    for (int i = 0; i < 5; ++i) z2_5_0 = z2_5_0 * z2_5_0;
    z2_5_0 = z2_5_0 * z11;

    // 2^10 - 2^0
    z2_10_0 = z2_5_0;
    for (int i = 0; i < 10; ++i) z2_10_0 = z2_10_0 * z2_10_0;
    z2_10_0 = z2_10_0 * z2_5_0;

    // 2^20 - 2^0
    z2_20_0 = z2_10_0;
    for (int i = 0; i < 20; ++i) z2_20_0 = z2_20_0 * z2_20_0;
    z2_20_0 = z2_20_0 * z2_10_0;

    // 2^50 - 2^0
    z2_50_0 = z2_20_0;
    for (int i = 0; i < 50; ++i) z2_50_0 = z2_50_0 * z2_50_0;
    z2_50_0 = z2_50_0 * z2_20_0;

    // 2^100 - 2^0
    z2_100_0 = z2_50_0;
    for (int i = 0; i < 100; ++i) z2_100_0 = z2_100_0 * z2_100_0;
    z2_100_0 = z2_100_0 * z2_50_0;

    // 2^200 - 2^0
    t = z2_100_0;
    for (int i = 0; i < 100; ++i) t = t * t;
    t = t * z2_100_0;

    // 2^250 - 2^0
    for (int i = 0; i < 50; ++i) t = t * t;
    t = t * z2_50_0;
    FieldElement out;
    for(size_t i =0; i< limbs.size(); ++i){
        out.limbs[i]=limbs[i];
    }
    for(size_t i = 253; i!=std::string::npos; i--){
        out=out * out;
        if(i!=2 && i!=4){
            out=out*(*this);
        }
    }
    return out;
}

    // 2^255 - 21
    for (int i = 0; i < 5; ++i) t = t * t;
    return t * z11;
void FieldElement::from_bytes(std::vector<uint8_t> in){
    for(size_t i=0; i< 16; ++i){
        limbs[i]=in[2*i]+static_cast<int64_t>(in[2*i+1] << 8);
    }
    limbs[15] &=0x7FFF;
}

std::vector<uint8_t> FieldElement::to_bytes() const {
    int64_t h[10];
    for (int i = 0; i < 10; ++i) h[i] = limbs[i];
    for (int i = 0; i < 16; ++i) h[i] = limbs[i];

    // ---------------------------------------------------------------------
    // Canonical reduction: ensure 0 <= h < p
@@ -291,112 +197,99 @@ 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) {

    auto cswap = [&](FieldElement& a, FieldElement& b, int swap) {
        uint64_t mask = (uint64_t)-(int64_t)swap; // 0 or all-ones
        for (int i = 0; i < 10; ++i) {
            uint64_t ai = (uint64_t)a.limbs[i];
            uint64_t bi = (uint64_t)b.limbs[i];
            uint64_t t  = mask & (ai ^ bi);
            a.limbs[i] = (int64_t)(ai ^ t);
            b.limbs[i] = (int64_t)(bi ^ t);
    // Lambda for conditional swap
    auto swap = [&](FieldElement& p, FieldElement& q, int swap) {
        int64_t t,c = ~(swap -1);
        for(size_t i=0; i<16; ++i){
            t=c&(p.limbs[i]^q.limbs[i]);
            p.limbs[i]^=t;
            q.limbs[i]^=t;
        }
        return;
    };

    auto load_3 = [&](const uint8_t *in) -> uint32_t {
        return (uint32_t)in[0] |
            ((uint32_t)in[1] << 8) |
            ((uint32_t)in[2] << 16);
    };

    auto load_4 = [&](const uint8_t *in) -> uint32_t {
        return (uint32_t)in[0] |
            ((uint32_t)in[1] << 8) |
            ((uint32_t)in[2] << 16) |
            ((uint32_t)in[3] << 24);
    };

    // Check input sizes
    if (scalar.size() != 32 || point_u.size() != 32) return false;
    auto pack = [&](std::vector<uint8_t> &out,const FieldElement &in){
        out.resize(32);

    // Clamp scalar as per RFC7748
    std::vector<uint8_t> e = scalar;
    e[0]  &= 248;
    e[31] &= 127;
    e[31] |= 64;

    // Decode u-coordinate (little-endian)
    FieldElement u;
    u.zero();
    // Decode u-coordinate (little-endian) into 10 limbs (ref10 fe_frombytes)
    u.limbs[0] =  load_4(&point_u[0])        & 0x3ffffff;
    u.limbs[1] = (load_3(&point_u[3]) >> 2)  & 0x1ffffff;
    u.limbs[2] = (load_3(&point_u[6]) >> 3)  & 0x3ffffff;
    u.limbs[3] = (load_3(&point_u[9]) >> 5)  & 0x1ffffff;
    u.limbs[4] = (load_3(&point_u[12]) >> 6) & 0x3ffffff;
    u.limbs[5] =  load_4(&point_u[16])       & 0x1ffffff;
    u.limbs[6] = (load_3(&point_u[19]) >> 1) & 0x3ffffff;
    u.limbs[7] = (load_3(&point_u[22]) >> 3) & 0x1ffffff;
    u.limbs[8] = (load_3(&point_u[25]) >> 4) & 0x3ffffff;
    u.limbs[9] = (load_3(&point_u[28]) >> 6) & 0x1ffffff;


    // Initialize ladder
    FieldElement x1 = u;
    FieldElement x2; x2.one();
    FieldElement z2; z2.zero();
    FieldElement x3 = u;
    FieldElement z3; z3.one();
    int swap = 0;

    // Montgomery ladder
    for (int t = 254; t >= 0; --t) {
        int k_t = (e[t / 8] >> (t & 7)) & 1;
        swap ^= k_t;
        // Conditional swap
        cswap(x2, x3, swap);
        cswap(z2, z3, swap);
        swap = k_t;

        // Differential addition and doubling
        FieldElement A = x2 + z2;
        FieldElement B = x2 - z2;
        FieldElement C = x3 + z3;
        FieldElement D = x3 - z3;
        FieldElement DA = D * A;
        FieldElement CB = C * B;
        FieldElement E = (DA + CB);
        FieldElement F = (DA - CB);
        FieldElement AA = A * A;
        FieldElement BB = B * B;
        FieldElement EE = AA - BB;
        FieldElement G = AA + 121666 * EE;
        x2 = AA * BB;
        x3 = E * E;
        z3 = x1 * F * F;
        z2 = EE * G;
    }
    // Final swap if needed
    cswap(x2, x3, swap);
    cswap(z2, z3, swap);
    // Compute u = x2 / z2
    FieldElement z2inv = z2.invert();
    FieldElement result = x2 * z2inv;
    out=result.to_bytes();
        int carry;
        FieldElement m,t;
        for(size_t i=0; i <16; ++i){
            t.limbs[i]=in.limbs[i];
        }
        t.carry25519(); t.carry25519(); t.carry25519();
        for(size_t j=0; j<2; ++j){
            m.limbs[0]=t.limbs[0]-0xFFED;
            for(size_t 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);
            carry=(m.limbs[15]>>16) & 1;
            m.limbs[14] &=0xFFFF;
            swap(t,m,1-carry);
        }
        for(size_t i = 0; i <16; ++i){
            out[2*i] = t.limbs[i] & 0xFF;
            out[2*i+1] = t.limbs[i] >> 8;
        }
    };
    std::array<uint8_t,32> clamped;
    int64_t bit;
    FieldElement _12665;
    _12665.limbs={0xDB41,1};
    FieldElement a,b,c,d,e,f,x;
    for(size_t i=0; i<32; ++i){
        clamped[i]=scalar[i];
    }
    clamped[0] &=0xF8;
    clamped[31] = (clamped[31] & 0x7F) | 0x40;
    x.from_bytes(point_u);
    for(size_t i=0; i<16; ++i){
        b.limbs[i]=x.limbs[i];
        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;
        swap(a,b,bit);
        swap(c,d,bit);
        e=a+c;
        a=a-c;
        c=b+d;
        b=b-d;
        d=e*e;
        f=a*a;
        a=c*a;
        c=b*e;
        e=a+c;
        a=a-c;
        b=a*a;
        c=d-f;
        a=c*_12665;
        a=a+d;
        c=c*a;
        a=d*f;
        d=b*x;
        b=e*e;
        swap(a,b,bit);
        swap(c,d,bit);
    }
    c=c.invert();
    a=a*c;
    pack(out,a);
    return true;
}


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(32, 0);
    base_point[0] = 9;

    std::vector<uint8_t> base_point;
    base_point.resize(32);
    std::fill(base_point.begin(),base_point.end(),9);
    // Delegate to the main scalar multiplication function
    return scalarmult_curve25519(out, scalar, base_point);
}
+5 −1
Original line number Diff line number Diff line
@@ -5,11 +5,13 @@
#include <vector>
#include <algorithm>

#define ALIMBS 16

namespace netplus {

class FieldElement {
public:
    std::array<int64_t, 10> limbs;
    std::array<int64_t, 16> limbs;

    FieldElement();
    FieldElement(int v);
@@ -25,11 +27,13 @@ public:

    bool operator==(const FieldElement& other) const;

    void carry25519();
    void zero();
    void one();
    FieldElement invert() const;

    std::vector<uint8_t> to_bytes() const;
    void from_bytes(std::vector<uint8_t> in);
};

FieldElement operator*(int32_t scalar, const FieldElement& fe);
+39 −43
Original line number Diff line number Diff line
@@ -92,7 +92,6 @@ int main() {
    // (Section 5.2, test with iterated scalarmult)
    // ---------------------------------------------------------


    std::cout << "Running 1000-iteration KAT...\n";

    std::vector<uint8_t> k(32, 0);
@@ -106,16 +105,15 @@ int main() {
    for (int i = 0; i < 1000; ++i) {
        std::vector<uint8_t> r;
        std::vector<uint8_t> prev_k = k;
/*
        std::cout << "KAT loop: k: "; print_hex(k); std::cout << "\n";
        std::cout << "KAT loop: u: "; print_hex(u); std::cout << "\n";
        std::cout << "Before scalarmult_curve25519: k = "; print_hex(k); std::cout << "\n";
        std::cout << "Before scalarmult_curve25519: u = "; print_hex(u); std::cout << "\n";
*/

        // Perform scalar multiplication
        netplus::scalarmult_curve25519(r, k, u);

        // Update u to the previous value of k for the next iteration
        u = prev_k;
        k = r;

        // Reset size to ensure it stays at 32 bytes
        k.resize(32, 0);
        u.resize(32, 0);

@@ -140,8 +138,6 @@ int main() {
        0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24
    };

    // RFC says final k and u should match these

    if (!equal32(k, kat_k)) {
        ok = 0;
        std::cerr << "FAIL: KAT 1000 - final k mismatch\n";