Example #1
0
        public void SnPublicKeyIsReturnedAsIs()
        {
            var key = ImmutableArray.Create(TestResources.General.snPublicKey);

            ImmutableArray <byte> pubKey;

            Assert.True(CryptoBlobParser.TryParseKey(key, out pubKey, out _));
            Assert.True(CryptoBlobParser.IsValidPublicKey(pubKey));
            AssertEx.Equal(key, pubKey);
        }
Example #2
0
        public void GetPublicKeyFromKeyPair2()
        {
            var key = ImmutableArray.Create(TestResources.General.snKey2);

            ImmutableArray <byte> pubKey;

            Assert.True(CryptoBlobParser.TryParseKey(key, out pubKey, out _));
            Assert.True(CryptoBlobParser.IsValidPublicKey(pubKey));
            AssertEx.Equal(TestResources.General.snPublicKey2, pubKey);
        }
Example #3
0
        public void GetPrivateKeyFromKeyPair2()
        {
            var key = ImmutableArray.Create(TestResources.General.snKey2);

            RSAParameters?privateKeyOpt;

            Assert.True(CryptoBlobParser.TryParseKey(key, out _, out privateKeyOpt));
            Assert.True(privateKeyOpt.HasValue);
            var privKey = privateKeyOpt.Value;

            AssertEx.Equal(privKey.Exponent, new byte[] { 0x01, 0x00, 0x01 });

            var expectedModulus = key.Skip(HEADER_LEN).Take(MOD_LEN).ToArray();

            Array.Reverse(expectedModulus);
            AssertEx.Equal(expectedModulus, privKey.Modulus);

            var expectedP = key.Skip(HEADER_LEN + MOD_LEN).Take(HALF_LEN).ToArray();

            Array.Reverse(expectedP);
            AssertEx.Equal(expectedP, privKey.P);

            var expectedQ = key.Skip(HEADER_LEN + MOD_LEN + HALF_LEN).Take(HALF_LEN).ToArray();

            Array.Reverse(expectedQ);
            AssertEx.Equal(expectedQ, privKey.Q);

            var expectedDP = key.Skip(HEADER_LEN + MOD_LEN + HALF_LEN * 2).Take(HALF_LEN).ToArray();

            Array.Reverse(expectedDP);
            AssertEx.Equal(expectedDP, privKey.DP);

            var expectedDQ = key.Skip(HEADER_LEN + MOD_LEN + HALF_LEN * 3).Take(HALF_LEN).ToArray();

            Array.Reverse(expectedDQ);
            AssertEx.Equal(expectedDQ, privKey.DQ);

            var expectedInverseQ = key.Skip(HEADER_LEN + MOD_LEN + HALF_LEN * 4)
                                   .Take(HALF_LEN)
                                   .ToArray();

            Array.Reverse(expectedInverseQ);
            AssertEx.Equal(expectedInverseQ, privKey.InverseQ);

            var expectedD = key.Skip(HEADER_LEN + MOD_LEN + HALF_LEN * 5).Take(MOD_LEN).ToArray();

            Array.Reverse(expectedD);
            AssertEx.Equal(expectedD, privKey.D);

            Assert.True(key.Skip(HEADER_LEN + MOD_LEN * 2 + HALF_LEN * 5).ToArray().Length == 0);
        }
Example #4
0
        public void TryGetPublicKeyFailsForInvalidKeyBlobs()
        {
            var invalidKeyBlobs = new[]
            {
                string.Empty,
                new string('0', 160 * 2),                              // 160 * 2 - the length of a public key, 2 - 2 chars per byte
                new string('0', 596 * 2),                              // 596 * 2 - the length of a key pair, 2 - 2 chars per byte
                "0702000000240000DEADBEEF" + new string('0', 584 * 2), // private key blob without magic private key
                "0602000000240000DEADBEEF" + new string('0', 136 * 2), // public key blob without magic public key
            };

            Assert.False(CryptoBlobParser.TryParseKey(HexToBin(invalidKeyBlobs[0]), out _, out _));
            Assert.False(CryptoBlobParser.TryParseKey(HexToBin(invalidKeyBlobs[1]), out _, out _));
            Assert.False(CryptoBlobParser.TryParseKey(HexToBin(invalidKeyBlobs[2]), out _, out _));
            Assert.False(CryptoBlobParser.TryParseKey(HexToBin(invalidKeyBlobs[3]), out _, out _));
        }
