From 7823ec3fc8c0691884e55c45687feaf12e86d8c8 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 19 Jun 2017 11:57:37 -0400 Subject: [PATCH] hmac check on rsa decrypt --- src/App/Enums/EncryptionType.cs | 4 +++- src/App/Models/CipherString.cs | 9 +++++++++ src/App/Services/CryptoService.cs | 11 +++++++++++ src/App/Utilities/Crypto.cs | 29 ++++++++++++++++++++--------- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/App/Enums/EncryptionType.cs b/src/App/Enums/EncryptionType.cs index 885d873d5..cfa153462 100644 --- a/src/App/Enums/EncryptionType.cs +++ b/src/App/Enums/EncryptionType.cs @@ -6,6 +6,8 @@ AesCbc128_HmacSha256_B64 = 1, AesCbc256_HmacSha256_B64 = 2, Rsa2048_OaepSha256_B64 = 3, - Rsa2048_OaepSha1_B64 = 4 + Rsa2048_OaepSha1_B64 = 4, + Rsa2048_OaepSha256_HmacSha256_B64 = 5, + Rsa2048_OaepSha1_HmacSha256_B64 = 6 } } diff --git a/src/App/Models/CipherString.cs b/src/App/Models/CipherString.cs index cebf6c12a..808388985 100644 --- a/src/App/Models/CipherString.cs +++ b/src/App/Models/CipherString.cs @@ -63,6 +63,15 @@ namespace Bit.App.Models } CipherText = encPieces[0]; break; + case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: + case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: + if(encPieces.Length != 2) + { + throw new ArgumentException("Malformed encPieces."); + } + CipherText = encPieces[0]; + Mac = encPieces[1]; + break; default: throw new ArgumentException("Unknown encType."); } diff --git a/src/App/Services/CryptoService.cs b/src/App/Services/CryptoService.cs index e853398ab..044a98856 100644 --- a/src/App/Services/CryptoService.cs +++ b/src/App/Services/CryptoService.cs @@ -323,13 +323,24 @@ namespace Bit.App.Services throw new ArgumentNullException(nameof(privateKey)); } + if(EncKey?.MacKey != null && !string.IsNullOrWhiteSpace(encyptedValue.Mac)) + { + var computedMacBytes = Crypto.ComputeMac(encyptedValue.CipherTextBytes, EncKey.MacKey); + if(!Crypto.MacsEqual(EncKey.MacKey, computedMacBytes, encyptedValue.MacBytes)) + { + throw new InvalidOperationException("MAC failed."); + } + } + IAsymmetricKeyAlgorithmProvider provider = null; switch(encyptedValue.EncryptionType) { case EncryptionType.Rsa2048_OaepSha256_B64: + case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: provider = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaOaepSha256); break; case EncryptionType.Rsa2048_OaepSha1_B64: + case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: provider = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaOaepSha1); break; default: diff --git a/src/App/Utilities/Crypto.cs b/src/App/Utilities/Crypto.cs index 08ca50c73..0d850ff35 100644 --- a/src/App/Utilities/Crypto.cs +++ b/src/App/Utilities/Crypto.cs @@ -1,6 +1,7 @@ using Bit.App.Models; using PCLCrypto; using System; +using System.Collections.Generic; using System.Linq; namespace Bit.App.Utilities @@ -63,19 +64,14 @@ namespace Bit.App.Utilities return WinRTCrypto.CryptographicBuffer.GenerateRandom(length); } - private static string ComputeMacBase64(byte[] ctBytes, byte[] ivBytes, byte[] macKey) + public static string ComputeMacBase64(byte[] ctBytes, byte[] ivBytes, byte[] macKey) { var mac = ComputeMac(ctBytes, ivBytes, macKey); return Convert.ToBase64String(mac); } - private static byte[] ComputeMac(byte[] ctBytes, byte[] ivBytes, byte[] macKey) + public static byte[] ComputeMac(byte[] ctBytes, byte[] ivBytes, byte[] macKey) { - if(macKey == null) - { - throw new ArgumentNullException(nameof(macKey)); - } - if(ctBytes == null) { throw new ArgumentNullException(nameof(ctBytes)); @@ -86,16 +82,31 @@ namespace Bit.App.Utilities throw new ArgumentNullException(nameof(ivBytes)); } + return ComputeMac(ivBytes.Concat(ctBytes), macKey); + } + + public static byte[] ComputeMac(IEnumerable dataBytes, byte[] macKey) + { + if(macKey == null) + { + throw new ArgumentNullException(nameof(macKey)); + } + + if(dataBytes == null) + { + throw new ArgumentNullException(nameof(dataBytes)); + } + var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256); var hasher = algorithm.CreateHash(macKey); - hasher.Append(ivBytes.Concat(ctBytes).ToArray()); + hasher.Append(dataBytes.ToArray()); var mac = hasher.GetValueAndReset(); return mac; } // Safely compare two MACs in a way that protects against timing attacks (Double HMAC Verification). // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ - private static bool MacsEqual(byte[] macKey, byte[] mac1, byte[] mac2) + public static bool MacsEqual(byte[] macKey, byte[] mac1, byte[] mac2) { var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256); var hasher = algorithm.CreateHash(macKey);