Skip to content

Commit

Permalink
hmac check on rsa decrypt
Browse files Browse the repository at this point in the history
  • Loading branch information
kspearrin committed Jun 19, 2017
1 parent 1e5883f commit 7823ec3
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 10 deletions.
4 changes: 3 additions & 1 deletion src/App/Enums/EncryptionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public enum EncryptionType : byte
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
}
}
9 changes: 9 additions & 0 deletions src/App/Models/CipherString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ public CipherString(string encryptedString)
}
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.");
}
Expand Down
11 changes: 11 additions & 0 deletions src/App/Services/CryptoService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,24 @@ public byte[] RsaDecryptToBytes(CipherString encyptedValue, byte[] privateKey)
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:
Expand Down
29 changes: 20 additions & 9 deletions src/App/Utilities/Crypto.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Bit.App.Models;
using PCLCrypto;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Bit.App.Utilities
Expand Down Expand Up @@ -63,19 +64,14 @@ public static byte[] RandomBytes(int length)
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));
Expand All @@ -86,16 +82,31 @@ private static byte[] ComputeMac(byte[] ctBytes, byte[] ivBytes, byte[] macKey)
throw new ArgumentNullException(nameof(ivBytes));
}

return ComputeMac(ivBytes.Concat(ctBytes), macKey);
}

public static byte[] ComputeMac(IEnumerable<byte> 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);
Expand Down

0 comments on commit 7823ec3

Please sign in to comment.