//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); }