/// <summary> /// Creates a web safe base64 thumbprint of some buffer. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <param name="buffer">The buffer.</param> /// <returns>A string representation of a hash of the <paramref name="buffer"/>.</returns> public static string CreateWebSafeBase64Thumbprint(this CryptoSettings cryptoProvider, byte[] buffer) { Requires.NotNull(cryptoProvider, "cryptoProvider"); Requires.NotNull(buffer, "buffer"); var hasher = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(cryptoProvider.SymmetricHashAlgorithm); var hash = hasher.HashData(buffer); return Utilities.ToBase64WebSafe(hash); }
/// <summary> /// Symmetrically encrypts the specified buffer using a randomly generated key. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <param name="data">The data to encrypt.</param> /// <param name="encryptionVariables">Optional encryption variables to use; or <c>null</c> to use randomly generated ones.</param> /// <returns> /// The result of the encryption. /// </returns> public static SymmetricEncryptionResult Encrypt(this CryptoSettings cryptoProvider, byte[] data, SymmetricEncryptionVariables encryptionVariables = null) { Requires.NotNull(data, "data"); encryptionVariables = ThisOrNewEncryptionVariables(cryptoProvider, encryptionVariables); var symmetricKey = CryptoSettings.SymmetricAlgorithm.CreateSymmetricKey(encryptionVariables.Key); var cipherTextBuffer = WinRTCrypto.CryptographicEngine.Encrypt(symmetricKey, data, encryptionVariables.IV); return new SymmetricEncryptionResult(encryptionVariables, cipherTextBuffer); }
/// <summary> /// Returns the specified encryption variables if they are non-null, or generates new ones. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <param name="encryptionVariables">The encryption variables.</param> /// <returns> /// A valid set of encryption variables. /// </returns> private static SymmetricEncryptionVariables ThisOrNewEncryptionVariables(CryptoSettings cryptoProvider, SymmetricEncryptionVariables encryptionVariables) { if (encryptionVariables == null) { return NewSymmetricEncryptionVariables(cryptoProvider); } else { Requires.Argument(encryptionVariables.Key.Length == cryptoProvider.SymmetricKeySize / 8, "key", "Incorrect length."); Requires.Argument(encryptionVariables.IV.Length == CryptoSettings.SymmetricAlgorithm.BlockLength, "iv", "Incorrect length."); return encryptionVariables; } }
/// <summary> /// Creates a signed address book entry that describes the public information in this endpoint. /// </summary> /// <param name="cryptoServices">The crypto services to use for signing the address book entry.</param> /// <returns>The address book entry.</returns> public AddressBookEntry CreateAddressBookEntry(CryptoSettings cryptoServices) { Requires.NotNull(cryptoServices, "cryptoServices"); var ms = new MemoryStream(); var writer = new BinaryWriter(ms); var entry = new AddressBookEntry(); writer.SerializeDataContract(this.PublicEndpoint); writer.Flush(); entry.SerializedEndpoint = ms.ToArray(); entry.Signature = WinRTCrypto.CryptographicEngine.Sign(this.SigningKey, entry.SerializedEndpoint); return(entry); }
/// <summary> /// Symmetrically decrypts a stream. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <param name="ciphertext">The stream of ciphertext to decrypt.</param> /// <param name="plaintext">The stream to receive the plaintext.</param> /// <param name="encryptionVariables">The key and IV to use.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <returns> /// A task that represents the asynchronous operation. /// </returns> public static async Task DecryptAsync(this CryptoSettings cryptoProvider, Stream ciphertext, Stream plaintext, SymmetricEncryptionVariables encryptionVariables, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(ciphertext, "ciphertext"); Requires.NotNull(plaintext, "plaintext"); Requires.NotNull(encryptionVariables, "encryptionVariables"); var key = CryptoSettings.SymmetricAlgorithm.CreateSymmetricKey(encryptionVariables.Key); using (var decryptor = WinRTCrypto.CryptographicEngine.CreateDecryptor(key, encryptionVariables.IV)) { var cryptoStream = new CryptoStream(plaintext, decryptor, CryptoStreamMode.Write); await ciphertext.CopyToAsync(cryptoStream, 4096, cancellationToken).ConfigureAwait(false); cryptoStream.FlushFinalBlock(); } }
/// <summary> /// Computes the hash of the specified buffer and checks for a match to an expected hash. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <param name="data">The data to hash.</param> /// <param name="expectedHash">The expected hash.</param> /// <param name="hashAlgorithm">The hash algorithm.</param> /// <returns> /// <c>true</c> if the hashes came out equal; <c>false</c> otherwise. /// </returns> internal static bool IsHashMatchWithTolerantHashAlgorithm(this CryptoSettings cryptoProvider, byte[] data, byte[] expectedHash, HashAlgorithm? hashAlgorithm) { Requires.NotNull(cryptoProvider, "cryptoProvider"); Requires.NotNull(data, "data"); Requires.NotNull(expectedHash, "expectedHash"); if (!hashAlgorithm.HasValue) { hashAlgorithm = Utilities.GuessHashAlgorithmFromLength(expectedHash.Length); } var hasher = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(hashAlgorithm.Value); byte[] actualHash = hasher.HashData(data); return Utilities.AreEquivalent(expectedHash, actualHash); }
/// <summary> /// Creates a signed address book entry that describes the public information in this endpoint. /// </summary> /// <param name="cryptoServices">The crypto services to use for signing the address book entry.</param> /// <returns>The address book entry.</returns> public AddressBookEntry CreateAddressBookEntry(CryptoSettings cryptoServices) { Requires.NotNull(cryptoServices, "cryptoServices"); var ms = new MemoryStream(); var writer = new BinaryWriter(ms); var entry = new AddressBookEntry(); writer.SerializeDataContract(this.PublicEndpoint); writer.Flush(); entry.SerializedEndpoint = ms.ToArray(); entry.Signature = WinRTCrypto.CryptographicEngine.Sign(this.SigningKey, entry.SerializedEndpoint); return entry; }
/// <summary> /// Generates a new set of encryption variables. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <returns> /// A set of encryption variables. /// </returns> private static SymmetricEncryptionVariables NewSymmetricEncryptionVariables(CryptoSettings cryptoProvider) { byte[] key = WinRTCrypto.CryptographicBuffer.GenerateRandom(cryptoProvider.SymmetricKeySize / 8); byte[] iv = WinRTCrypto.CryptographicBuffer.GenerateRandom(CryptoSettings.SymmetricAlgorithm.BlockLength); return new SymmetricEncryptionVariables(key, iv); }
/// <summary> /// Symmetrically decrypts a buffer using the specified key. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <param name="data">The encrypted data and the key and IV used to encrypt it.</param> /// <returns> /// The decrypted buffer. /// </returns> public static byte[] Decrypt(this CryptoSettings cryptoProvider, SymmetricEncryptionResult data) { var symmetricKey = CryptoSettings.SymmetricAlgorithm.CreateSymmetricKey(data.Key); return WinRTCrypto.CryptographicEngine.Decrypt(symmetricKey, data.Ciphertext, data.IV); }