예제 #1
0
        /// <summary>
        /// Gets the file format of the specified stream based on file signature.
        /// </summary>
        /// <param name="buffer">The signature bytes buffer.</param>
        /// <returns>The detected database file format.</returns>
        private static FileFormats CheckSignature(IBuffer buffer)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            // KeePass 1.x
            var oldSignature = CryptographicBuffer
                               .DecodeFromHexString("03D9A29A65FB4BB5");

            if (CryptographicBuffer.Compare(buffer, oldSignature))
            {
                return(FileFormats.KeePass1x);
            }

            // KeePass 2.x pre-release
            var preRelease = CryptographicBuffer
                             .DecodeFromHexString("03D9A29A66FB4BB5");

            if (CryptographicBuffer.Compare(buffer, preRelease))
            {
                return(FileFormats.OldVersion);
            }

            // KeePass 2.x
            var current = CryptographicBuffer
                          .DecodeFromHexString("03D9A29A67FB4BB5");

            if (!CryptographicBuffer.Compare(buffer, current))
            {
                return(FileFormats.NotSupported);
            }

            return(FileFormats.Supported);
        }
예제 #2
0
        public async Task StoredDataIsOverwritable()
        {
            Assert.IsNull(
                await this.credentialProvider.GetRawKeyAsync(this.storedCandidate.FileName),
                "StoredCandidate should not be stored yet"
                );

            byte[]  overwriteData   = Enumerable.Range(0, 256).Reverse().Select(i => (byte)i).ToArray();
            IBuffer overwriteBuffer = CryptographicBuffer.CreateFromByteArray(overwriteData);

            Assert.IsTrue(await this.credentialProvider.TryStoreRawKeyAsync(this.storedCandidate.FileName, this.mockPasswordBuffer));
            Assert.IsTrue(
                await this.credentialProvider.TryStoreRawKeyAsync(this.storedCandidate.FileName, overwriteBuffer),
                "Storing data twice for a database should be fine"
                );

            IBuffer retrievedData = await this.credentialProvider.GetRawKeyAsync(this.storedCandidate.FileName);

            Assert.IsNotNull(retrievedData);
            Assert.IsTrue(
                CryptographicBuffer.Compare(overwriteBuffer, retrievedData),
                "The retrieved data should be what was stored most recently for the database"
                );
        }
예제 #3
0
        /// <summary>
        /// This is the click handler for the 'RunSample' button.  It is responsible for executing the sample code.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RunSample_Click(object sender, RoutedEventArgs e)
        {
            String algName = AlgorithmNames.SelectionBoxItem.ToString();
            UInt32 keySize = UInt32.Parse(KeySizes.SelectionBoxItem.ToString());

            Scenario5Text.Text = "";

            IBuffer encrypted;
            IBuffer decrypted;
            IBuffer buffer;
            IBuffer iv          = null;
            String  blockCookie = "1234567812345678"; // 16 bytes

            // Open the algorithm provider for the algorithm specified on input.
            SymmetricKeyAlgorithmProvider Algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(algName);

            Scenario5Text.Text += "\n*** Sample Cipher Encryption\n";
            Scenario5Text.Text += "    Algorithm Name: " + Algorithm.AlgorithmName + "\n";
            Scenario5Text.Text += "    Key Size: " + keySize + "\n";
            Scenario5Text.Text += "    Block length: " + Algorithm.BlockLength + "\n";

            // Generate a symmetric key.
            IBuffer          keymaterial = CryptographicBuffer.GenerateRandom((keySize + 7) / 8);
            CryptographicKey key;

            try
            {
                key = Algorithm.CreateSymmetricKey(keymaterial);
            }
            catch (ArgumentException ex)
            {
                Scenario5Text.Text += ex.Message + "\n";
                Scenario5Text.Text += "An invalid key size was selected for the given algorithm.\n";
                return;
            }

            // CBC mode needs Initialization vector, here just random data.
            // IV property will be set on "Encrypted".
            if (algName.Contains("CBC"))
            {
                iv = CryptographicBuffer.GenerateRandom(Algorithm.BlockLength);
            }

            // Set the data to encrypt.
            buffer = CryptographicBuffer.ConvertStringToBinary(blockCookie, BinaryStringEncoding.Utf8);

            // Encrypt and create an authenticated tag.
            encrypted = Windows.Security.Cryptography.Core.CryptographicEngine.Encrypt(key, buffer, iv);

            Scenario5Text.Text += "    Plain text: " + buffer.Length + " bytes\n";
            Scenario5Text.Text += "    Encrypted: " + encrypted.Length + " bytes\n";

            // Create another instance of the key from the same material.
            CryptographicKey key2 = Algorithm.CreateSymmetricKey(keymaterial);

            if (key.KeySize != key2.KeySize)
            {
                Scenario5Text.Text += "CreateSymmetricKey failed!  The imported key's size did not match the original's!";
                return;
            }

            // Decrypt and verify the authenticated tag.
            decrypted = Windows.Security.Cryptography.Core.CryptographicEngine.Decrypt(key2, encrypted, iv);

            if (!CryptographicBuffer.Compare(decrypted, buffer))
            {
                Scenario5Text.Text += "Decrypted does not match original!";
                return;
            }
        }
