crypto_sign static method
The crypto_sign interface expecting either
- a standard Ed25519 seed
- or an extended Ed25519 secret key (meaning already hashed and bits are/cleared and set).
Note: Extended interface simply means that the corresponding 64-byte long private key is already hashed and its bits are cleared/set.
The crypto_sign
function signs a message m
using the signer's secret
key sk
.
The crypto_sign
function returns the resulting signed message sm
.
The function raises an exception if
- sk (sk || pk) size is not 64 or
- sk (esk || pk) size is not 96 (extended).
Implementation
static int crypto_sign(Uint8List sm, int dummy /* *smlen not used*/,
Uint8List m, final int moff, int n, Uint8List sk,
{bool extended = false}) {
final d = Uint8List(64), h = Uint8List(64), r = Uint8List(64);
int i, j;
final x = Int32List(64);
final p = List<Int32List>.generate(4, (_) => Int32List(16));
final pk_offset = extended ? 64 : 32;
/// Added support for extended private keys (96 bytes long))
/// Assuming 64 byte-length secret keys
/// bits have already cleared and set
if (extended) {
for (i = 0; i < pk_offset; i++) {
d[i] = sk[i];
}
} else {
_crypto_hash_off(d, sk, 0, 32);
}
// when it's extended then we leave clear/set bit below only for safeness.
// As we can assume that the 64-byte length
// extended private key's bits have been already cleared and set.
// TODO: throw exception if the above assumption is not met.
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
//*smlen = n+64;
for (i = 0; i < n; i++) {
sm[64 + i] = m[i + moff];
}
for (i = 0; i < 32; i++) {
sm[32 + i] = d[32 + i];
}
_crypto_hash_off(r, sm, 32, n + 32);
_reduce(r);
_scalarbase(p, r, 0);
_pack(sm, p);
for (i = 0; i < 32; i++) {
sm[i + 32] = sk[i + pk_offset];
}
_crypto_hash_off(h, sm, 0, n + 64);
_reduce(h);
for (i = 0; i < 64; i++) {
x[i] = 0;
}
for (i = 0; i < 32; i++) {
x[i] = r[i];
}
for (i = 0; i < 32; i++) {
for (j = 0; j < 32; j++) {
x[i + j] += h[i] * d[j];
}
}
_modL(sm, 32, x);
return 0;
}