我有一些来自外部方的数据,根据它们加密:'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个字符
我可能错过了一些非常明显的东西...... 任何建议都表示赞赏。
答案 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)
第一部分是从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密码)。