예제 #4
0
        /// <summary>
        /// Reads the specified hashed block stream into a memory stream.
        /// </summary>
        /// <param name="input">The hashed block stream.</param>
        /// <returns>The de-hashed stream.</returns>
        public static async Task <Stream> Read(IInputStream input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            var blockIndex = 0;
            var result     = new MemoryStream();
            var hash       = WindowsRuntimeBuffer.Create(32);

            var reader = new DataReader(input)
            {
                ByteOrder = ByteOrder.LittleEndian,
            };
            var sha = HashAlgorithmProvider
                      .OpenAlgorithm(HashAlgorithmNames.Sha256);

            try
            {
                while (true)
                {
                    // Detect end of file
                    var read = await reader.LoadAsync(4);

                    if (read == 0)
                    {
                        break;
                    }

                    // Verify block index
                    var index = reader.ReadInt32();
                    if (index != blockIndex)
                    {
                        throw new InvalidDataException(string.Format(
                                                           "Wrong block ID detected, expected: {0}, actual: {1}",
                                                           blockIndex, index));
                    }
                    blockIndex++;

                    // Block hash
                    hash = await input.ReadAsync(hash, 32);

                    if (hash.Length != 32)
                    {
                        throw new InvalidDataException(
                                  "Data corruption detected (truncated data)");
                    }

                    read = await reader.LoadAsync(4);

                    if (read != 4)
                    {
                        throw new InvalidDataException(
                                  "Data corruption detected (truncated data)");
                    }

                    // Validate block size (< 10MB)
                    var blockSize = reader.ReadInt32();
                    if (blockSize == 0)
                    {
                        // Terminator block
                        var isTerminator = hash
                                           .ToArray()
                                           .All(x => x == 0);

                        if (!isTerminator)
                        {
                            throw new InvalidDataException(
                                      "Data corruption detected (invalid hash for terminator block)");
                        }

                        break;
                    }

                    if (0 > blockSize || blockSize > 10485760)
                    {
                        throw new InvalidDataException(
                                  "Data corruption detected (truncated data)");
                    }

                    // Check data truncate
                    var loaded = await reader.LoadAsync((uint)blockSize);

                    if (loaded < blockSize)
                    {
                        throw new InvalidDataException(
                                  "Data corruption detected (truncated data)");
                    }

                    var buffer = reader.ReadBuffer((uint)blockSize);

                    // Verify block integrity
                    var actual = sha.HashData(buffer);
                    if (!CryptographicBuffer.Compare(hash, actual))
                    {
                        throw new InvalidDataException(
                                  "Data corruption detected (content corrupted)");
                    }

                    await result.WriteAsync(buffer.ToArray(),
                                            0, (int)buffer.Length);
                }

                result.Position = 0;
                return(result);
            }
            catch
            {
                result.Dispose();
                throw;
            }
        }
        /// <summary>
        /// This is the click handler for the 'RunSample' button.  It is responsible for executing the sample code.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RunEncryption_Click(object sender, RoutedEventArgs e)
        {
            EncryptDecryptText.Text = "";

            IBuffer encrypted;
            IBuffer decrypted;
            IBuffer iv = null;
            IBuffer data;
            IBuffer nonce;
            String  algName = AlgorithmNames.SelectionBoxItem.ToString();

            CryptographicKey key = null;

            if (bSymAlgs.IsChecked.Value || bAuthEncrypt.IsChecked.Value)
            {
                key = GenerateSymmetricKey();
            }
            else
            {
                key = GenerateAsymmetricKey();
            }

            data = GenearetData();

            if ((bool)bAuthEncrypt.IsChecked)
            {
                nonce = GetNonce();

                EncryptedAndAuthenticatedData encryptedData = CryptographicEngine.EncryptAndAuthenticate(key, data, nonce, null);

                EncryptDecryptText.Text += "    Plain text: " + data.Length + " bytes\n";
                EncryptDecryptText.Text += "    Encrypted: " + encryptedData.EncryptedData.Length + " bytes\n";
                EncryptDecryptText.Text += "    AuthTag: " + encryptedData.AuthenticationTag.Length + " bytes\n";

                decrypted = CryptographicEngine.DecryptAndAuthenticate(key, encryptedData.EncryptedData, nonce, encryptedData.AuthenticationTag, null);

                if (!CryptographicBuffer.Compare(decrypted, data))
                {
                    EncryptDecryptText.Text += "Decrypted does not match original!";
                    return;
                }
            }
            else
            {
                // CBC mode needs Initialization vector, here just random data.
                // IV property will be set on "Encrypted".
                if (algName.Contains("CBC"))
                {
                    SymmetricKeyAlgorithmProvider algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(algName);
                    iv = CryptographicBuffer.GenerateRandom(algorithm.BlockLength);
                }

                // Encrypt the data.
                try
                {
                    encrypted = CryptographicEngine.Encrypt(key, data, iv);
                }
                catch (ArgumentException ex)
                {
                    EncryptDecryptText.Text += ex.Message + "\n";
                    EncryptDecryptText.Text += "An invalid key size was selected for the given algorithm.\n";
                    return;
                }

                EncryptDecryptText.Text += "    Plain text: " + data.Length + " bytes\n";
                EncryptDecryptText.Text += "    Encrypted: " + encrypted.Length + " bytes\n";

                // Decrypt the data.
                decrypted = CryptographicEngine.Decrypt(key, encrypted, iv);

                if (!CryptographicBuffer.Compare(decrypted, data))
                {
                    EncryptDecryptText.Text += "Decrypted data does not match original!";
                    return;
                }
            }
        }
        public async void SampleDataProtectionStream(String descriptor)
        {
            EncryptDecryptText.Text += "*** Sample Stream Data Protection for " + descriptor + " ***\n";

            IBuffer    data = CryptographicBuffer.GenerateRandom(10000);
            DataReader reader1, reader2;
            IBuffer    buff1, buff2;

            DataProtectionProvider     Provider     = new DataProtectionProvider(descriptor);
            InMemoryRandomAccessStream originalData = new InMemoryRandomAccessStream();

            //Populate the new memory stream
            IOutputStream outputStream              = originalData.GetOutputStreamAt(0);
            DataWriter    writer                    = new DataWriter(outputStream);

            writer.WriteBuffer(data);
            await writer.StoreAsync();

            await outputStream.FlushAsync();

            //open new memory stream for read
            IInputStream source = originalData.GetInputStreamAt(0);

            //Open the output memory stream
            InMemoryRandomAccessStream protectedData = new InMemoryRandomAccessStream();
            IOutputStream dest = protectedData.GetOutputStreamAt(0);

            // Protect
            await Provider.ProtectStreamAsync(source, dest);

            //Flush the output
            if (await dest.FlushAsync())
            {
                EncryptDecryptText.Text += "    Protected output was successfully flushed\n";
            }


            //Verify the protected data does not match the original
            reader1 = new DataReader(originalData.GetInputStreamAt(0));
            reader2 = new DataReader(protectedData.GetInputStreamAt(0));

            await reader1.LoadAsync((uint)originalData.Size);

            await reader2.LoadAsync((uint)protectedData.Size);

            EncryptDecryptText.Text += "    Size of original stream:  " + originalData.Size + "\n";
            EncryptDecryptText.Text += "    Size of protected stream:  " + protectedData.Size + "\n";

            if (originalData.Size == protectedData.Size)
            {
                buff1 = reader1.ReadBuffer((uint)originalData.Size);
                buff2 = reader2.ReadBuffer((uint)protectedData.Size);
                if (CryptographicBuffer.Compare(buff1, buff2))
                {
                    EncryptDecryptText.Text += "ProtectStreamAsync returned unprotected data";
                    return;
                }
            }

            EncryptDecryptText.Text += "    Stream Compare completed.  Streams did not match.\n";

            source = protectedData.GetInputStreamAt(0);

            InMemoryRandomAccessStream unprotectedData = new InMemoryRandomAccessStream();

            dest = unprotectedData.GetOutputStreamAt(0);

            // Unprotect
            DataProtectionProvider Provider2 = new DataProtectionProvider();
            await Provider2.UnprotectStreamAsync(source, dest);

            if (await dest.FlushAsync())
            {
                EncryptDecryptText.Text += "    Unprotected output was successfully flushed\n";
            }

            //Verify the unprotected data does match the original
            reader1 = new DataReader(originalData.GetInputStreamAt(0));
            reader2 = new DataReader(unprotectedData.GetInputStreamAt(0));

            await reader1.LoadAsync((uint)originalData.Size);

            await reader2.LoadAsync((uint)unprotectedData.Size);

            EncryptDecryptText.Text += "    Size of original stream:  " + originalData.Size + "\n";
            EncryptDecryptText.Text += "    Size of unprotected stream:  " + unprotectedData.Size + "\n";

            buff1 = reader1.ReadBuffer((uint)originalData.Size);
            buff2 = reader2.ReadBuffer((uint)unprotectedData.Size);
            if (!CryptographicBuffer.Compare(buff1, buff2))
            {
                EncryptDecryptText.Text += "UnrotectStreamAsync did not return expected data";
                return;
            }

            EncryptDecryptText.Text += "*** Done!\n";
        }