Example #5
0
        public void GetSnPublicKeyFromPublicKeyBlob()
        {
            // An Strongname public key blob includes an additional header on top
            // of the wincrypt.h public key blob
            var snBlob = TestResources.General.snPublicKey;

            var buf = new byte[snBlob.Length - CryptoBlobParser.s_publicKeyHeaderSize];

            Array.Copy(snBlob, CryptoBlobParser.s_publicKeyHeaderSize, buf, 0, buf.Length);

            var publicKeyBlob = ImmutableArray.Create(buf);

            ImmutableArray <byte> pubKey;

            Assert.True(CryptoBlobParser.TryParseKey(publicKeyBlob, out pubKey, out _));
            Assert.True(CryptoBlobParser.IsValidPublicKey(pubKey));
            AssertEx.Equal(snBlob, pubKey);
        }
        public void TryGetPublicKeyFailsForInvalidKeyBlobs()
        {
            var invalidKeyBlobs = new[]
            {
                string.Empty,
                new string('0', 160 * 2),                              // 160 * 2 - the length of a public key, 2 - 2 chars per byte
                new string('0', 596 * 2),                              // 596 * 2 - the length of a key pair, 2 - 2 chars per byte
                "0702000000240000DEADBEEF" + new string('0', 584 * 2), // private key blob without magic private key
                "0602000000240000DEADBEEF" + new string('0', 136 * 2), // public key blob without magic public key
            };

            ImmutableArray <byte> pubKey;

            foreach (var key in invalidKeyBlobs)
            {
                Assert.False(CryptoBlobParser.TryGetPublicKey(HexToBin(key), out pubKey));
            }
        }
Example #7
0
        /// <summary>
        /// Validates that the given stream is marked as signed, the signature matches
        /// the public key, and the header checksum is correct.
        /// </summary>
        public static bool IsStreamFullSigned(Stream moduleContents)
        {
            var savedPosition = moduleContents.Position;

            try
            {
                moduleContents.Position = 0;

                var peHeaders = new PEHeaders(moduleContents);

                moduleContents.Position = 0;

                using (var metadata = ModuleMetadata.CreateFromStream(moduleContents, leaveOpen: true))
                {
                    var metadataReader = metadata.MetadataReader;
                    var peReader       = metadata.Module.PEReaderOpt;
                    var flags          = peHeaders.CorHeader.Flags;

                    if (CorFlags.StrongNameSigned != (flags & CorFlags.StrongNameSigned))
                    {
                        return(false);
                    }

                    var snDirectory = peReader.PEHeaders.CorHeader.StrongNameSignatureDirectory;
                    if (!peHeaders.TryGetDirectoryOffset(snDirectory, out int snOffset))
                    {
                        return(false);
                    }

                    moduleContents.Position = 0;
                    int peSize;
                    try
                    {
                        peSize = checked ((int)moduleContents.Length);
                    }
                    catch
                    {
                        return(false);
                    }

                    var peImage = new BlobBuilder(peSize);
                    if (peSize != peImage.TryWriteBytes(moduleContents, peSize))
                    {
                        return(false);
                    }

                    byte[] buffer = GetBlobBuffer(peImage.GetBlobs().Single());

                    uint expectedChecksum = peHeaders.PEHeader.CheckSum;
                    Blob checksumBlob     = MakeBlob(buffer, peHeaders.PEHeaderStartOffset + ChecksumOffset, sizeof(uint));

                    if (expectedChecksum != PeWriter.CalculateChecksum(peImage, checksumBlob))
                    {
                        return(false);
                    }

                    int    snSize = snDirectory.Size;
                    byte[] hash   = ComputeSigningHash(peImage, peHeaders, checksumBlob, snOffset, snSize);

                    ImmutableArray <byte> publicKeyBlob = metadataReader.GetBlobContent(metadataReader.GetAssemblyDefinition().PublicKey);
                    // RSA parameters start after the public key offset
                    byte[] publicKeyParams = new byte[publicKeyBlob.Length - CryptoBlobParser.s_publicKeyHeaderSize];
                    publicKeyBlob.CopyTo(CryptoBlobParser.s_publicKeyHeaderSize, publicKeyParams, 0, publicKeyParams.Length);
                    var snKey = CryptoBlobParser.ToRSAParameters(publicKeyParams.AsSpan(), includePrivateParameters: false);

                    using (var rsa = RSA.Create())
                    {
                        rsa.ImportParameters(snKey);
                        var reversedSignature = peReader.GetSectionData(snDirectory.RelativeVirtualAddress).GetContent(0, snSize).ToArray();

                        // Unknown why the signature is reversed, but this matches the behavior of the CLR
                        // signing implementation.
                        Array.Reverse(reversedSignature);

                        if (!rsa.VerifyHash(hash, reversedSignature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
                        {
                            return(false);
                        }
                    }

                    return(true);
                }
            }
            finally
            {
                moduleContents.Position = savedPosition;
            }
        }