internal static void ValidateEncryptionAlgorithm(KeyEncryptionKeyAlgorithm encryptionAlgorithm) { if (encryptionAlgorithm != KeyEncryptionKeyAlgorithm.RSA_OAEP) { throw new MicrosoftDataEncryptionException(InvalidKeyAlgorithm.FormatInvariant(encryptionAlgorithm, KeyEncryptionKeyAlgorithm.RSA_OAEP.ToString())); } }
/// <summary> /// This function uses the asymmetric key specified by the key path /// and encrypts an unencrypted data encryption key with RSA encryption algorithm. /// </summary> /// <param name="encryptionKeyId">Identifier of an asymmetric key in Azure Key Vault</param> /// <param name="algorithm">The encryption algorithm.</param> /// <param name="key">The plaintext key.</param> /// <returns>Encrypted data encryption key</returns> public override byte[] WrapKey(string encryptionKeyId, KeyEncryptionKeyAlgorithm algorithm, byte[] key) { // Validate the input parameters ValidateNonEmptyAKVPath(encryptionKeyId, isSystemOp: true); ValidateEncryptionAlgorithm(algorithm); key.ValidateNotNull(nameof(key)); ValidateDataEncryptionKeyNotEmpty(key); // Also validates whether the key is RSA one or not and then get the key size KeyCryptographer.AddKey(encryptionKeyId); int keySizeInBytes = KeyCryptographer.GetKeySize(encryptionKeyId); // Construct the encryptedDataEncryptionKey // Format is // firstVersion + keyPathLength + ciphertextLength + keyPath + ciphertext + signature // Get the Unicode encoded bytes of cultureinvariant lower case keyEncryptionKeyPath byte[] keyEncryptionKeyPathBytes = Encoding.Unicode.GetBytes(encryptionKeyId.ToLowerInvariant()); byte[] keyPathLength = BitConverter.GetBytes((short)keyEncryptionKeyPathBytes.Length); // Encrypt the plain text byte[] cipherText = KeyCryptographer.WrapKey(keyWrapAlgorithm, key, encryptionKeyId); byte[] cipherTextLength = BitConverter.GetBytes((short)cipherText.Length); if (cipherText.Length != keySizeInBytes) { throw new MicrosoftDataEncryptionException(CipherTextLengthMismatch); } // Compute message // SHA-2-256(version + keyPathLength + ciphertextLength + keyPath + ciphertext) byte[] message = firstVersion.Concat(keyPathLength).Concat(cipherTextLength).Concat(keyEncryptionKeyPathBytes).Concat(cipherText).ToArray(); // Sign the message byte[] signature = KeyCryptographer.SignData(message, encryptionKeyId); if (signature.Length != keySizeInBytes) { throw new MicrosoftDataEncryptionException(HashLengthMismatch); } ValidateSignature(encryptionKeyId, message, signature); return(message.Concat(signature).ToArray()); }
/// <summary> /// This function uses the asymmetric key specified by the key path /// and decrypts an encrypted data dencryption key with RSA encryption algorithm. /// </summary> /// <param name="encryptionKeyId">Identifier of an asymmetric key in Azure Key Vault</param> /// <param name="algorithm">The encryption algorithm.</param> /// <param name="encryptedKey">The ciphertext key.</param> /// <returns>Plain text data encryption key</returns> public override byte[] UnwrapKey(string encryptionKeyId, KeyEncryptionKeyAlgorithm algorithm, byte[] encryptedKey) { // Validate the input parameters ValidateNonEmptyAKVPath(encryptionKeyId, isSystemOp: true); ValidateEncryptionAlgorithm(algorithm); encryptedKey.ValidateNotNull(nameof(encryptedKey)); encryptedKey.ValidateNotEmpty(nameof(encryptedKey)); ValidateVersionByte(encryptedKey[0], firstVersion[0]); return(GetOrCreateDataEncryptionKey(encryptedKey.ToHexString(), DecryptEncryptionKey)); byte[] DecryptEncryptionKey() { // Also validates whether the key is RSA one or not and then get the key size KeyCryptographer.AddKey(encryptionKeyId); int keySizeInBytes = KeyCryptographer.GetKeySize(encryptionKeyId); // Get key path length int currentIndex = firstVersion.Length; ushort keyPathLength = BitConverter.ToUInt16(encryptedKey, currentIndex); currentIndex += sizeof(ushort); // Get ciphertext length ushort cipherTextLength = BitConverter.ToUInt16(encryptedKey, currentIndex); currentIndex += sizeof(ushort); // Skip KeyPath // KeyPath exists only for troubleshooting purposes and doesnt need validation. currentIndex += keyPathLength; // validate the ciphertext length if (cipherTextLength != keySizeInBytes) { throw new MicrosoftDataEncryptionException(InvalidCiphertextLengthTemplate.FormatInvariant(cipherTextLength, keySizeInBytes, encryptionKeyId)); } // Validate the signature length int signatureLength = encryptedKey.Length - currentIndex - cipherTextLength; if (signatureLength != keySizeInBytes) { throw new MicrosoftDataEncryptionException(InvalidSignatureLengthTemplate.FormatInvariant(signatureLength, keySizeInBytes, encryptionKeyId)); } // Get ciphertext byte[] cipherText = encryptedKey.Skip(currentIndex).Take(cipherTextLength).ToArray(); currentIndex += cipherTextLength; // Get signature byte[] signature = encryptedKey.Skip(currentIndex).Take(signatureLength).ToArray(); // Compute the message to validate the signature byte[] message = encryptedKey.Take(encryptedKey.Length - signatureLength).ToArray(); if (null == message) { throw new MicrosoftDataEncryptionException(NullHash); } if (!KeyCryptographer.VerifyData(message, signature, encryptionKeyId)) { throw new MicrosoftDataEncryptionException(InvalidSignatureTemplate.FormatInvariant(encryptionKeyId)); } return(KeyCryptographer.UnwrapKey(keyWrapAlgorithm, cipherText, encryptionKeyId)); } }
public override byte[] WrapKey(string masterKeyPath, KeyEncryptionKeyAlgorithm encryptionAlgorithm, byte[] columnEncryptionKey) { throw new NotImplementedException(); }
public override byte[] UnwrapKey(string masterKeyPath, KeyEncryptionKeyAlgorithm encryptionAlgorithm, byte[] encryptedColumnEncryptionKey) { return(GetOrCreateDataEncryptionKey(encryptedColumnEncryptionKey.ToHexString(), DecryptEncryptionKey));
public override byte[] WrapKey(string masterKeyPath, KeyEncryptionKeyAlgorithm encryptionAlgorithm, byte[] key) { byte[] encryptedkey = key.Select(b => (byte)(b + 1)).ToArray(); return(encryptedkey); }
public override byte[] UnwrapKey(string masterKeyPath, KeyEncryptionKeyAlgorithm encryptionAlgorithm, byte[] encryptedKey) { byte[] plainkey = encryptedKey.Select(b => (byte)(b - 1)).ToArray(); return(plainkey); }