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 void curve25519_keygen(byte[] curve25519_pubkey_out, byte[] curve25519_privkey_in) { Ge_p3 ed = new Ge_p3(); /* Ed25519 pubkey point */ int[] ed_y = new int[10]; int[] ed_y_plus_one = new int[10]; int[] one_minus_ed_y = new int[10]; int[] inv_one_minus_ed_y = new int[10]; int[] mont_x = new int[10]; /* Perform a fixed-base multiplication of the Edwards base point, * (which is efficient due to precalculated tables), then convert * to the Curve25519 montgomery-format public key. In particular, * convert Curve25519's "montgomery" x-coordinate into an Ed25519 * "edwards" y-coordinate: * * mont_x = (ed_y + 1) / (1 - ed_y) * * with projective coordinates: * * mont_x = (ed_y + ed_z) / (ed_z - ed_y) * * NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp */ Ge_scalarmult_base.ge_scalarmult_base(ed, curve25519_privkey_in); Fe_add.fe_add(ed_y_plus_one, ed.Y, ed.Z); Fe_sub.fe_sub(one_minus_ed_y, ed.Z, ed.Y); Fe_invert.fe_invert(inv_one_minus_ed_y, one_minus_ed_y); Fe_mul.fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y); Fe_tobytes.fe_tobytes(curve25519_pubkey_out, mont_x); }
//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_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); }
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 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); }