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);
        }
Beispiel #3
0
        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);
        }