sign method

List<int> sign(
  1. RSAPrivateKey key,
  2. dynamic msg, {
  3. List<int>? salt,
})
override

Implementation

List<int> sign(RSAPrivateKey key, /* String | List<int> | BigInt */ msg,
    {List<int>? salt}) {
  int blockSize = key.blockSize;
  int emBits = key.bitSize - 1;

  List<int> msgBytes;
  if (msg is List<int>) {
    msgBytes = msg;
  } else if (msg is Iterable<int>) {
    msgBytes = msg.toList();
  } else if (msg is String) {
    msgBytes = utf8.encode(msg);
  } else if (msg is BigInt) {
    msgBytes = bigIntToBytes(msg);
  } else {
    throw Exception('invalid message type');
  }

  final mHash = hasher.convert(msgBytes).bytes;
  final hashLength = mHash.length;

  if (emBits < (8 * (hashLength + saltLength) + 9)) {
    throw Exception('emBits too small');
  }

  if (blockSize < hashLength + saltLength + 2) {
    throw Exception('encoding error. blockSize too small');
  }

  if (salt == null) {
    salt =
        List<int>.generate(saltLength, (index) => saltGenerator.nextInt(256));
  } else {
    if (salt.length != saltLength) {
      throw Exception('invalid salt. must be of length $saltLength');
    }
  }

  final mDash = <int>[
    ...List<int>.filled(8, 0),
    ...mHash,
    ...salt,
  ];

  final h = hasher.convert(mDash).bytes;

  final ps = List.filled(blockSize - saltLength - hashLength - 2, 0);

  final db = <int>[
    ...ps,
    0x01,
    ...salt,
  ];

  final dbMask = mgf.encode(blockSize - hashLength - 1, h);

  final maskedDb = ListOps.xor(db, dbMask);

  final em = Uint8List.fromList(<int>[
    ...maskedDb,
    ...h,
    0xbc,
  ]);

  int emDiff = (8 * blockSize) - (emBits);
  if (emDiff < 0) {
    throw Exception();
  } else if (emDiff > 7) {
    throw Exception();
  }
  emDiff = 8 - emDiff;

  em[0] &= (1 << emDiff) - 1;

  return key.engine.signBlock(em);
}