public static int curve25519_sign(ISha512 sha512provider, byte[] signature_out, byte[] curve25519_privkey, byte[] msg, int msg_len, byte[] random) { Ge_p3 ed_pubkey_point = new Ge_p3(); /* Ed25519 pubkey point */ byte[] ed_pubkey = new byte[32]; /* Ed25519 encoded pubkey */ byte[] sigbuf = new byte[msg_len + 128]; /* working buffer */ byte sign_bit = 0; /* Convert the Curve25519 privkey to an Ed25519 public key */ Ge_scalarmult_base.ge_scalarmult_base(ed_pubkey_point, curve25519_privkey); Ge_p3_tobytes.ge_p3_tobytes(ed_pubkey, ed_pubkey_point); sign_bit = (byte)(ed_pubkey[31] & 0x80); /* Perform an Ed25519 signature with explicit private key */ sign_modified.crypto_sign_modified(sha512provider, sigbuf, msg, msg_len, curve25519_privkey, ed_pubkey, random); Array.Copy(sigbuf, 0, signature_out, 0, 64); /* Encode the sign bit into signature (in unused high bit of S) */ signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ signature_out[63] |= sign_bit; return(0); }
public static int vxed25519_verify(ISha512 sha512provider, byte[] vrf_out, byte[] signature, byte[] curve25519_pubkey, byte[] msg, int msg_len) { int[] u = new int[10]; int[] y = new int[10]; byte[] ed_pubkey = new byte[32]; byte[] strict = new byte[32]; byte[] verifybuf = new byte[crypto_additions.MAX_MSG_LEN + 160]; /* working buffer */ byte[] verifybuf2 = new byte[crypto_additions.MAX_MSG_LEN + 160]; /* working buffer #2 ?? !!! */ Ge_p3 Bv = new Ge_p3(); if (msg_len > crypto_additions.MAX_MSG_LEN) { return(-1); } /* Convert the Curve25519 public key into an Ed25519 public key. * * y = (u - 1) / (u + 1) * * NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp */ Fe_frombytes.fe_frombytes(u, curve25519_pubkey); Fe_tobytes.fe_tobytes(strict, u); if (Crypto_verify_32.crypto_verify_32(strict, curve25519_pubkey) != 0) { return(0); } Fe_montx_to_edy.fe_montx_to_edy(y, u); Fe_tobytes.fe_tobytes(ed_pubkey, y); Elligator.calculate_Bv(sha512provider, Bv, verifybuf, ed_pubkey, msg, msg_len); Array.Copy(signature, 0, verifybuf, 0, 96); Array.Copy(msg, 0, verifybuf, 96, msg_len); /* Then perform a signature verification, return 0 on success */ /* The below call has a strange API: */ /* verifybuf = V || h || s || message */ /* verifybuf2 = used as buffer, gets the VRF output if success */ if (Vopen_modified.crypto_vsign_open_modified(sha512provider, verifybuf2, verifybuf, 96 + msg_len, ed_pubkey, Bv) == 0) { Array.Copy(verifybuf2, 0, vrf_out, 0, 32); return(0); } else { //memset(vrf_out, 0, 32); return(-1); } }
//CONVERT #include <string.h> //CONVERT #include "crypto_sign.h" //CONVERT #include "crypto_hash_sha512.h" //CONVERT #include "crypto_verify_32.h" //CONVERT #include "ge.h" //CONVERT #include "sc.h" public static int crypto_sign_open( ISha512 sha512provider, byte[] m, long mlen, byte[] sm, long smlen, byte[] pk ) { byte[] pkcopy = new byte[32]; byte[] rcopy = new byte[32]; byte[] scopy = new byte[32]; byte[] h = new byte[64]; byte[] rcheck = new byte[32]; Ge_p3 A = new Ge_p3(); Ge_p2 R = new Ge_p2(); if (smlen < 64) { return(-1); } if ((sm[63] & 224) != 0) { return(-1); } if (Ge_frombytes.ge_frombytes_negate_vartime(A, pk) != 0) { return(-1); } byte[] pubkeyhash = new byte[64]; sha512provider.calculateDigest(pubkeyhash, pk, 32); Array.Copy(pk, 0, pkcopy, 0, 32); Array.Copy(sm, 0, rcopy, 0, 32); Array.Copy(sm, 32, scopy, 0, 32); Array.Copy(sm, 0, m, 0, (int)smlen); Array.Copy(pkcopy, 0, m, 32, 32); sha512provider.calculateDigest(h, m, smlen); Sc_reduce.sc_reduce(h); Ge_double_scalarmult.ge_double_scalarmult_vartime(R, h, A, scopy); Ge_tobytes.ge_tobytes(rcheck, R); if (Crypto_verify_32.crypto_verify_32(rcheck, rcopy) == 0) { Array.Copy(m, 64, m, 0, (int)(smlen - 64)); //memset(m + smlen - 64,0,64); return(0); } //badsig: //memset(m,0,smlen); return(-1); }
public static int curve25519_verify(ISha512 sha512provider, byte[] signature, byte[] curve25519_pubkey, byte[] msg, int msg_len) { int[] mont_x = new int[10]; int[] mont_x_minus_one = new int[10]; int[] mont_x_plus_one = new int[10]; int[] inv_mont_x_plus_one = new int[10]; int[] one = new int[10]; int[] ed_y = new int[10]; byte[] ed_pubkey = new byte[32]; long some_retval = 0; byte[] verifybuf = new byte[msg_len + 64]; /* working buffer */ byte[] verifybuf2 = new byte[msg_len + 64]; /* working buffer #2 */ /* Convert the Curve25519 public key into an Ed25519 public key. In * particular, convert Curve25519's "montgomery" x-coordinate into an * Ed25519 "edwards" y-coordinate: * * ed_y = (mont_x - 1) / (mont_x + 1) * * NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp * * Then move the sign bit into the pubkey from the signature. */ Fe_frombytes.fe_frombytes(mont_x, curve25519_pubkey); Fe_1.fe_1(one); Fe_sub.fe_sub(mont_x_minus_one, mont_x, one); Fe_add.fe_add(mont_x_plus_one, mont_x, one); Fe_invert.fe_invert(inv_mont_x_plus_one, mont_x_plus_one); Fe_mul.fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one); Fe_tobytes.fe_tobytes(ed_pubkey, ed_y); /* Copy the sign bit, and remove it from signature */ ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ ed_pubkey[31] |= (byte)(signature[63] & 0x80); Array.Copy(signature, 0, verifybuf, 0, 64); verifybuf[63] &= 0x7F; Array.Copy(msg, 0, verifybuf, 64, (int)msg_len); /* Then perform a normal Ed25519 verification, return 0 on success */ /* The below call has a strange API: */ /* verifybuf = R || S || message */ /* verifybuf2 = java to next call gets a copy of verifybuf, S gets * replaced with pubkey for hashing, then the whole thing gets zeroized * (if bad sig), or contains a copy of msg (good sig) */ return(Open.crypto_sign_open(sha512provider, verifybuf2, some_retval, verifybuf, 64 + msg_len, ed_pubkey)); }
public static void calculate_Bv_and_V(ISha512 sha512provider, Ge_p3 Bv, byte[] V, byte[] buf, byte[] a, byte[] A, byte[] msg, int msg_len) { Ge_p3 p3 = new Ge_p3(); calculate_Bv(sha512provider, Bv, buf, A, msg, msg_len); Ge_scalarmult.ge_scalarmult(p3, a, Bv); Ge_p3_tobytes.ge_p3_tobytes(V, p3); }
public static int uxed25519_sign(ISha512 sha512provider, byte[] signature_out, byte[] curve25519_privkey, byte[] msg, int msg_len, byte[] random) { // just return -1 as this shouldn't be used return(-1); byte[] a = new byte[32]; byte[] aneg = new byte[32]; byte[] A = new byte[32]; Ge_p3 Bu = new Ge_p3(); Ge_p3 ed_pubkey_point = new Ge_p3(); byte[] sigbuf = new byte[crypto_additions.MAX_MSG_LEN + 160]; /* working buffer */ byte sign_bit = 0; if (msg_len > crypto_additions.MAX_MSG_LEN) { //memset(signature_out, 0, 96); return(-1); } /* Convert the Curve25519 privkey to an Ed25519 public key */ Ge_scalarmult_base.ge_scalarmult_base(ed_pubkey_point, curve25519_privkey); Ge_p3_tobytes.ge_p3_tobytes(A, ed_pubkey_point); /* Force Edwards sign bit to zero */ sign_bit = (byte)((A[31] & 0x80) >> 7); Array.Copy(curve25519_privkey, 0, a, 0, 32); Sc_neg.sc_neg(aneg, a); Sc_cmov.sc_cmov(a, aneg, sign_bit); A[31] &= 0x7F; //Elligator.calculate_Bv_and_V(sha512provider, Bu, signature_out, sigbuf, a, msg, msg_len); /* Perform an Ed25519 signature with explicit private key */ usign_modified.crypto_usign_modified(sha512provider, sigbuf, msg, msg_len, a, A, random, Bu, signature_out /*U*/); Array.Copy(sigbuf, 0, signature_out, 32, 64); Zeroize.zeroize(a, 32); return(0); }
//CONVERT #include <string.h> //CONVERT #include "crypto_sign.h" //CONVERT #include "crypto_hash_sha512.h" //CONVERT #include "ge.h" //CONVERT #include "sc.h" //CONVERT #include "zeroize.h" /* NEW: Compare to pristine crypto_sign() * Uses explicit private key for nonce derivation and as scalar, * instead of deriving both from a master key. */ public static int crypto_sign_modified( ISha512 sha512provider, byte[] sm, byte[] m, long mlen, byte[] sk, byte[] pk, byte[] random ) { byte[] nonce = new byte[64]; byte[] hram = new byte[64]; Ge_p3 R = new Ge_p3(); int count = 0; Array.Copy(m, 0, sm, 64, (int)mlen); Array.Copy(sk, 0, sm, 32, 32); /* NEW : add prefix to separate hash uses - see .h */ sm[0] = (byte)0xFE; for (count = 1; count < 32; count++) { sm[count] = (byte)0xFF; } /* NEW: add suffix of random data */ Array.Copy(random, 0, sm, (int)(mlen + 64), 64); sha512provider.calculateDigest(nonce, sm, mlen + 128); Array.Copy(pk, 0, sm, 32, 32); Sc_reduce.sc_reduce(nonce); Ge_scalarmult_base.ge_scalarmult_base(R, nonce); Ge_p3_tobytes.ge_p3_tobytes(sm, R); sha512provider.calculateDigest(hram, sm, mlen + 64); Sc_reduce.sc_reduce(hram); byte[] S = new byte[32]; Sc_muladd.sc_muladd(S, hram, sk, nonce); /* NEW: Use privkey directly */ Array.Copy(S, 0, sm, 32, 32); /* Erase any traces of private scalar or * nonce left in the stack from sc_muladd */ //zeroize_stack(); Zeroize.zeroize(nonce, 64); return(0); }
public static int uxed25519_verify(ISha512 sha512provider, byte[] signature, byte[] curve25519_pubkey, byte[] msg, int msg_len) { // just return -1 as this shouldn't be used return(-1); int[] u = new int[10]; int[] y = new int[10]; byte[] ed_pubkey = new byte[32]; long some_retval = 0; byte[] verifybuf = new byte[crypto_additions.MAX_MSG_LEN + 160]; /* working buffer */ byte[] verifybuf2 = new byte[crypto_additions.MAX_MSG_LEN + 160]; /* working buffer #2 ?? !!! */ Ge_p3 Bu = new Ge_p3(); if (msg_len > crypto_additions.MAX_MSG_LEN) { return(-1); } //Elligator.calculate_Bv(sha512provider, Bu, verifybuf, msg, msg_len); /* Convert the Curve25519 public key (u) into an Ed25519 public key. * * y = (u - 1) / (u + 1) * * NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp */ Fe_frombytes.fe_frombytes(u, curve25519_pubkey); Fe_montx_to_edy.fe_montx_to_edy(y, u); Fe_tobytes.fe_tobytes(ed_pubkey, y); Array.Copy(signature, 0, verifybuf, 0, 96); Array.Copy(msg, 0, verifybuf, 96, msg_len); /* Then perform a signature verification, return 0 on success */ /* The below call has a strange API: */ /* verifybuf = U || h || s || message */ /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets * replaced with pubkey for hashing, then the whole thing gets zeroized * (if bad sig), or contains a copy of msg (good sig) */ return(uopen_modified.crypto_usign_open_modified(sha512provider, verifybuf2, some_retval, verifybuf, 96 + msg_len, ed_pubkey, Bu)); }
public static void hash_to_point(ISha512 sha512provider, Ge_p3 p, byte[] iIn, int in_len) { byte[] hash = new byte[64]; int[] h = new int[10]; int[] u = new int[10]; byte sign_bit; Ge_p3 p3 = new Ge_p3(); sha512provider.calculateDigest(hash, iIn, in_len); /* take the high bit as Edwards sign bit */ sign_bit = (byte)(((uint)hash[31] & 0x80) >> 7); hash[31] &= 0x7F; Fe_frombytes.fe_frombytes(h, hash); elligator(u, h); Ge_montx_to_p3.ge_montx_to_p3(p3, u, sign_bit); Ge_scalarmult_cofactor.ge_scalarmult_cofactor(p, p3); }
public static void calculate_Bv(ISha512 sha512provider, Ge_p3 Bv, byte[] buf, byte[] A, byte[] msg, int msg_len) { int count; /* Calculate SHA512(label(2) || A || msg) */ buf[0] = 0xFD; for (count = 1; count < 32; count++) { buf[count] = 0xFF; } Array.Copy(A, 0, buf, 32, 32); Array.Copy(msg, 0, buf, 64, msg_len); hash_to_point(sha512provider, Bv, buf, 64 + msg_len); }
public static int xed25519_sign(ISha512 sha512provider, byte[] signature_out, byte[] curve25519_privkey, byte[] msg, int msg_len, byte[] random) { byte[] a = new byte[32]; byte[] A = new byte[32]; byte[] aneg = new byte[32]; Ge_p3 ed_pubkey_point = new Ge_p3(); // see link below byte[] sigbuf = new byte[msg_len + 128]; /* working buffer */ byte sign_bit = 0; // this should be different but whatever // https://github.com/WhisperSystems/curve25519-java/commit/2f388f601afdac6a78a19ced2f0629da1ff9800f#diff-6e488e4e28814b3fa524b6781fcaf912R19 //if (msg_len > crypto_additions.MAX_MSG_LEN) //{ // //memset(signature_out, 0, 64); // return -1; //} /* Convert the Curve25519 privkey to an Ed25519 public key */ Ge_scalarmult_base.ge_scalarmult_base(ed_pubkey_point, curve25519_privkey); Ge_p3_tobytes.ge_p3_tobytes(A, ed_pubkey_point); /* Force Edwards sign bit to zero */ sign_bit = (byte)((A[31] & 0x80) >> 7); Array.Copy(curve25519_privkey, 0, a, 0, 32); Sc_neg.sc_neg(aneg, a); Sc_cmov.sc_cmov(a, aneg, sign_bit); A[31] &= 0x7F; /* Perform an Ed25519 signature with explicit private key */ sign_modified.crypto_sign_modified(sha512provider, sigbuf, msg, msg_len, a, A, random); Array.Copy(sigbuf, 0, signature_out, 0, 64); Zeroize.zeroize(a, 32); Zeroize.zeroize(aneg, 32); return(0); }
public static int curve25519_verify(ISha512 sha512provider, byte[] signature, byte[] curve25519_pubkey, byte[] msg, int msg_len) { int[] u = new int[10]; int[] y = new int[10]; byte[] ed_pubkey = new byte[32]; byte[] verifybuf = new byte[msg_len + 64]; /* working buffer */ byte[] verifybuf2 = new byte[msg_len + 64]; /* working buffer #2 */ /* Convert the Curve25519 public key into an Ed25519 public key. In * particular, convert Curve25519's "montgomery" x-coordinate (u) into an * Ed25519 "edwards" y-coordinate: * * y = (u - 1) / (u + 1) * * NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp * * Then move the sign bit into the pubkey from the signature. */ Fe_frombytes.fe_frombytes(u, curve25519_pubkey); Fe_montx_to_edy.fe_montx_to_edy(y, u); Fe_tobytes.fe_tobytes(ed_pubkey, y); /* Copy the sign bit, and remove it from signature */ ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ ed_pubkey[31] |= (byte)(signature[63] & 0x80); Array.Copy(signature, 0, verifybuf, 0, 64); verifybuf[63] &= 0x7F; Array.Copy(msg, 0, verifybuf, 64, (int)msg_len); /* Then perform a normal Ed25519 verification, return 0 on success */ /* The below call has a strange API: */ /* verifybuf = R || S || message */ /* verifybuf2 = java to next call gets a copy of verifybuf, S gets * replaced with pubkey for hashing, then the whole thing gets zeroized * (if bad sig), or contains a copy of msg (good sig) */ return(open_modified.crypto_sign_open_modified(sha512provider, verifybuf2, verifybuf, 64 + msg_len, ed_pubkey)); }
public static int xed25519_verify(ISha512 sha512provider, byte[] signature, byte[] curve25519_pubkey, byte[] msg, int msg_len) { int[] u = new int[10]; int[] y = new int[10]; byte[] ed_pubkey = new byte[32]; byte[] strict = new byte[32]; byte[] verifybuf = new byte[crypto_additions.MAX_MSG_LEN + 64]; /* working buffer */ byte[] verifybuf2 = new byte[crypto_additions.MAX_MSG_LEN + 64]; /* working buffer #2 */ if (msg_len > crypto_additions.MAX_MSG_LEN) { return(-1); } /* Convert the Curve25519 public key into an Ed25519 public key. * * y = (u - 1) / (u + 1) * * NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp */ Fe_frombytes.fe_frombytes(u, curve25519_pubkey); Fe_tobytes.fe_tobytes(strict, u); if (Crypto_verify_32.crypto_verify_32(strict, curve25519_pubkey) != 0) { return(0); } Fe_montx_to_edy.fe_montx_to_edy(y, u); Fe_tobytes.fe_tobytes(ed_pubkey, y); Array.Copy(signature, 0, verifybuf, 0, 64); Array.Copy(msg, 0, verifybuf, 64, msg_len); /* Then perform a normal Ed25519 verification, return 0 on success */ /* The below call has a strange API: */ /* verifybuf = R || S || message */ /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets * replaced with pubkey for hashing*/ return(open_modified.crypto_sign_open_modified(sha512provider, verifybuf2, verifybuf, 64 + msg_len, ed_pubkey)); }
public BaseCSharpCurve25519Provider() { sha512provider = null; secureRandomProvider = null; }
public static int crypto_vsign_open_modified(ISha512 sha512provider, byte[] m, byte[] sm, long smlen, byte[] pk, Ge_p3 Bv) { Ge_p3 Vneg = new Ge_p3(); Ge_p3 V = new Ge_p3(); Ge_p3 Aneg = new Ge_p3(); Ge_p3 A = new Ge_p3(); Ge_p3 c_V = new Ge_p3(); Ge_p3 c_A = new Ge_p3(); Ge_p3 h_Vneg = new Ge_p3(); Ge_p3 s_Bv = new Ge_p3(); byte[] h = new byte[32]; byte[] s = new byte[32]; Ge_p2 R = new Ge_p2(); byte[] hcheck = new byte[64]; byte[] vrf_output = new byte[64]; int count; if (smlen < 96) { return(-1); } if ((sm[63] & 224) != 0) /* strict parsing of h */ { return(-1); } if ((sm[95] & 224) != 0) /* strict parsing of s */ { return(-1); } /* Load -A */ if (Ge_frombytes.ge_frombytes_negate_vartime(Aneg, pk) != 0) { return(-1); } /* Load -V, h, s */ if (Ge_frombytes.ge_frombytes_negate_vartime(Vneg, sm) != 0) { return(-1); } Array.Copy(sm, 32, h, 0, 32); Array.Copy(sm, 64, s, 0, 32); if ((h[31] & 224) != 0) /* strict parsing of h */ { return(-1); } if ((s[31] & 224) != 0) /* strict parsing of s */ { return(-1); } Ge_neg.ge_neg(A, Aneg); Ge_neg.ge_neg(V, Vneg); Ge_scalarmult_cofactor.ge_scalarmult_cofactor(c_A, A); Ge_scalarmult_cofactor.ge_scalarmult_cofactor(c_V, V); if (Ge_isneutral.ge_isneutral(c_A) != 0 || Ge_isneutral.ge_isneutral(c_V) != 0 || Ge_isneutral.ge_isneutral(Bv) != 0) { return(-1); } // R = (s*B) + (h * -A)) Ge_double_scalarmult.ge_double_scalarmult_vartime(R, h, Aneg, s); // s * Bv Ge_scalarmult.ge_scalarmult(s_Bv, s, Bv); // h * -V Ge_scalarmult.ge_scalarmult(h_Vneg, h, Vneg); // Rv = (sc * Bv) + (hc * (-V)) Ge_p1p1 Rp1p1 = new Ge_p1p1(); Ge_p3 Rv = new Ge_p3(); Ge_cached h_Vnegcached = new Ge_cached(); Ge_p3_to_cached.ge_p3_to_cached(h_Vnegcached, h_Vneg); Ge_add.ge_add(Rp1p1, s_Bv, h_Vnegcached); Ge_p1p1_to_p3.ge_p1p1_to_p3(Rv, Rp1p1); // Check h == SHA512(label(4) || A || V || R || Rv || M) m[0] = 0xFB; // label 4 for (count = 1; count < 32; count++) { m[count] = 0xFF; } Array.Copy(pk, 0, m, 32, 32); byte[] M = new byte[32]; Array.Copy(m, 64, M, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(M, V); Array.Copy(M, 0, m, 64, 32); byte[] M2 = new byte[32]; Array.Copy(m, 96, M2, 0, 32); Ge_tobytes.ge_tobytes(M2, R); Array.Copy(M2, 0, m, 96, 32); byte[] M3 = new byte[32]; Array.Copy(m, 128, M3, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(M3, Rv); Array.Copy(M3, 0, m, 128, 32); Array.Copy(sm, 96, m, 160, (int)smlen - 96); sha512provider.calculateDigest(hcheck, m, smlen + 64); Sc_reduce.sc_reduce(hcheck); if (Crypto_verify_32.crypto_verify_32(hcheck, h) == 0) { byte[] M4 = new byte[32]; Array.Copy(m, 32, M4, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(M4, c_V); Array.Copy(M4, 0, m, 32, 32); m[0] = 0xFA; // label 5 sha512provider.calculateDigest(vrf_output, m, 64); Array.Copy(vrf_output, 0, m, 0, 32); return(0); } //badsig //memset(m, 0, 32); return(-1); }
public static int crypto_vsign_modified(ISha512 sha512provider, byte[] sm, byte[] M, int Mlen, byte[] a, byte[] A, byte[] random, Ge_p3 Bv, byte[] V) { byte[] r = new byte[64]; byte[] h = new byte[64]; Ge_p3 R = new Ge_p3(); Ge_p3 Rv = new Ge_p3(); int count = 0; /* r = SHA512(label(3) || a || V || random(64)) */ sm[0] = 0xFC; for (count = 1; count < 32; count++) { sm[count] = 0xFF; } Array.Copy(a, 0, sm, 32, 32); /* Use privkey directly for nonce derivation */ Array.Copy(V, 0, sm, 64, 32); Array.Copy(random, 0, sm, 96, 64); /* Add suffix of random data */ sha512provider.calculateDigest(r, sm, 160); Sc_reduce.sc_reduce(r); Ge_scalarmult_base.ge_scalarmult_base(R, r); Ge_scalarmult.ge_scalarmult(Rv, r, Bv); /* h = SHA512(label(4) || A || V || R || Rv || M) */ sm[0] = 0xFB; Array.Copy(A, 0, sm, 32, 32); Array.Copy(V, 0, sm, 64, 32); byte[] R1 = new byte[32]; Array.Copy(sm, 96, R1, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(R1, R); Array.Copy(R1, 0, sm, 96, 32); byte[] R2 = new byte[32]; Array.Copy(sm, 128, R2, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(R2, Rv); Array.Copy(R2, 0, sm, 128, 32); Array.Copy(M, 0, sm, 160, Mlen); sha512provider.calculateDigest(h, sm, Mlen + 160); Sc_reduce.sc_reduce(h); Array.Copy(h, 0, sm, 0, 32); byte[] S = new byte[32]; Array.Copy(sm, 32, S, 0, 32); Sc_muladd.sc_muladd(S, h, a, r); Array.Copy(S, 0, sm, 32, 32); /* Erase any traces of private scalar or * nonce left in stack from sc_muladd. */ //zeroize_stack(); Zeroize.zeroize(r, 64); return(0); }
protected BaseCSharpCurve25519Provider(ISha512 sha512provider, SecureRandomProvider secureRandomProvider) { this.sha512provider = sha512provider; this.secureRandomProvider = secureRandomProvider; }
public override void setSha512Provider(ISha512 sha512Provider) { this.sha512provider = sha512Provider; }
public CSharpCurve25519Provider(ISha512 sha, SecureRandomProvider random) : base(sha, random) { }
public DonnaCSharpCurve25519Provider(ISha512 sha512provider, SecureRandomProvider secureRandomProvider) : base(sha512provider, secureRandomProvider) { }
public abstract void setSha512Provider(ISha512 provider);
public static int crypto_usign_open_modified(ISha512 sha512provider, byte[] m, long mlen, byte[] sm, long smlen, byte[] pk, Ge_p3 Bu) { Ge_p3 U = new Ge_p3(); byte[] h = new byte[64]; byte[] s = new byte[64]; byte[] strict = new byte[64]; Ge_p3 A = new Ge_p3(); Ge_p2 R = new Ge_p2(); byte[] hcheck = new byte[64]; int count; if (smlen < 96) { return(-1); } if ((sm[63] & 224) != 0) /* strict parsing of h */ { return(-1); } if ((sm[95] & 224) != 0) /* strict parsing of s */ { return(-1); } /* Load -A */ if (Ge_frombytes.ge_frombytes_negate_vartime(A, pk) != 0) { return(-1); } /* Load -U, h, s */ Ge_frombytes.ge_frombytes_negate_vartime(U, sm); Array.Copy(sm, 32, h, 0, 32); Array.Copy(sm, 64, s, 0, 32); /* Insist that s and h are reduced scalars (strict parsing) */ Array.Copy(h, 0, strict, 0, 64); Sc_reduce.sc_reduce(strict); if (!Arrays.isEqual(strict, h, 32)) { return(-1); } Array.Copy(s, 0, strict, 0, 64); Sc_reduce.sc_reduce(strict); if (!Arrays.isEqual(strict, s, 32)) { return(-1); } /* Reject U (actually -U) if small order */ if (Ge_is_small_order.ge_is_small_order(U) != 0) { return(-1); } // R = sB + h(-A) Ge_double_scalarmult.ge_double_scalarmult_vartime(R, h, A, s); // Ru = sBu + h(-U) Ge_p3 sBu = new Ge_p3(); Ge_p3 hU = new Ge_p3(); // sBu Ge_scalarmult.ge_scalarmult(sBu, s, Bu); // h(-U) Ge_scalarmult.ge_scalarmult(hU, h, U); // Ru = sBu + h(-U) Ge_p1p1 Rp1p1 = new Ge_p1p1(); Ge_p3 Ru = new Ge_p3(); Ge_cached hUcached = new Ge_cached(); Ge_p3_to_cached.ge_p3_to_cached(hUcached, hU); Ge_add.ge_add(Rp1p1, sBu, hUcached); Ge_p1p1_to_p3.ge_p1p1_to_p3(Ru, Rp1p1); // Check h == SHA512(label(4) || A || U || R || Ru || M) m[0] = 0xFB; for (count = 1; count < 32; count++) { m[count] = 0xFF; } Array.Copy(pk, 0, m, 32, 32); /* undo the negation for U */ Fe_neg.fe_neg(U.X, U.X); Fe_neg.fe_neg(U.T, U.T); byte[] M = new byte[32]; Array.Copy(m, 64, M, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(M, U); Array.Copy(M, 0, m, 64, 32); byte[] M2 = new byte[32]; Array.Copy(m, 96, M2, 0, 32); Ge_tobytes.ge_tobytes(M2, R); Array.Copy(M2, 0, m, 96, 32); byte[] M3 = new byte[32]; Array.Copy(m, 128, M3, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(M3, Ru); Array.Copy(M3, 0, m, 128, 32); Array.Copy(sm, 96, m, 160, (int)smlen - 96); sha512provider.calculateDigest(hcheck, m, smlen + 64); Sc_reduce.sc_reduce(hcheck); if (Crypto_verify_32.crypto_verify_32(hcheck, h) == 0) { Array.Copy(m, 64, m, 0, (int)smlen - 64); //memset(m + smlen - 64,0,64); //*mlen = smlen - 64; return(0); } //badsig: //*mlen = -1; //memset(m,0,smlen); return(-1); }