1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
#include "randombytes.h"
#include "cleanup.h"
#include "crypto_hash_sha512.h"
#include "crypto_verify_32.h"
#include "ge25519.h"
#include "sc25519.h"
#include "crypto_sign_ed25519.h"
int crypto_sign_ed25519_tinyssh(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long n, const unsigned char *skorig) {
long long i;
unsigned char nonce[64], hram[64], sk[64], pk[32];
ge25519 R;
/* compute secret key from seed sk = H(skorig), H = sha512 */
crypto_hash_sha512(sk, skorig, 32);
sk[0] &= 248;
sk[31] &= 63;
sk[31] |= 64;
/* copy m to sm, copy secret key and public key */
*smlen = n + 64;
for (i = 31; i >= 0; --i) pk[i ] = skorig[i + 32];
for (i = n - 1; i >= 0; --i) sm[i + 64] = m[i];
for (i = 31; i >= 0; --i) sm[i + 32] = sk[i + 32];
/* get pseudorandom nonce = H(sk2, m) */
crypto_hash_sha512(nonce, sm + 32, n + 32);
sc25519_reduce(nonce);
/* copy pk to sm */
for (i = 31; i >= 0; --i) sm[i + 32] = pk[i];
/* compute R */
ge25519_scalarmult_base(R, nonce);
ge25519_tobytes(sm, R);
/* calculate hram = H(r, a, m) */
crypto_hash_sha512(hram, sm, n + 64);
sc25519_reduce(hram);
/* compute S */
sc25519_muladd(sm + 32, hram, sk, nonce);
/* cleanup */
cleanup(nonce); cleanup(hram); cleanup(sk); cleanup(pk); cleanup(R);
return 0;
}
int crypto_sign_ed25519_tinyssh_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long n, const unsigned char *pk) {
long long i;
unsigned char pkcopy[32], rcopy[32], scopy[32], hram[64], rcheck[32];
ge25519 R, S, A;
int ret = -1;
/* check input */
if (n < 64) goto fail;
if (sm[63] & 224) goto fail;
/* unpack pk */
if (ge25519_frombytes_negate_vartime(A, pk) != 0) goto fail;
/* copy pk, r, s */
for (i = 0; i < 32; ++i) pkcopy[i] = pk[i];
for (i = 0; i < 32; ++i) rcopy[i] = sm[i];
for (i = 0; i < 32; ++i) scopy[i] = sm[i + 32];
/* copy sm to m and copy pk to m */
for (i = n - 1; i >= 0; --i) m[i] = sm[i];
for (i = 0; i < 32; ++i) m[i + 32] = pkcopy[i];
/* calculate hram = H(r, a, m) */
crypto_hash_sha512(hram, m, n);
sc25519_reduce(hram);
/* compute R */
ge25519_scalarmult(A, A, hram);
ge25519_scalarmult_base(S, scopy);
ge25519_add(R, S, A);
/* check R */
ge25519_tobytes(rcheck, R);
if (crypto_verify_32(rcheck, rcopy) != 0) goto fail;
/* copy message */
n -= 64; *mlen = n;
for (i = 0; i < n; ++i) m[i] = m[i + 64];
for (i = 0; i < 64; ++i) m[i + n] = 0;
ret = 0;
goto cleanup;
fail:
for (i = 0; i < n; ++i) m[i] = 0;
cleanup:
cleanup(pkcopy); cleanup(rcopy); cleanup(scopy);
cleanup(hram); cleanup(rcheck);
cleanup(R); cleanup(S); cleanup(A);
return ret;
}
int crypto_sign_ed25519_tinyssh_keypair(unsigned char *pk, unsigned char *sk) {
unsigned char h[64];
ge25519 A;
long long i;
randombytes(sk, 32);
crypto_hash_sha512(h, sk, 32);
h[0] &= 248;
h[31] &= 63;
h[31] |= 64;
ge25519_scalarmult_base(A, h);
ge25519_tobytes(pk, A);
for (i = 31; i >= 0; --i) sk[i + 32] = pk[i];
cleanup(h); cleanup(A);
return 0;
}
|