예제 #1
0
    private async Task PlayAliceRoleAsync(ICryptographicKey ownSigningKey, ICryptographicKey othersSigningPublicKey, Stream channel, CancellationToken cancellationToken)
    {
        // Create ephemeral ECDH key pair, to prepare for the symmetric encryption key exchange.
        using (var ecdhKeyPair = NetFxCrypto.ECDiffieHellman.Create())
        {
            // Alice receives Bob's ECDH public key and signature.
            byte[] bobPublicDH = await ReadAsync(channel, cancellationToken);

            byte[] bobSignedDH = await ReadAsync(channel, cancellationToken);

            // Alice verifies Bob's signature to be sure it's his key.
            Assert.IsTrue(WinRTCrypto.CryptographicEngine.VerifySignature(othersSigningPublicKey, bobPublicDH, bobSignedDH));

            // Alice replies to Bob's public key by transmitting her own public key and signature.
            var ecdhPublicKey = ecdhKeyPair.PublicKey.ToByteArray();
            await WriteAsync(channel, ecdhPublicKey, cancellationToken);

            byte[] ecdhPublicKeySignature = WinRTCrypto.CryptographicEngine.Sign(ownSigningKey, ecdhPublicKey);
            await WriteAsync(channel, ecdhPublicKeySignature, cancellationToken);

            // Derive a shared secret with Bob by combining Alice's private key with Bob's public key.
            var    bobDHPK = NetFxCrypto.ECDiffieHellmanCngPublicKey.FromByteArray(bobPublicDH);
            byte[] encryptionKeyMaterial  = ecdhKeyPair.DeriveKeyMaterial(bobDHPK);
            var    symmetricEncryptionKey = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7)
                                            .CreateSymmetricKey(encryptionKeyMaterial);

            // Alice also adds a secret message.
            using (var aes = CryptoStream.WriteTo(channel, WinRTCrypto.CryptographicEngine.CreateEncryptor(symmetricEncryptionKey)))
            {
                await aes.WriteAsync(SecretMessage, 0, SecretMessage.Length, cancellationToken);
            }

            channel.Dispose();
        }
    }
예제 #2
0
 public void WriteTo_InvalidInputs()
 {
     ExceptionAssert.Throws <ArgumentNullException>(
         () => CryptoStream.WriteTo(null, new MockCryptoTransform(5)));
     ExceptionAssert.Throws <ArgumentException>(
         () => CryptoStream.WriteTo(Stream.Null));
     ExceptionAssert.Throws <ArgumentException>(
         () => CryptoStream.WriteTo(Stream.Null, null));
 }
예제 #3
0
        public void WriteTo()
        {
            var t1 = new MockCryptoTransform(6);
            var t2 = new MockCryptoTransform(9);
            var ms = new MemoryStream();

            using (var cryptoStream = CryptoStream.WriteTo(ms, t1, t2))
            {
                cryptoStream.Write(Encoding.UTF8.GetBytes("abcdefghijkl"), 0, 12);
            }

            Assert.AreEqual("--abcdef-g_hijkl_ZZ", Encoding.UTF8.GetString(ms.ToArray()));
        }
        public async Task <string> ComputeMD5Async(IFile file)
        {
            using (var inputStream = await file.OpenAsync(PCLStorage.FileAccess.Read))
                using (var hasher = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Md5).CreateHash())
                    using (var nullStream = Stream.Null)
                    {
                        using (var cryptoStream = CryptoStream.WriteTo(nullStream, hasher))
                        {
                            await inputStream.CopyToAsync(cryptoStream);

                            var hashBytes  = hasher.GetValueAndReset();
                            var hashString = BitConverter.ToString(hashBytes);
                            return(hashString.Replace("-", string.Empty));
                        }
                    }
        }
예제 #5
0
        static async Task CryptoTransformFileAsync(string sourcePath, string destinationPath, ICryptoTransform[] transforms, CancellationToken cancellationToken)
        {
            const int BufferSize = 4096;

            using (var sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, useAsync: true))
            {
                using (var destinationStream = new FileStream(destinationPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, BufferSize, useAsync: true))
                {
                    using (var cryptoStream = CryptoStream.WriteTo(destinationStream, transforms))
                    {
                        await sourceStream.CopyToAsync(cryptoStream, BufferSize, cancellationToken);

                        await cryptoStream.FlushAsync(cancellationToken);

                        cryptoStream.FlushFinalBlock();
                    }
                }
            }
        }
