解密Rijndael 256(来自PhP)在java中编码的文本信息很少

时间:2012-03-23 12:35:40

标签: java aes encryption private-key

我有一些来自外部方的数据,根据它们加密:'Rijndeal 256 with private key'

除了这些记录外,还有一个公钥和私钥证书,看起来像RSA证书。

从我到目前为止所学到的,似乎使用证书加密的常用方法是在初始化向量中生成“秘密密钥”或某种类型,并将其用于加密文本。所以我认为这可能就是他们所做的(数据是由PHP应用程序加密的)

我正在尝试使用javax.crypto.Cipher解密此文本,但我认为我可能需要有关特定加密的更多信息,但我真的不知道要求哪些信息,并认为它可能是“默认选项”可能会奏效。 (与供应方的沟通既困难又缓慢。)

我目前正在使用以下代码获取私钥:

  InputStreamReader ir = new InputStreamReader(the_inputstream_for_the_private_key_record);
   Security.addProvider(new BouncyCastleProvider());
   pemr = new PEMReader(ir);
   Object o = pemr.readObject();
   keyPair kp = (KeyPair) o;
   return kp.getPrivate();

这似乎有效,因为我得到一个实例化的PrivateKey对象而没有错误,toString看起来像:

RSA Private CRT Key
            modulus: c98faa50ba69<trimmed>
    public exponent: 10001
   private exponent: bb889fbe5cb2a6763f...<trimmed>
             primeP: eb73e85dc636f5751b...<trimmed>
             primeQ: db269bd603a2b81fc9...<trimmed>
     primeExponentP: 85b9f111c190595cc8...<trimmed>
     primeExponentQ: a66d59a75bb77530de...<trimmed>
     crtCoefficient: 79415b078c4c229746...<trimmed>

对于每条记录,我也有如下条目:

{
"decryptedLength":128389,
"symKeyLength":32,
"symKey":"SImE8VnSZaAu1Ve...<trimmed (this is always 685 chars long) >...ayaJcnpSeOqAGM7q="
}

基本上这是我有点卡住的地方。 我的猜测是'symkey'值是用RSA加密的,而RSA在解密后会产生AES部分的secretKey,但如果我尝试:

Cipher rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.DECRYPT_MODE, key);
byte[] b = rsaCipher.doFinal('symkey'.getbytes());

这让我觉得“javax.crypto.IllegalBlockSizeException:数据不能超过512个字节”,这似乎是合乎逻辑的,因为这个字符串长度为685个字符

我可能错过了一些非常明显的东西...... 任何建议都表示赞赏。

3 个答案:

答案 0 :(得分:2)

猜猜,但我认为价值

"symKey":"SImE8VnSZaAu1Ve...<trimmed (this is always 685 chars long) >...ayaJcnpSeOqAGM7q="

是使用4096位公钥从RSA加密的base64编码输出。您需要先将base64解码为byte []数组,然后使用私钥解密,其结果将是256位密钥。请注意,“Rijndael 256”是不明确的,因为Rijndael既支持256位块大小,也支持256位密钥大小。

答案 1 :(得分:1)

根据GregS的回答,我最终得到了这个。 (添加答案,以防其他人需要解密类似的PHP编码的东西)。

第一部分是从metaData字符串解密de symmetricKey(“symkey”) 这是因为Greg注意到Base64编码的RSA加密密钥,它被解码如下:

Cipher rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptedRijndaelKey = Base64.decodeBase64(base64EncodedSymetricKey); //from the metaData
byte[] rijndaelKeyBytes = rsaCipher.doFinal(encryptedRijndaelKey);

然后使用此Rijndael密钥解密实际加密数据,如下所示:

RijndaelEngine rijndaelEngine = new RijndaelEngine(256); // *1 *2
KeyParameter keyParam = new KeyParameter(rijndaelKeyBytes)
rijndaelEngine.init(false, keyParam);  //false == decrypt
PaddedBufferedBlockCipher bbc = new PaddedBufferedBlockCipher(rijndaelEngine, new ZeroBytePadding()); // *3 

byte[] decryptedBytes = new byte[decryptedLenght]; //from the storageOptions string
int processed = bbc.processBytes(inputBytes, 0, inputBytes.length, decryptedBytes, 0);
bbc.doFinal(decryptedBytes, processed);

* 1因为Sun JCA仅支持具有128位密钥的公共AES,所以我必须使用不同的提供程序(BouncyCastle)。 * 2显然块大小也是256位(跟踪和错误) * 3显然没有使用填充,因此ZeroPadding用于填充(再次跟踪和错误)。

答案 2 :(得分:0)

symKey值是Base64编码的,必须先解码才能对其进行私钥解密。此外,对称加密听起来像是AES-256。 (AES基于Rijndael密码)。