예제 #7
0
        /// <summary>
        /// This is the click handler for the 'RunSample' button.  It is responsible for executing the sample code.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RunSample_Click(object sender, RoutedEventArgs e)
        {
            String algName = AlgorithmNames.SelectionBoxItem.ToString();
            UInt32 KeySize = UInt32.Parse(KeySizes.SelectionBoxItem.ToString());

            Scenario7Text.Text = "";

            IBuffer Data;
            String  cookie = "Some cookie to encrypt";

            switch (AlgorithmNames.SelectedIndex)
            {
            case 0:
                Data = CryptographicBuffer.ConvertStringToBinary(cookie, BinaryStringEncoding.Utf16LE);
                break;

            // OAEP Padding depends on key size, message length and hash block length
            //
            // The maximum plaintext length is KeyLength - 2*HashBlock - 2
            //
            // OEAP padding supports an optional label with the length is restricted by plaintext/key/hash sizes.
            // Here we just use a small label.
            case 1:
                Data = CryptographicBuffer.GenerateRandom(1024 / 8 - 2 * 20 - 2);
                break;

            case 2:
                Data = CryptographicBuffer.GenerateRandom(1024 / 8 - 2 * (256 / 8) - 2);
                break;

            case 3:
                Data = CryptographicBuffer.GenerateRandom(2048 / 8 - 2 * (384 / 8) - 2);
                break;

            case 4:
                Data = CryptographicBuffer.GenerateRandom(2048 / 8 - 2 * (512 / 8) - 2);
                break;

            default:
                Scenario7Text.Text += "An invalid algorithm was selected";
                return;
            }

            IBuffer Encrypted;
            IBuffer Decrypted;
            IBuffer blobOfPublicKey;
            IBuffer blobOfKeyPair;

            // Crate an AsymmetricKeyAlgorithmProvider object for the algorithm specified on input.
            AsymmetricKeyAlgorithmProvider Algorithm = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algName);

            Scenario7Text.Text += "*** Sample Encryption Algorithm\n";
            Scenario7Text.Text += "    Algorithm Name: " + Algorithm.AlgorithmName + "\n";
            Scenario7Text.Text += "    Key Size: " + KeySize + "\n";

            // Generate a random key.
            CryptographicKey keyPair = Algorithm.CreateKeyPair(KeySize);

            // Encrypt the data.
            try
            {
                Encrypted = CryptographicEngine.Encrypt(keyPair, Data, null);
            }
            catch (ArgumentException ex)
            {
                Scenario7Text.Text += ex.Message + "\n";
                Scenario7Text.Text += "An invalid key size was selected for the given algorithm.\n";
                return;
            }

            Scenario7Text.Text += "    Plain text: " + Data.Length + " bytes\n";
            Scenario7Text.Text += "    Encrypted: " + Encrypted.Length + " bytes\n";

            // Export the public key.
            blobOfPublicKey = keyPair.ExportPublicKey();
            blobOfKeyPair   = keyPair.Export();

            // Import the public key.
            CryptographicKey keyPublic = Algorithm.ImportPublicKey(blobOfPublicKey);

            if (keyPublic.KeySize != keyPair.KeySize)
            {
                Scenario7Text.Text += "ImportPublicKey failed!  The imported key's size did not match the original's!";
                return;
            }

            // Import the key pair.
            keyPair = Algorithm.ImportKeyPair(blobOfKeyPair);

            // Check the key size of the imported key.
            if (keyPublic.KeySize != keyPair.KeySize)
            {
                Scenario7Text.Text += "ImportKeyPair failed!  The imported key's size did not match the original's!";
                return;
            }

            // Decrypt the data.
            Decrypted = CryptographicEngine.Decrypt(keyPair, Encrypted, null);

            if (!CryptographicBuffer.Compare(Decrypted, Data))
            {
                Scenario7Text.Text += "Decrypted data does not match original!";
                return;
            }
        }