我在Java中使用 bouncy castle 提供程序进行密钥解包时使用以下代码:
private static byte[] unwrapKey(byte[] toUnwrap, String key) throws Exception {
byte[] decoded = Base64.decode(toUnwrap);
if (decoded == null || decoded.length <= 16) {
throw new RuntimeException("Bad input data.");
}
byte[] salt = new byte[16];
byte[] wrappedKey = new byte[decoded.length - 16];
System.arraycopy(decoded, 0, salt, 0, 16);
System.arraycopy(decoded, 16, wrappedKey, 0, decoded.length - 16);
PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
SecretKey wrapperKey = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC").generateSecret(pbeKeySpec);
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 10);
Cipher decCipher = Cipher.getInstance("AES/GCM/NoPadding", bcProvider);
decCipher.init(Cipher.UNWRAP_MODE, wrapperKey, parameterSpec);
return decCipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY).getEncoded();
}
现在,我需要在C#
中做同样的事情。问题是即使有一个BC到C#的端口,我仍然无法使其工作。尝试了不同的事情,并总是得到一些例外。
例如,此代码在最后一行引发“pad block corrupted”异常:
byte[] decoded = Convert.FromBase64String(toUnwrap);
if (decoded == null || decoded.Length <= 16) {
throw new System.ArgumentException("Bad input data", "toUnwrap");
}
byte[] salt = new byte[16];
byte[] wrappedKey = new byte[decoded.Length - 16];
Array.Copy(decoded, 0, salt, 0, 16);
Array.Copy(decoded, 16, wrappedKey, 0, decoded.Length - 16);
int iterationCount = 10;
String alg = "PBEWithSHA256And256BitAES-CBC-BC";
Asn1Encodable defParams = PbeUtilities.GenerateAlgorithmParameters(alg, salt, iterationCount);
char[] password = key.ToCharArray();
IWrapper wrapper = WrapperUtilities.GetWrapper(alg);
ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(alg, password, defParams);
wrapper.Init(false, parameters);
byte[] pText = wrapper.Unwrap(wrappedKey, 0, wrappedKey.Length);
return pText.ToString();
我怀疑C#默认使用不同类型的填充,但不知道如何在Java代码中强制使用“NoPadding”。
我不确定,如果JAVA代码使用rfc3994是否是这种情况,因为在RFC中你需要提供IV,而这里有一个盐,但没有IV。
我想知道是否有人之前做过,如果有的话,那将是c#analogy。
答案 0 :(得分:0)
我终于明白了:
public static String unwrapKey(String toUnwrap, String key)
{
byte[] decoded = Convert.FromBase64String(toUnwrap);
if (decoded == null || decoded.Length <= 16)
{
throw new System.ArgumentException("Bad input data", "toUnwrap");
}
byte[] salt = new byte[16];
byte[] wrappedKey = new byte[decoded.Length - 16];
Array.Copy(decoded, 0, salt, 0, 16);
Array.Copy(decoded, 16, wrappedKey, 0, decoded.Length - 16);
int iterationCount = 10;
String algSpec = "AES/GCM/NoPadding";
String algName = "PBEWithSHA256And256BitAES-CBC-BC";
Asn1Encodable defParams = PbeUtilities.GenerateAlgorithmParameters(algName, salt, iterationCount);
char[] password = key.ToCharArray();
IWrapper wrapper = WrapperUtilities.GetWrapper(algSpec);
ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(algName, password, defParams);
wrapper.Init(false, parameters);
byte[] keyText = wrapper.Unwrap(wrappedKey, 0, wrappedKey.Length);
return Convert.ToBase64String(keyText);
}
这与上面的JAVA代码完全相同。