crypto_sign static method

int crypto_sign(
  1. Uint8List sm,
  2. int dummy,
  3. Uint8List m,
  4. int moff,
  5. int n,
  6. Uint8List sk, {
  7. bool extended = false,
})

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