【问题标题】:C# Key wrap/unwrap PBEWITHSHA256AND256BITAES CBCC# 密钥包装/解包 PBEWITHSHA256AND256BITAES CBC
【发布时间】:2013-11-18 08:22:45
【问题描述】:

我在 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损坏”异常:

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# 的类比是什么。

【问题讨论】:

  • 您会遇到哪些例外情况?
  • 在问题中添加了代码。

标签: c# java cryptography aes bouncycastle


【解决方案1】:

我终于明白了:

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 代码完全相同。

【讨论】:

    猜你喜欢
    • 2015-10-19
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    相关资源
    最近更新 更多