Пример #1
0
    public void StreamingCipherKeyRetainsStateAcrossOperations_Decrypt()
    {
        // NetFX doesn't support RC4. If another streaming cipher is ever added to the suite,
        // this test should be modified to use that cipher to test the NetFx PCL wrapper for
        // streaming cipher behavior.
        SymmetricAlgorithmName         symmetricAlgorithm = SymmetricAlgorithmName.Rc4;
        ISymmetricKeyAlgorithmProvider?algorithmProvider  = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(symmetricAlgorithm, SymmetricAlgorithmMode.Streaming, SymmetricAlgorithmPadding.None);
        int keyLength = GetKeyLength(symmetricAlgorithm, algorithmProvider);

        byte[]            keyMaterial = WinRTCrypto.CryptographicBuffer.GenerateRandom(keyLength);
        ICryptographicKey?key1        = algorithmProvider.CreateSymmetricKey(keyMaterial);
        ICryptographicKey?key2        = algorithmProvider.CreateSymmetricKey(keyMaterial);

        byte[] allData       = new byte[] { 1, 2, 3 };
        byte[] allCiphertext = WinRTCrypto.CryptographicEngine.Decrypt(key1, allData);

        var cipherStream = new MemoryStream();

        for (int i = 0; i < allData.Length; i++)
        {
            byte[] cipherText = WinRTCrypto.CryptographicEngine.Decrypt(key2, new byte[] { allData[i] });
            cipherStream.Write(cipherText, 0, cipherText.Length);
        }

        byte[] incrementalResult = cipherStream.ToArray();
        Assert.Equal(
            Convert.ToBase64String(allCiphertext),
            Convert.ToBase64String(incrementalResult));
    }
Пример #2
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);
        }
    }
Пример #3
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);
            }
        }
    }
        public CertificateOutputViewModel(byte[] signature, byte[] data, byte[] key, HashAlgorithmName hash,
                                          SymmetricAlgorithmName sym, SymmetricAlgorithmKey symKey, AsymmetricAlgorithmName alg,
                                          AsymmetricAlgorithmKey algKey, string file)
        {
            this.Description = "Certificate";

            this.EnvelopeData     = Convert.ToBase64String(data);
            this.EnvelopeCryptKey = key.ConvertToHex();
            this.Signature        = signature.ConvertToHex();

            this.Methods = new List <string>()
            {
                hash.ToString(),
                    sym.ToString(),
                    alg.ToString()
            };
            this.Method     = string.Join("\n", Methods);
            this.KeyLengths = new List <string>()
            {
                "",
                ((int)symKey).ToString("X"), // hex
                ((int)algKey).ToString("X")  // hex
            };
            this.KeyLength = string.Join("\n", KeyLengths);
            this.FileName  = file;
        }
 /// <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;
 }
 /// <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;
 }
Пример #7
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="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;
        }
Пример #9
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;
        }
Пример #10
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())
            {
            }
        }
    public void LegalKeySizes(SymmetricAlgorithmName name, int minSize, int maxSize, int stepSize)
    {
        var blockMode = name.IsBlockCipher() ? SymmetricAlgorithmMode.Cbc : SymmetricAlgorithmMode.Streaming;
        var padding = name.IsBlockCipher() ? SymmetricAlgorithmPadding.PKCS7 : SymmetricAlgorithmPadding.None;
        using (ISymmetricKeyAlgorithmProvider provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(name, blockMode, padding))
        {
            var result = provider.LegalKeySizes;
            Assert.NotNull(result);
            Assert.NotEmpty(result);

            var random = new Random();
            Action<int> attemptKeySize = size =>
            {
                var keyMaterial = new byte[size / 8];
                random.NextBytes(keyMaterial); // some algorithms check against weak keys (e.g. all zeros)
                provider.CreateSymmetricKey(keyMaterial).Dispose();
            };

            // Verify that each allegedly legal key size actually works.
            foreach (var item in result)
            {
                this.logger.WriteLine($"{item.MinSize}-{item.MaxSize} ({item.StepSize})");
                foreach (var keySize in item)
                {
                    attemptKeySize(keySize);
                }

                // Also check the cases just off the edges of the range to see that they actually fail.
                // This ensures the returned values aren't too conservative.
#if false // WinRT actually doesn't throw when given keys of inappropriate size. Go figure.
                if (item.StepSize > 0)
                {
                    if (item.MinSize - item.StepSize > 0)
                    {
                        Assert.Throws<ArgumentException>(() => attemptKeySize(item.MinSize - item.StepSize));
                    }

                    if (item.MaxSize + item.StepSize > 0)
                    {
                        Assert.Throws<ArgumentException>(() => attemptKeySize(item.MaxSize + item.StepSize));
                    }
                }
#endif
            }

            var range = result.Single();
            Assert.Equal(minSize, range.MinSize);
            Assert.Equal(maxSize, range.MaxSize);
            Assert.Equal(stepSize, range.StepSize);
        }
    }
