Cryptography 如何使用使用Libgcrypt原始标志加密的C#Bouncy Castle解密AES密钥

Cryptography 如何使用使用Libgcrypt原始标志加密的C#Bouncy Castle解密AES密钥,cryptography,aes,rsa,bouncycastle,libgcrypt,Cryptography,Aes,Rsa,Bouncycastle,Libgcrypt,摘要: 我正在尝试解密(并最终加密并返回)AES128加密的文件。AES密钥使用libcrypt的RSA提供程序加密。当我尝试在Windows 7上使用C#&BouncyCastle解密AESKey时,调用“ProcessBlock”时会抛出一个“block truncated”错误。我已经尝试将数据转换为BigEndian,当我尝试创建RsaKeyParameters时,会得到一个“无效的RSA指数” 加密是在linux系统上使用libgcrypt 1.2x完成的。我认为这是一个填充问题,因为

摘要: 我正在尝试解密(并最终加密并返回)AES128加密的文件。AES密钥使用libcrypt的RSA提供程序加密。当我尝试在Windows 7上使用C#&BouncyCastle解密AESKey时,调用“ProcessBlock”时会抛出一个“block truncated”错误。我已经尝试将数据转换为BigEndian,当我尝试创建RsaKeyParameters时,会得到一个“无效的RSA指数”

加密是在linux系统上使用libgcrypt 1.2x完成的。我认为这是一个填充问题,因为这段代码表明没有使用填充。
gcry\u sexp\u build(&PlainKeyExp,NULL,“(数据(原始标志)(值%s))”,AESKey)

很遗憾,我无法更改原始系统。我在下面提供代码示例和键以提供帮助。在过去的三天里,这让我发疯。我已经搜索了interwebz,还没有找到解决方案。 提前感谢您的帮助

原始代码段

static const char RSAPrivateKey[] =
"(private-key"
" (rsa"
"  (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
"      2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
"      ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
"      891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)"
"  (e #010001#)"
"  (d #046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b11"
"      7d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bd"
"      c543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21"
"      c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781#)"
"  (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
"      fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)"
"  (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9"
"      35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)"
"  (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
"      ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))";

Error = gcry_sexp_sscan(&PublicKey, NULL, RSAPublicKey, strlen(RSAPublicKey));
if ( Error ) { goto Return; }

Error = gcry_sexp_sscan(&PrivateKey, NULL, RSAPrivateKey, strlen(RSAPrivateKey));
if ( Error ) { goto Return; }

Error = gcry_sexp_build(&PlainKeyExp, NULL, "(data (flags raw) (value %s))", AESKey );
gpg_strerror_r(Error, Output, 500);
if ( Error ) { goto Return; }

Error = gcry_pk_encrypt(&Encrypted, PlainKeyExp, PublicKey);
if ( Error ) { goto Return; }

if ( gcry_sexp_sprint(Encrypted, GCRYSEXP_FMT_CANON, Output, 500) <= 0 ) { Error = TRUE; goto Return; }
Encrypted = gcry_sexp_find_token(Encrypted, "a", 0);
if ( Encrypted == NULL ) { Error = TRUE; goto Return; }

if ( gcry_sexp_sprint(Encrypted, GCRYSEXP_FMT_ADVANCED, Output, 500) <= 0 ) { Error = TRUE; goto Return; }
if ( strtok(Output, "#") != NULL ) {
    Output2 = strtok(NULL, "#");
    if ( Output2 != NULL ) { sprintf(EncryptedKey,"%s", Output2); }
    else { Error = TRUE; }
} else { Error = TRUE; }
var modulus ="00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251";

var privateExponent ="046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b117d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bdc543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781";

var encryptedAesKey ="77FD84196959DDE3C367952B3C25B34582B489A705FB3C61D69D04DDA16B011F6358F32834DD76BF81A1DF28106F377FF1125F91CA39BB92D293B8F5134C15C17DE1157390723301A01B938489E04DA1D8D4A70511F0FF2508984710CEB3F18D4BA929C18487A0977011BDE169DBBF3047646FBFBC50ED5A02FC40E53E59B8CD";

try
{
  // Convert to biginteger
  var bcMod = new Org.BouncyCastle.Math.BigInteger(Hex.Decode(modulus));
  var bcPrivateExponent = new Org.BouncyCastle.Math.BigInteger(Hex.Decode(privateExponent));
  byte[] decodedAesKey = Hex.Decode(encryptedAesKey);

  // Init bouncyCastle
  var privParameters = new RsaKeyParameters(true, bcMod, bcPrivateExponent);
  var eng = new Pkcs1Encoding(new RsaEngine());
  eng.Init(false, privParameters);

  var ret = eng.ProcessBlock(decodedAesKey, 0, 128);
}
catch (Exception e)
{
  Console.WriteLine(e);
}

答案就是删除
新的Pkcs1Encoding()
构造函数调用,并直接使用
RsaEngine
。如果没有填充,则无需删除或验证它


请注意,填充是创建基于RSA的安全密文的必要条件。因此,这可以克服兼容性问题,但应该立即更换系统。

答案只是删除
新的Pkcs1Encoding()
构造函数调用,并直接使用
RsaEngine
。如果没有填充,则无需删除或验证它


请注意,填充是创建基于RSA的安全密文的必要条件。因此,这可以解决兼容性问题,但应该立即更换系统。

还要注意,PKCS#1v1.5填充不安全–您应该使用OAEP。@ntoskrnl是的,PKCS#1.5没有OAEP填充安全。与无填充相比,PKSC#1 v1.5填充非常安全:)谢谢@owlstead!答案就在我眼前!我同意并理解这是“不太理想的”,但事实就是如此。还要注意。。有时,加密的AESKey有前导零,需要在解密之前删除。原则上,RSA加密将数字作为密文传递。通常,它被编码为一个字节数组,长度与键相同(答案当然总是在模内)。对于填充加密方法,这意味着答案总是关于模的大小。它变小一个字节的概率大约是1/192,变小两个字节的概率大约是1/192乘以256。同样,对于解密,密文被视为一个数字。领先零应该不是问题。如果您有超过2/3个前导零,那么您就有麻烦了。还要注意,PKCS#1v1.5填充不安全–您应该使用OAEP。@ntoskrnl是的,PKCS#1.5没有OAEP填充那么安全。与无填充相比,PKSC#1 v1.5填充非常安全:)谢谢@owlstead!答案就在我眼前!我同意并理解这是“不太理想的”,但事实就是如此。还要注意。。有时,加密的AESKey有前导零,需要在解密之前删除。原则上,RSA加密将数字作为密文传递。通常,它被编码为一个字节数组,长度与键相同(答案当然总是在模内)。对于填充加密方法,这意味着答案总是关于模的大小。它变小一个字节的概率大约是1/192,变小两个字节的概率大约是1/192乘以256。同样,对于解密,密文被视为一个数字。领先零应该不是问题。如果你有超过2/3个前导零,那么你就有麻烦了。