public static void ReadIntegers() { byte[] derEncoded = { /* SEQUENCE */ 0x30, 23, /* INTEGER(0) */ 0x02, 0x01, 0x00, /* INTEGER(256) */ 0x02, 0x02, 0x01, 0x00, /* INTEGER(-1) */ 0x02, 0x01, 0xFF, /* Big integer */ 0x02, 0x0B, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, }; DerSequenceReader reader = new DerSequenceReader(derEncoded); Assert.True(reader.HasData); Assert.Equal(23, reader.ContentLength); int first = reader.ReadInteger(); Assert.Equal(0, first); int second = reader.ReadInteger(); Assert.Equal(256, second); int third = reader.ReadInteger(); Assert.Equal(-1, third); // Reader reads Big-Endian, BigInteger reads Little-Endian byte[] fourthBytes = reader.ReadIntegerBytes(); Array.Reverse(fourthBytes); BigInteger fourth = new BigInteger(fourthBytes); Assert.Equal(BigInteger.Parse("3645759592820458633497613"), fourth); // And... done. Assert.False(reader.HasData); }
public static void ReadIntegers() { byte[] derEncoded = { /* SEQUENCE */ 0x30, 23, /* INTEGER(0) */ 0x02, 0x01, 0x00, /* INTEGER(256) */ 0x02, 0x02, 0x01, 0x00, /* INTEGER(-1) */ 0x02, 0x01, 0xFF, /* Big integer */ 0x02, 0x0B, 0x03, 0x04,0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, }; DerSequenceReader reader = new DerSequenceReader(derEncoded); Assert.True(reader.HasData); Assert.Equal(23, reader.ContentLength); int first = reader.ReadInteger(); Assert.Equal(0, first); int second = reader.ReadInteger(); Assert.Equal(256, second); int third = reader.ReadInteger(); Assert.Equal(-1, third); // Reader reads Big-Endian, BigInteger reads Little-Endian byte[] fourthBytes = reader.ReadIntegerBytes(); Array.Reverse(fourthBytes); BigInteger fourth = new BigInteger(fourthBytes); Assert.Equal(BigInteger.Parse("3645759592820458633497613"), fourth); // And... done. Assert.False(reader.HasData); }
private static void ReadCertPolicyConstraintsExtension(X509Extension extension, CertificatePolicy policy) { DerSequenceReader reader = new DerSequenceReader(extension.RawData); while (reader.HasData) { // Policy Constraints context specific tag values are defined in RFC 3280 4.2.1.12, // and restated (unchanged) in RFC 5280 4.2.1.11. switch (reader.PeekTag()) { case DerSequenceReader.ContextSpecificTagFlag | 0: policy.RequireExplicitPolicyDepth = reader.ReadInteger(); break; case DerSequenceReader.ContextSpecificTagFlag | 1: policy.InhibitMappingDepth = reader.ReadInteger(); break; default: if (extension.Critical) { // If an unknown value is read, but we're marked as critical, // then we don't know what we're doing and MUST fail validation // (RFC 3280). // If it isn't critical then it means we're allowed to be ignorant // of data defined more recently than we understand. throw new CryptographicException(); } break; } } }
private static DerSequenceReader ReadEncryptedPkcs8Blob(string passphrase, DerSequenceReader reader) { // EncryptedPrivateKeyInfo::= SEQUENCE { // encryptionAlgorithm EncryptionAlgorithmIdentifier, // encryptedData EncryptedData } // // EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier // // EncryptedData ::= OCTET STRING DerSequenceReader algorithmIdentifier = reader.ReadSequence(); string algorithmOid = algorithmIdentifier.ReadOidAsString(); // PBES2 (Password-Based Encryption Scheme 2) if (algorithmOid != OidPbes2) { Debug.Fail($"Expected PBES2 ({OidPbes2}), got {algorithmOid}"); throw new CryptographicException(); } // PBES2-params ::= SEQUENCE { // keyDerivationFunc AlgorithmIdentifier { { PBES2 - KDFs} }, // encryptionScheme AlgorithmIdentifier { { PBES2 - Encs} } // } DerSequenceReader pbes2Params = algorithmIdentifier.ReadSequence(); algorithmIdentifier = pbes2Params.ReadSequence(); string kdfOid = algorithmIdentifier.ReadOidAsString(); // PBKDF2 (Password-Based Key Derivation Function 2) if (kdfOid != OidPbkdf2) { Debug.Fail($"Expected PBKDF2 ({OidPbkdf2}), got {kdfOid}"); throw new CryptographicException(); } // PBKDF2-params ::= SEQUENCE { // salt CHOICE { // specified OCTET STRING, // otherSource AlgorithmIdentifier { { PBKDF2 - SaltSources} } // }, // iterationCount INTEGER (1..MAX), // keyLength INTEGER(1..MAX) OPTIONAL, // prf AlgorithmIdentifier { { PBKDF2 - PRFs} } DEFAULT algid - hmacWithSHA1 // } DerSequenceReader pbkdf2Params = algorithmIdentifier.ReadSequence(); byte[] salt = pbkdf2Params.ReadOctetString(); int iterCount = pbkdf2Params.ReadInteger(); int keySize = -1; if (pbkdf2Params.HasData && pbkdf2Params.PeekTag() == (byte)DerSequenceReader.DerTag.Integer) { keySize = pbkdf2Params.ReadInteger(); } if (pbkdf2Params.HasData) { string prfOid = pbkdf2Params.ReadOidAsString(); // SHA-1 is the only hash algorithm our PBKDF2 supports. if (prfOid != OidSha1) { Debug.Fail($"Expected SHA1 ({OidSha1}), got {prfOid}"); throw new CryptographicException(); } } DerSequenceReader encryptionScheme = pbes2Params.ReadSequence(); string cipherOid = encryptionScheme.ReadOidAsString(); // DES-EDE3-CBC (TripleDES in CBC mode) if (cipherOid != OidTripleDesCbc) { Debug.Fail($"Expected DES-EDE3-CBC ({OidTripleDesCbc}), got {cipherOid}"); throw new CryptographicException(); } byte[] decrypted; using (TripleDES des3 = TripleDES.Create()) { if (keySize == -1) { foreach (KeySizes keySizes in des3.LegalKeySizes) { keySize = Math.Max(keySize, keySizes.MaxSize); } } byte[] iv = encryptionScheme.ReadOctetString(); using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, iterCount)) using (ICryptoTransform decryptor = des3.CreateDecryptor(pbkdf2.GetBytes(keySize / 8), iv)) { byte[] encrypted = reader.ReadOctetString(); decrypted = decryptor.TransformFinalBlock(encrypted, 0, encrypted.Length); } } DerSequenceReader pkcs8Reader = new DerSequenceReader(decrypted); return(pkcs8Reader); }