Пример #12
0
    public void LegalKeySizes(SymmetricAlgorithmName name, int minSize, int maxSize, int stepSize)
    {
        var blockMode = name.IsBlockCipher() ? SymmetricAlgorithmMode.Cbc : SymmetricAlgorithmMode.Streaming;
        var padding   = name.IsBlockCipher() ? SymmetricAlgorithmPadding.PKCS7 : SymmetricAlgorithmPadding.None;
        ISymmetricKeyAlgorithmProvider provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(name, blockMode, padding);
        var result = provider.LegalKeySizes;

        Assert.NotNull(result);
        Assert.NotEmpty(result);

        var          random         = new Random();
        Action <int> attemptKeySize = size =>
        {
            var keyMaterial = new byte[size / 8];
            random.NextBytes(keyMaterial); // some algorithms check against weak keys (e.g. all zeros)
            provider.CreateSymmetricKey(keyMaterial).Dispose();
        };

        // Verify that each allegedly legal key size actually works.
        foreach (var item in result)
        {
            this.logger.WriteLine($"{item.MinSize}-{item.MaxSize} ({item.StepSize})");
            foreach (var keySize in item)
            {
                attemptKeySize(keySize);
            }

            // Also check the cases just off the edges of the range to see that they actually fail.
            // This ensures the returned values aren't too conservative.
#if false // WinRT actually doesn't throw when given keys of inappropriate size. Go figure.
            if (item.StepSize > 0)
            {
                if (item.MinSize - item.StepSize > 0)
                {
                    Assert.Throws <ArgumentException>(() => attemptKeySize(item.MinSize - item.StepSize));
                }

                if (item.MaxSize + item.StepSize > 0)
                {
                    Assert.Throws <ArgumentException>(() => attemptKeySize(item.MaxSize + item.StepSize));
                }
            }
#endif
        }

        var range = result.Single();
        Assert.Equal(minSize, range.MinSize);
        Assert.Equal(maxSize, range.MaxSize);
        Assert.Equal(stepSize, range.StepSize);
    }
Пример #13
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>
        /// 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);
            }
        }
Пример #15
0
        /// <summary>
        /// Gets a value indicating whether the specified algorithm is implemented by a block cipher.
        /// </summary>
        /// <param name="algorithm">The algorithm to check.</param>
        /// <returns><c>true</c> if the cipher is a block cipher; <c>false</c> otherwise.</returns>
        public static bool IsBlockCipher(this SymmetricAlgorithmName algorithm)
        {
            switch (algorithm)
            {
            case SymmetricAlgorithmName.Aes:
            case SymmetricAlgorithmName.Des:
            case SymmetricAlgorithmName.TripleDes:
            case SymmetricAlgorithmName.Rc2:
                return(true);

            case SymmetricAlgorithmName.Rc4:
                return(false);

            default:
                throw new NotSupportedException();
            }
        }
Пример #16
0
    private static int GetKeyLength(SymmetricAlgorithmName symmetricAlgorithm, ISymmetricKeyAlgorithmProvider algorithmProvider)
    {
        int keyLength;

        switch (symmetricAlgorithm)
        {
        case SymmetricAlgorithmName.TripleDes:
            keyLength = algorithmProvider.BlockLength * 3;
            break;

        default:
            keyLength = algorithmProvider.BlockLength;
            break;
        }

        return(keyLength);
    }
        private static ISymmetricCryptoAlgorithm GetSymmetricAlgorithm(this SymmetricAlgorithmName name,
                                                                       SymmetricAlgorithmKey keySize, System.Security.Cryptography.CipherMode mode)
        {
            switch (name)
            {
            case SymmetricAlgorithmName.TripleDES:
                return(new TripleDES(keySize: (int)keySize, mode: mode));

                break;

            case SymmetricAlgorithmName.AES:
            default:
                return(new AES(keySize: (int)keySize, mode: mode));

                break;
            }
        }
        /// <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="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;
        }
