Reputation: 33
Trying to do AES decrypt the data using BounceCastle, getting mac check in GCM failed error at line: output = cipher.DoFinal(cipherData);
https://github.com/psraju1/CSharpApplePayDecrypter for full code
Error:
mac check in GCM failed
BouncyCastle.Crypto
at Org.BouncyCastle.Crypto.Modes.GcmBlockCipher.DoFinal(Byte[] output, Int32 outOff)
at Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.DoFinal(Byte[] output, Int32 outOff)
at Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.DoFinal(Byte[] input, Int32 inOff, Int32 inLen)
at Org.BouncyCastle.Crypto.BufferedCipherBase.DoFinal(Byte[] input)
at ApplePayDecrypter.ApplePay.DoDecrypt(Byte[] cipherData, Byte[] encryptionKeyBytes) in ApplePayDecrypter.cs:line 107
Code:
protected byte[] RestoreSymmertricKey(byte[] sharedSecretBytes)
{
byte[] merchantIdentifier = GetHashSha256Bytes("");//applePayRequest.MerchantIdentifier);
ConcatenationKdfGenerator generator = new ConcatenationKdfGenerator(new Sha256Digest());
byte[] COUNTER = { 0x00, 0x00, 0x00, 0x01 };
byte[] algorithmIdBytes = Encoding.UTF8.GetBytes((char)0x0d + "id-aes256-GCM");
byte[] partyUInfoBytes = Encoding.UTF8.GetBytes("Apple");
byte[] partyVInfoBytes = merchantIdentifier;
byte[] otherInfoBytes = Combine(Combine(algorithmIdBytes, partyUInfoBytes), COUNTER);//, partyVInfoBytes);
generator.Init(new KdfParameters(sharedSecretBytes, otherInfoBytes));
byte[] encryptionKeyBytes = new byte[16];
generator.GenerateBytes(encryptionKeyBytes, 0, encryptionKeyBytes.Length);
return encryptionKeyBytes;
}
private byte[] DoDecrypt(byte[] cipherData, byte[] encryptionKeyBytes)
{
byte[] output;
try
{
KeyParameter keyparam = ParameterUtilities.CreateKeyParameter("AES", encryptionKeyBytes);
ParametersWithIV parameters = new ParametersWithIV(keyparam, symmetricIv);
IBufferedCipher cipher = GetCipher();
cipher.Init(false, parameters);
try
{
output = cipher.DoFinal(cipherData);
}
catch (Exception ex)
{
throw new ApplicationException("Invalid Data");
}
}
catch (Exception ex)
{
throw new ApplicationException("There was an error occured when decrypting message.");
}
return output;
}
public IBufferedCipher GetCipher()
{
return CipherUtilities.GetCipher("AES/GCM/NoPadding");
}
private static byte[] GetHashSha256Bytes(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
SHA256Managed hashstring = new SHA256Managed();
byte[] hash = hashstring.ComputeHash(bytes);
return hash;
}
protected static byte[] Combine(byte[] first, byte[] second)
{
byte[] ret = new byte[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
Actually, I'm trying to decrypt this for ApplePay, and converting sample Java code to C#. Let me know, if you want to take a look at JAVA code
Here is the full code in JAVA & C#. Please check it.
https://github.com/psraju1/CSharpApplePayDecrypter
Upvotes: 0
Views: 6475
Reputation: 491
I had the same problem, so I forked the repo above, made the necessary changes, cleaned it up and pushed it to GitHub.
https://github.com/fscopel/CSharpApplePayDecrypter
Happy Coding!
Upvotes: 1
Reputation: 103
After following Lou's advice, I needed two more changes to get it to work.
RestoreSymmetricKey now looks like this:
protected byte[] RestoreSymmertricKey(byte[] sharedSecretBytes)
{
byte[] merchantIdentifier = ExtractMIdentifier();
ConcatenationKdfGenerator generator = new ConcatenationKdfGenerator(new Sha256Digest());
byte[] algorithmIdBytes = Encoding.UTF8.GetBytes((char)0x0d + "id-aes256-GCM");
byte[] partyUInfoBytes = Encoding.UTF8.GetBytes("Apple");
byte[] partyVInfoBytes = merchantIdentifier;
byte[] otherInfoBytes = Combine(Combine(algorithmIdBytes, partyUInfoBytes), partyVInfoBytes);
generator.Init(new KdfParameters(sharedSecretBytes, otherInfoBytes));
byte[] encryptionKeyBytes = new byte[32];
generator.GenerateBytes(encryptionKeyBytes, 0, encryptionKeyBytes.Length);
return encryptionKeyBytes;
}
Upvotes: 0
Reputation: 1
had the same problem. Please try not to hash the merchant identifier. It is already hashed. And ignore the first two bytes of it, before set to partyVInfo. When you get merchantIdentifier from certifcate there is ".@" at the beginning of the hash. This must be deleted
byte[] partyVInfo = ExtractMIdentifier();
private byte[] ExtractMIdentifier()
{
X509Certificate2 merchantCertificate = InflateCertificate();
byte[] merchantIdentifierTlv = merchantCertificate.Extensions["1.2.840.113635.100.6.32"].RawData;
byte[] merchantIdentifier = new byte[64];
Buffer.BlockCopy(merchantIdentifierTlv, 2, merchantIdentifier, 0, 64);
return Hex.Decode(Encoding.ASCII.GetString(merchantIdentifier));
}
Party V Info The SHA-256 hash of the merchant identifier. This value is a fixed-length bit string.
I don't use SHA-256 hash and deleted the first two bytes of the merchant identifier. Now it works.
Upvotes: 0