Esempio n. 1
0
    public void SymmetricEncryption(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
    {
        Skip.If(mode.IsAuthenticated(), "This test is only for non-authenticated block modes.");
        bool badCombination = false;
        badCombination |= !mode.IsBlockCipher() && padding != SymmetricAlgorithmPadding.None; // Padding does not apply to streaming ciphers.
        badCombination |= name.IsBlockCipher() != mode.IsBlockCipher(); // Incompatible cipher and block mode.

        Func<ISymmetricKeyAlgorithmProvider> creator = () => WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(name, mode, padding);
        if (badCombination)
        {
            Assert.Throws<ArgumentException>(creator);
            this.logger.WriteLine("Expected exception thrown for invalid combination.");
            return;
        }

        using (var algorithm = creator())
        {
            int keyLength = algorithm.LegalKeySizes.First().MinSize;
            var keyMaterial = WinRTCrypto.CryptographicBuffer.GenerateRandom(keyLength / 8);
            using (var key = algorithm.CreateSymmetricKey(keyMaterial))
            {
                var ciphertext = WinRTCrypto.CryptographicEngine.Encrypt(key, new byte[algorithm.BlockLength], null);
                Assert.NotEqual(0, ciphertext.Length);
            }
        }
    }
 /// <summary>
 /// Initializes a new instance of the <see cref="SymmetricCryptographicKey"/> class.
 /// </summary>
 /// <param name="algorithm">The algorithm, initialized with the key.</param>
 /// <param name="name">The name of the base algorithm to use.</param>
 /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
 /// <param name="padding">The padding to use.</param>
 internal SymmetricCryptographicKey(Platform.SymmetricAlgorithm algorithm, SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
 {
     Requires.NotNull(algorithm, "algorithm");
     this.algorithm = algorithm;
     this.Name = name;
     this.Mode = mode;
     this.Padding = padding;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricKeyAlgorithmProvider"/> class.
        /// </summary>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        public SymmetricKeyAlgorithmProvider(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
        {
            Requires.Argument(mode.IsBlockCipher() == name.IsBlockCipher(), nameof(mode), "Block chaining mode incompatible with cipher. Don't mix streaming and non-streaming ciphers and modes.");
            Requires.Argument(padding == SymmetricAlgorithmPadding.None || mode.IsBlockCipher(), nameof(padding), "Padding does not apply to streaming ciphers.");

            this.Name = name;
            this.Mode = mode;
            this.Padding = padding;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricKeyAlgorithmProvider"/> class.
        /// </summary>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        public SymmetricKeyAlgorithmProvider(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
        {
            this.Name = name;
            this.Mode = mode;
            this.Padding = padding;

            this.Algorithm = BCryptOpenAlgorithmProvider(GetAlgorithmName(name));
            try
            {
                BCryptSetProperty(this.Algorithm, PropertyNames.BCRYPT_CHAINING_MODE, GetChainingMode(mode));
            }
            catch (PInvoke.Win32Exception ex)
            {
                throw new ArgumentException(ex.Message, ex);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Gets the platform enum value for the padding used by the specified algorithm.
        /// </summary>
        /// <param name="padding">The algorithm padding.</param>
        /// <returns>The platform-specific enum value for the padding.</returns>
        private static Platform.PaddingMode GetPadding(SymmetricAlgorithmPadding padding)
        {
            switch (padding)
            {
            case SymmetricAlgorithmPadding.None:
                return(Platform.PaddingMode.None);

            case SymmetricAlgorithmPadding.PKCS7:
                return(Platform.PaddingMode.PKCS7);

            case SymmetricAlgorithmPadding.Zeros:
                return(Platform.PaddingMode.Zeros);

            default:
                throw new ArgumentException();
            }
        }
        /// <summary>
        /// Gets the padding substring to include in the string
        /// passed to <see cref="Cipher.GetInstance(string)"/>.
        /// </summary>
        /// <param name="padding">The padding.</param>
        /// <returns>A value such as "PKCS7Padding", or "NoPadding" if no padding.</returns>
        private static string GetPaddingName(SymmetricAlgorithmPadding padding)
        {
            // The constants used here come from
            // http://www.bouncycastle.org/specifications.html
            switch (padding)
            {
            case SymmetricAlgorithmPadding.Zeros:     // we apply Zeros padding ourselves, since BC does it wrong (?!)
            case SymmetricAlgorithmPadding.None:
                return("NoPadding");

            case SymmetricAlgorithmPadding.PKCS7:
                return("PKCS7Padding");

            default:
                throw new NotSupportedException();
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricCryptographicKey" /> class.
        /// </summary>
        /// <param name="provider">The provider that created this instance.</param>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        /// <param name="keyMaterial">The key.</param>
        internal SymmetricCryptographicKey(SymmetricKeyAlgorithmProvider provider, SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding, byte[] keyMaterial)
        {
            Requires.NotNull(provider, nameof(provider));
            Requires.NotNull(keyMaterial, nameof(keyMaterial));

            if (name == SymmetricAlgorithmName.Aes && mode == SymmetricAlgorithmMode.Ccm && padding == SymmetricAlgorithmPadding.None)
            {
                // On Android encryption misbehaves causing our unit tests to fail.
                throw new NotSupportedException();
            }

            this.provider = provider;
            this.Name = name;
            this.Mode = mode;
            this.Padding = padding;
            this.key = new SecretKeySpec(keyMaterial, this.Name.GetString());
            this.KeySize = keyMaterial.Length * 8;
        }
Esempio n. 8
0
    public void EncryptDecrypt_AES(int inputLength, SymmetricAlgorithmPadding padding, string expectedCiphertext)
    {
        byte[] iv        = IV;
        byte[] plaintext = new byte[inputLength];
        Array.Copy(this.bigData, plaintext, inputLength);
        var algorithm = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmName.Aes, SymmetricAlgorithmMode.Cbc, padding);

        using (var key = algorithm.CreateSymmetricKey(Convert.FromBase64String(AesKeyMaterial)))
        {
            if (expectedCiphertext == null)
            {
                Assert.Throws <ArgumentException>(
                    () => WinRTCrypto.CryptographicEngine.Encrypt(key, plaintext, iv));
            }
            else
            {
                byte[] actualCipherText = WinRTCrypto.CryptographicEngine.Encrypt(key, plaintext, iv);
                Assert.Equal(
                    expectedCiphertext,
                    Convert.ToBase64String(actualCipherText));

                byte[] expectedPlainText = plaintext;
                if (!PaddingPreservesPlaintextLength(padding))
                {
                    // Therefore the expected decrypted value will have a length that is a multiple
                    // of the block length.
                    int blockLength = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmName.Aes, SymmetricAlgorithmMode.Cbc, SymmetricAlgorithmPadding.Zeros)
                                      .BlockLength;
                    int bytesBeyondLastBlockLength = expectedPlainText.Length % blockLength;
                    if (bytesBeyondLastBlockLength > 0)
                    {
                        int growBy = blockLength - bytesBeyondLastBlockLength;
                        Array.Resize(ref expectedPlainText, expectedPlainText.Length + growBy);
                    }
                }

                byte[] actualPlainText = WinRTCrypto.CryptographicEngine.Decrypt(key, actualCipherText, iv);

                Assert.Equal(
                    Convert.ToBase64String(expectedPlainText),
                    Convert.ToBase64String(actualPlainText));
            }
        }
    }
 /// <summary>
 /// Initializes a new instance of the <see cref="CryptoTransformAdaptor"/> class.
 /// </summary>
 /// <param name="name">The name of the base algorithm to use.</param>
 /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
 /// <param name="padding">The padding to use.</param>
 /// <param name="transform">The transform.</param>
 internal CryptoTransformAdaptor(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding, Cipher transform)
 {
     Requires.NotNull(transform, "transform");
     this.name = name;
     this.mode = mode;
     this.padding = padding;
     this.transform = transform;
 }
Esempio n. 10
0
        /// <summary>
        /// Finds a composite <see cref="SymmetricAlgorithm"/> for the specified unit parts, if one exists.
        /// </summary>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        /// <param name="algorithm">Receives the composite algorithm enum value, if one exists.</param>
        /// <returns><c>true</c> if a match was found; otherwise <c>false</c>.</returns>
        public static bool TryAssemblyAlgorithm(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding, out SymmetricAlgorithm algorithm)
        {
            foreach (SymmetricAlgorithm assembled in Enum.GetValues(typeof(SymmetricAlgorithm)))
            {
                if (assembled.GetName() == name && assembled.GetMode() == mode && assembled.GetPadding() == padding)
                {
                    algorithm = assembled;
                    return(true);
                }
            }

            algorithm = (SymmetricAlgorithm)0;
            return(false);
        }
 /// <summary>
 /// Gets the padding substring to include in the string
 /// passed to <see cref="Cipher.GetInstance(string)"/>
 /// </summary>
 /// <param name="padding">The padding.</param>
 /// <returns>A value such as "PKCS7Padding", or "NoPadding" if no padding.</returns>
 private static string GetPaddingName(SymmetricAlgorithmPadding padding)
 {
     // The constants used here come from
     // http://www.bouncycastle.org/specifications.html
     switch (padding)
     {
         case SymmetricAlgorithmPadding.Zeros: // we apply Zeros padding ourselves, since BC does it wrong (?!)
         case SymmetricAlgorithmPadding.None:
             return "NoPadding";
         case SymmetricAlgorithmPadding.PKCS7:
             return "PKCS7Padding";
         default:
             throw new NotSupportedException();
     }
 }
Esempio n. 12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricKeyAlgorithmProvider"/> class.
        /// </summary>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        public SymmetricKeyAlgorithmProvider(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
        {
            Requires.Argument(mode.IsBlockCipher() == name.IsBlockCipher(), nameof(mode), "Block chaining mode incompatible with cipher. Don't mix streaming and non-streaming ciphers and modes.");
            Requires.Argument(padding == SymmetricAlgorithmPadding.None || mode.IsBlockCipher(), nameof(padding), "Padding does not apply to streaming ciphers.");

            this.Name    = name;
            this.Mode    = mode;
            this.Padding = padding;
        }
Esempio n. 13
0
 /// <inheritdoc />
 public ISymmetricKeyAlgorithmProvider OpenAlgorithm(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
 {
     return(new SymmetricKeyAlgorithmProvider(name, mode, padding));
 }
 /// <summary>
 /// Gets the platform enum value for the padding used by the specified algorithm.
 /// </summary>
 /// <param name="padding">The algorithm padding.</param>
 /// <returns>The platform-specific enum value for the padding.</returns>
 private static Platform.PaddingMode GetPadding(SymmetricAlgorithmPadding padding)
 {
     switch (padding)
     {
         case SymmetricAlgorithmPadding.None:
             return Platform.PaddingMode.None;
         case SymmetricAlgorithmPadding.PKCS7:
             return Platform.PaddingMode.PKCS7;
         case SymmetricAlgorithmPadding.Zeros:
             return Platform.PaddingMode.Zeros;
         default:
             throw new ArgumentException();
     }
 }
    public void EncryptDecrypt_AES(int inputLength, SymmetricAlgorithmPadding padding, string expectedCiphertext)
    {
        byte[] iv = IV;
        byte[] plaintext = new byte[inputLength];
        Array.Copy(this.bigData, plaintext, inputLength);
        using (var algorithm = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmName.Aes, SymmetricAlgorithmMode.Cbc, padding))
        {
            using (var key = algorithm.CreateSymmetricKey(Convert.FromBase64String(AesKeyMaterial)))
            {
                if (expectedCiphertext == null)
                {
                    Assert.Throws<ArgumentException>(
                        () => WinRTCrypto.CryptographicEngine.Encrypt(key, plaintext, iv));
                }
                else
                {
                    byte[] actualCipherText = WinRTCrypto.CryptographicEngine.Encrypt(key, plaintext, iv);
                    Assert.Equal(
                        expectedCiphertext,
                        Convert.ToBase64String(actualCipherText));

                    byte[] expectedPlainText = plaintext;
                    if (!PaddingPreservesPlaintextLength(padding))
                    {
                        // Therefore the expected decrypted value will have a length that is a multiple
                        // of the block length.
                        int blockLength = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmName.Aes, SymmetricAlgorithmMode.Cbc, SymmetricAlgorithmPadding.Zeros)
                            .BlockLength;
                        int bytesBeyondLastBlockLength = expectedPlainText.Length % blockLength;
                        if (bytesBeyondLastBlockLength > 0)
                        {
                            int growBy = blockLength - bytesBeyondLastBlockLength;
                            Array.Resize(ref expectedPlainText, expectedPlainText.Length + growBy);
                        }
                    }

                    byte[] actualPlainText = WinRTCrypto.CryptographicEngine.Decrypt(key, actualCipherText, iv);

                    Assert.Equal(
                        Convert.ToBase64String(expectedPlainText),
                        Convert.ToBase64String(actualPlainText));
                }
            }
        }
    }
Esempio n. 16
0
    public void SymmetricEncryption(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
    {
        Skip.If(mode.IsAuthenticated(), "This test is only for non-authenticated block modes.");
        bool badCombination = false;

        badCombination |= !mode.IsBlockCipher() && padding != SymmetricAlgorithmPadding.None; // Padding does not apply to streaming ciphers.
        badCombination |= name.IsBlockCipher() != mode.IsBlockCipher();                       // Incompatible cipher and block mode.

        Func <ISymmetricKeyAlgorithmProvider> creator = () => WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(name, mode, padding);

        if (badCombination)
        {
            Assert.Throws <ArgumentException>(creator);
            this.logger.WriteLine("Expected exception thrown for invalid combination.");
            return;
        }

        var algorithm   = creator();
        int keyLength   = algorithm.LegalKeySizes.First().MinSize;
        var keyMaterial = WinRTCrypto.CryptographicBuffer.GenerateRandom(keyLength / 8);

        using (var key = algorithm.CreateSymmetricKey(keyMaterial))
        {
            var ciphertext = WinRTCrypto.CryptographicEngine.Encrypt(key, new byte[algorithm.BlockLength], null);
            Assert.NotEmpty(ciphertext);
        }
    }
    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));
            }
        }
    }
Esempio n. 18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SymmetricCryptographicKey"/> class.
 /// </summary>
 /// <param name="algorithm">The algorithm, initialized with the key.</param>
 /// <param name="name">The name of the base algorithm to use.</param>
 /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
 /// <param name="padding">The padding to use.</param>
 internal SymmetricCryptographicKey(Platform.SymmetricAlgorithm algorithm, SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
 {
     Requires.NotNull(algorithm, "algorithm");
     this.algorithm = algorithm;
     this.Name      = name;
     this.Mode      = mode;
     this.Padding   = padding;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricCryptographicKey" /> class.
        /// </summary>
        /// <param name="provider">The provider that created this instance.</param>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        /// <param name="keyMaterial">The key.</param>
        internal SymmetricCryptographicKey(SymmetricKeyAlgorithmProvider provider, SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding, byte[] keyMaterial)
        {
            Requires.NotNull(provider, nameof(provider));
            Requires.NotNull(keyMaterial, nameof(keyMaterial));

            if (name == SymmetricAlgorithmName.Aes && mode == SymmetricAlgorithmMode.Ccm && padding == SymmetricAlgorithmPadding.None)
            {
                // On Android encryption misbehaves causing our unit tests to fail.
                throw new NotSupportedException();
            }

            this.provider = provider;
            this.Name     = name;
            this.Mode     = mode;
            this.Padding  = padding;
            this.key      = new SecretKeySpec(keyMaterial, this.Name.GetString());
            this.KeySize  = keyMaterial.Length * 8;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="CryptoTransformAdaptor"/> class.
 /// </summary>
 /// <param name="name">The name of the base algorithm to use.</param>
 /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
 /// <param name="padding">The padding to use.</param>
 /// <param name="transform">The transform.</param>
 internal CryptoTransformAdaptor(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding, Cipher transform)
 {
     Requires.NotNull(transform, "transform");
     this.name      = name;
     this.mode      = mode;
     this.padding   = padding;
     this.transform = transform;
 }
Esempio n. 21
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricKeyAlgorithmProvider"/> class.
        /// </summary>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        public SymmetricKeyAlgorithmProvider(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
        {
            this.Name    = name;
            this.Mode    = mode;
            this.Padding = padding;

            // Try opening the algorithm now to throw any exceptions that it may.
            using (this.OpenAlgorithm())
            {
            }
        }
 private static bool PaddingPreservesPlaintextLength(SymmetricAlgorithmPadding padding)
 {
     return padding != SymmetricAlgorithmPadding.Zeros;
 }
        /// <summary>
        /// Finds a composite <see cref="SymmetricAlgorithm"/> for the specified unit parts, if one exists.
        /// </summary>
        /// <param name="name">The name of the base algorithm to use.</param>
        /// <param name="mode">The algorithm's mode (i.e. streaming or some block mode).</param>
        /// <param name="padding">The padding to use.</param>
        /// <param name="algorithm">Receives the composite algorithm enum value, if one exists.</param>
        /// <returns><c>true</c> if a match was found; otherwise <c>false</c>.</returns>
        public static bool TryAssemblyAlgorithm(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding, out SymmetricAlgorithm algorithm)
        {
            foreach (SymmetricAlgorithm assembled in Enum.GetValues(typeof(SymmetricAlgorithm)))
            {
                if (assembled.GetName() == name && assembled.GetMode() == mode && assembled.GetPadding() == padding)
                {
                    algorithm = assembled;
                    return true;
                }
            }

            algorithm = (SymmetricAlgorithm)0;
            return false;
        }
Esempio n. 24
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));
            }
        }
    }
 /// <inheritdoc />
 public ISymmetricKeyAlgorithmProvider OpenAlgorithm(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
 {
     return new SymmetricKeyAlgorithmProvider(name, mode, padding);
 }
Esempio n. 26
0
 private static bool PaddingPreservesPlaintextLength(SymmetricAlgorithmPadding padding)
 {
     return(padding != SymmetricAlgorithmPadding.Zeros);
 }