Пример #20
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));
            }
        }
    }
Пример #21
0
        /// <summary>
        /// Gets the string representation of an algorithm name.
        /// </summary>
        /// <param name="algorithm">The algorithm.</param>
        /// <returns>A non-empty string, such as "AES".</returns>
        public static string GetString(this SymmetricAlgorithmName algorithm)
        {
            switch (algorithm)
            {
            case SymmetricAlgorithmName.Aes:
                return("AES");

            case SymmetricAlgorithmName.Des:
                return("DES");

            case SymmetricAlgorithmName.Rc2:
                return("RC2");

            case SymmetricAlgorithmName.Rc4:
                return("RC4");

            case SymmetricAlgorithmName.TripleDes:
                return("TRIPLEDES");

            default:
                throw new ArgumentException();
            }
        }
Пример #22
0
        /// <summary>
        /// Returns the string to pass to the platform APIs for a given algorithm.
        /// </summary>
        /// <param name="algorithm">The algorithm desired.</param>
        /// <returns>The platform-specific string to pass to OpenAlgorithm.</returns>
        private static string GetAlgorithmName(SymmetricAlgorithmName algorithm)
        {
            switch (algorithm)
            {
            case SymmetricAlgorithmName.Aes:
                return(AlgorithmIdentifiers.BCRYPT_AES_ALGORITHM);

            case SymmetricAlgorithmName.Des:
                return(AlgorithmIdentifiers.BCRYPT_DES_ALGORITHM);

            case SymmetricAlgorithmName.TripleDes:
                return(AlgorithmIdentifiers.BCRYPT_3DES_ALGORITHM);

            case SymmetricAlgorithmName.Rc2:
                return(AlgorithmIdentifiers.BCRYPT_RC2_ALGORITHM);

            case SymmetricAlgorithmName.Rc4:
                return(AlgorithmIdentifiers.BCRYPT_RC4_ALGORITHM);

            default:
                throw new NotSupportedException();
            }
        }
 /// <inheritdoc />
 public ISymmetricKeyAlgorithmProvider OpenAlgorithm(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
 {
     return new SymmetricKeyAlgorithmProvider(name, mode, padding);
 }
    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));
            }
        }
    }
        /// <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;
        }
    private static int GetKeyLength(SymmetricAlgorithmName symmetricAlgorithm, ISymmetricKeyAlgorithmProvider algorithmProvider)
    {
        int keyLength;
        switch (symmetricAlgorithm)
        {
            case SymmetricAlgorithmName.TripleDes:
                keyLength = algorithmProvider.BlockLength * 3;
                break;
            default:
                keyLength = algorithmProvider.BlockLength;
                break;
        }

        return keyLength;
    }
 /// <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;
 }
Пример #28
0
 /// <inheritdoc />
 public ISymmetricKeyAlgorithmProvider OpenAlgorithm(SymmetricAlgorithmName name, SymmetricAlgorithmMode mode, SymmetricAlgorithmPadding padding)
 {
     return(new SymmetricKeyAlgorithmProvider(name, mode, padding));
 }
 /// <summary>
 /// Gets the BCrypt algorithm identifier to pass to <see cref="BCryptOpenAlgorithmProvider(string, string, BCryptOpenAlgorithmProviderFlags)"/>.
 /// </summary>
 /// <param name="algorithm">The algorithm.</param>
 /// <returns>The algorithm identifier.</returns>
 private static string GetAlgorithmIdentifier(SymmetricAlgorithmName algorithm)
 {
     switch (algorithm)
     {
         case SymmetricAlgorithmName.Aes:
             return AlgorithmIdentifiers.BCRYPT_AES_ALGORITHM;
         case SymmetricAlgorithmName.Des:
             return AlgorithmIdentifiers.BCRYPT_DES_ALGORITHM;
         case SymmetricAlgorithmName.TripleDes:
             return AlgorithmIdentifiers.BCRYPT_3DES_ALGORITHM;
         case SymmetricAlgorithmName.Rc2:
             return AlgorithmIdentifiers.BCRYPT_RC2_ALGORITHM;
         case SymmetricAlgorithmName.Rc4:
             return AlgorithmIdentifiers.BCRYPT_RC4_ALGORITHM;
         default:
             throw new NotSupportedException();
     }
 }