Pkcs1RsaPrivateKey.decode constructor

Pkcs1RsaPrivateKey.decode(
  1. Uint8List data,
  2. PvtTextSource? source
)

Decode from a sequence of bytes.

Implementation

Pkcs1RsaPrivateKey.decode(Uint8List data, this.source) {
  String msg;

  try {
    List<ASN1Object> objects;

    try {
      objects = _asn1parseAll(data);
    } on ASN1Exception catch (e) {
      throw _Pkcs1Msg('ASN.1 encoding bad: ${e.message}');
    } catch (e) {
      throw _Pkcs1Msg('ASN.1 encoding bad: $e');
    }

    if (objects.length != 1) {
      throw _Pkcs1Msg('ASN.1 encoding has an incorrect number of objects'
          ' (expecting 1, got ${objects.length})');
    }

    final topSequence = objects.first;
    if (topSequence is ASN1Sequence) {
      const _numberOfIntegers = 9;

      if (topSequence.elements.length != _numberOfIntegers &&
          topSequence.elements.length != _numberOfIntegers + 1) {
        final expecting = '$_numberOfIntegers or ${_numberOfIntegers + 1}';
        throw _Pkcs1Msg('ASN.1 sequence has wrong length'
            ' (expecting $expecting, got ${topSequence.elements.length})');
      }

      // Check the mandatory objects in the sequence are ASN.1 Integers

      final values = <BigInt>[];

      for (int x = 0; x < _numberOfIntegers; x++) {
        final n = topSequence.elements[x];
        if (n is ASN1Integer) {
          values.add(n.valueAsBigInteger);
        } else {
          throw _Pkcs1Msg('ASN.1 sequence item $x is not an ASN.1 Integer');
        }
      }

      // Populate the members with the ASN.1 Integer values

      var i = 0;
      _version = values[i++];
      modulus = values[i++];
      _publicExponent = values[i++];
      privateExponent = values[i++];
      prime1 = values[i++];
      prime2 = values[i++];
      _exponent1 = values[i++];
      _exponent2 = values[i++];
      _coefficient = values[i++];
      assert(i == _numberOfIntegers);

      // Check the values are sane (including whether version == 0)

      final notCorrect = _isCorrect();
      if (notCorrect != null) {
        throw _Pkcs1Msg(notCorrect);
      }

      if (_numberOfIntegers < topSequence.elements.length) {
        // version=0 does not have any other objects in the sequence.
        //
        // version==1 can have an additional "otherPrimeInfos" object, but
        // this implementation currently does not support version==1.
        throw _Pkcs1Msg('ASN.1 sequence has unexpected item');
      }

      return; // success
    } else {
      throw _Pkcs1Msg('ASN.1 encoding is not a sequence');
    }
  } on _Pkcs1Msg catch (e) {
    msg = e.message;
  } catch (e) {
    msg = 'unexpected: $e';
  }

  throw KeyBad('invalid PKCS #1 private key: $msg');
}