예제 #6
0
        public void CreateEncryptor_SymmetricEncryptionEquivalence()
        {
            foreach (SymmetricAlgorithm symmetricAlgorithm in Enum.GetValues(typeof(SymmetricAlgorithm)))
            {
                try
                {
                    var  algorithmProvider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(symmetricAlgorithm);
                    uint keyLength         = GetKeyLength(symmetricAlgorithm, algorithmProvider);

                    byte[] keyMaterial = WinRTCrypto.CryptographicBuffer.GenerateRandom(keyLength);
                    var    key1        = algorithmProvider.CreateSymmetricKey(keyMaterial);
                    var    key2        = algorithmProvider.CreateSymmetricKey(keyMaterial); // create a second key so that streaming ciphers will be produce the same result when executed the second time
                    var    iv          = symmetricAlgorithm.UsesIV() ? WinRTCrypto.CryptographicBuffer.GenerateRandom((uint)algorithmProvider.BlockLength) : null;

                    for (int dataLengthFactor = 1; dataLengthFactor <= 3; dataLengthFactor++)
                    {
                        var data     = WinRTCrypto.CryptographicBuffer.GenerateRandom((uint)(dataLengthFactor * algorithmProvider.BlockLength));
                        var expected = WinRTCrypto.CryptographicEngine.Encrypt(key1, data, iv);

                        var encryptor    = WinRTCrypto.CryptographicEngine.CreateEncryptor(key2, iv);
                        var actualStream = new MemoryStream();
                        using (var cryptoStream = CryptoStream.WriteTo(actualStream, encryptor))
                        {
                            cryptoStream.Write(data, 0, data.Length);
                            cryptoStream.FlushFinalBlock();

                            byte[] actual = actualStream.ToArray();
                            Assert.AreEqual(
                                Convert.ToBase64String(expected),
                                Convert.ToBase64String(actual));
                        }
                    }

                    Debug.WriteLine("Algorithm {0} passed.", symmetricAlgorithm);
                }
                catch (NotSupportedException)
                {
                    Debug.WriteLine("Algorithm {0} is not supported on this platform.", symmetricAlgorithm);
                }
            }
        }
예제 #7
0
    public void CreateEncryptor_SymmetricEncryptionEquivalence(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
    {
        Skip.If(!name.IsBlockCipher() && padding != SymmetricAlgorithmPadding.None, "By design - streaming ciphers need no padding.");

        var algorithmProvider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(name, mode, padding);
        int keyLength         = GetKeyLength(name, algorithmProvider);

        byte[] keyMaterial = WinRTCrypto.CryptographicBuffer.GenerateRandom(keyLength);
        var    key1        = algorithmProvider.CreateSymmetricKey(keyMaterial);
        var    key2        = algorithmProvider.CreateSymmetricKey(keyMaterial); // create a second key so that streaming ciphers will be produce the same result when executed the second time
        var    iv          = mode.UsesIV() ? WinRTCrypto.CryptographicBuffer.GenerateRandom(algorithmProvider.BlockLength) : null;

        float incrementBy = padding == SymmetricAlgorithmPadding.None ? 1 : 0.5f;

        for (float dataLengthFactor = 1; dataLengthFactor <= 3; dataLengthFactor += incrementBy)
        {
            var data     = WinRTCrypto.CryptographicBuffer.GenerateRandom((int)(dataLengthFactor * algorithmProvider.BlockLength));
            var expected = WinRTCrypto.CryptographicEngine.Encrypt(key1, data, iv);

            var encryptor    = WinRTCrypto.CryptographicEngine.CreateEncryptor(key2, iv);
            var actualStream = new MemoryStream();
            using (var cryptoStream = CryptoStream.WriteTo(actualStream, encryptor))
            {
                // Write it in smaller than block length chunks so we're exercising more product code.
                int chunkSize = Math.Max(1, (int)(data.Length / Math.Max(1, dataLengthFactor + 1)));
                for (int dataOffset = 0; dataOffset < data.Length; dataOffset += chunkSize)
                {
                    cryptoStream.Write(data, dataOffset, Math.Min(chunkSize, data.Length - dataOffset));
                }

                cryptoStream.FlushFinalBlock();

                byte[] actual = actualStream.ToArray();
                Assert.Equal(
                    Convert.ToBase64String(expected),
                    Convert.ToBase64String(actual));
            }
        }
    }