我有一个加密的私钥,并且知道密码。
我需要使用Java库对其进行解密。
不过,我宁愿不要使用BouncyCastle,除非没有其他选择。根据以前的经验,有太多更改,没有足够的文档。
私钥的格式如下:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,56F3A98D9CFFA77A
X5h7SUDStF1tL16lRM+AfZb1UBDQ0D1YbQ6vmIlXiK....
.....
/KK5CZmIGw==
-----END RSA PRIVATE KEY-----
我相信关键数据是Base64编码的,因为我看到的是\r\n
64个字符。
我尝试了以下解密密钥:
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
public String decrypt(String keyDataStr, String passwordStr){
// This key data start from "X5... to =="
char [] password=passwordStr.toCharArray();
byte [] keyDataBytes=com.sun.jersey.core.util.Base64.decode(keyDataStr);
PBEKeySpec pbeSpec = new PBEKeySpec(password);
EncryptedPrivateKeyInfo pkinfo = new EncryptedPrivateKeyInfo(keyDataBytes);
SecretKeyFactory skf = SecretKeyFactory.getInstance(pkinfo.getAlgName());
Key secret = skf.generateSecret(pbeSpec);
PKCS8EncodedKeySpec keySpec = pkinfo.getKeySpec(secret);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey pk=kf.generatePrivate(keySpec);
return pk.toString();
}
我得到这个例外
java.io.IOException: DerInputStream.getLength(): lengthTag=50, too big.
at sun.security.util.DerInputStream.getLength(DerInputStream.java:561)
at sun.security.util.DerValue.init(DerValue.java:365)
at sun.security.util.DerValue.<init>(DerValue.java:294)
at javax.crypto.EncryptedPrivateKeyInfo.<init> (EncryptedPrivateKeyInfo.java:84)
我是否将正确的参数传递给EncryptedPrivateKeyInfo
构造函数?
我该如何工作?
我尝试了Ericsonn的建议,但做了一点小改动,因为我正在使用Java
7,所以我无法使用Base64.getMimeCoder(),而是使用Base64.decode,但出现此错误,我得到这样的错误,输入长度必须是多个在com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)上使用填充密码解密时的8个
static RSAPrivateKey decrypt(String keyDataStr, String ivHex, String password)
throws GeneralSecurityException, UnsupportedEncodingException
{
byte[] pw = password.getBytes(StandardCharsets.UTF_8);
byte[] iv = h2b(ivHex);
SecretKey secret = opensslKDF(pw, iv);
Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte [] keyBytes=Base64.decode(keyDataStr.getBytes("UTF-8"));
byte[] pkcs1 = cipher.doFinal(keyBytes);
/* See note for definition of "decodeRSAPrivatePKCS1" */
RSAPrivateCrtKeySpec spec = decodeRSAPrivatePKCS1(pkcs1);
KeyFactory rsa = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) rsa.generatePrivate(spec);
}
private static SecretKey opensslKDF(byte[] pw, byte[] iv)
throws NoSuchAlgorithmException
{
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(pw);
md5.update(iv);
byte[] d0 = md5.digest();
md5.update(d0);
md5.update(pw);
md5.update(iv);
byte[] d1 = md5.digest();
byte[] key = new byte[24];
System.arraycopy(d0, 0, key, 0, 16);
System.arraycopy(d1, 0, key, 16, 8);
return new SecretKeySpec(key, "DESede");
}
private static byte[] h2b(CharSequence s)
{
int len = s.length();
byte[] b = new byte[len / 2];
for (int src = 0, dst = 0; src < len; ++dst) {
int hi = Character.digit(s.charAt(src++), 16);
int lo = Character.digit(s.charAt(src++++), 16);
b[dst] = (byte) (hi << 4 | lo);
}
return b;
}
static RSAPrivateCrtKeySpec decodeRSAPrivatePKCS1(byte[] encoded)
{
ByteBuffer input = ByteBuffer.wrap(encoded);
if (der(input, 0x30) != input.remaining())
throw new IllegalArgumentException("Excess data");
if (!BigInteger.ZERO.equals(derint(input)))
throw new IllegalArgumentException("Unsupported version");
BigInteger n = derint(input);
BigInteger e = derint(input);
BigInteger d = derint(input);
BigInteger p = derint(input);
BigInteger q = derint(input);
BigInteger ep = derint(input);
BigInteger eq = derint(input);
BigInteger c = derint(input);
return new RSAPrivateCrtKeySpec(n, e, d, p, q, ep, eq, c);
}
private static BigInteger derint(ByteBuffer input)
{
byte[] value = new byte[der(input, 0x02)];
input.get(value);
return new BigInteger(+1, value);
}
private static int der(ByteBuffer input, int exp)
{
int tag = input.get() & 0xFF;
if (tag != exp)
throw new IllegalArgumentException("Unexpected tag");
int n = input.get() & 0xFF;
if (n < 128)
return n;
n &= 0x7F;
if ((n < 1) || (n > 2))
throw new IllegalArgumentException("Invalid length");
int len = 0;
while (n-- > 0) {
len <<= 8;
len |= input.get() & 0xFF;
}
return len;
}
1640是keyDataStr.length()和1228是keyBytes.length
您需要使用非标准的OpenSSL方法来获取解密密钥。然后使用它解密PKCS#1编码的密钥-您使用的 不是
PKCS#8信封。您还需要标题中的IV作为这些过程的输入。
看起来像这样:
static RSAPrivateKey decrypt(String keyDataStr, String ivHex, String password)
throws GeneralSecurityException
{
byte[] pw = password.getBytes(StandardCharsets.UTF_8);
byte[] iv = h2b(ivHex);
SecretKey secret = opensslKDF(pw, iv);
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] pkcs1 = cipher.doFinal(Base64.getMimeDecoder().decode(keyDataStr));
/* See note for definition of "decodeRSAPrivatePKCS1" */
RSAPrivateCrtKeySpec spec = decodeRSAPrivatePKCS1(pkcs1);
KeyFactory rsa = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) rsa.generatePrivate(spec);
}
private static SecretKey opensslKDF(byte[] pw, byte[] iv)
throws NoSuchAlgorithmException
{
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(pw);
md5.update(iv);
byte[] d0 = md5.digest();
md5.update(d0);
md5.update(pw);
md5.update(iv);
byte[] d1 = md5.digest();
byte[] key = new byte[24];
System.arraycopy(d0, 0, key, 0, 16);
System.arraycopy(d1, 0, key, 16, 8);
return new SecretKeySpec(key, "DESede");
}
private static byte[] h2b(CharSequence s)
{
int len = s.length();
byte[] b = new byte[len / 2];
for (int src = 0, dst = 0; src < len; ++dst) {
int hi = Character.digit(s.charAt(src++), 16);
int lo = Character.digit(s.charAt(src++), 16);
b[dst] = (byte) (hi << 4 | lo);
}
return b;
}
这已经是很多代码,因此我将链接到该方法定义的另一个答案。decodeRSAPrivatePKCS1()
我有一个加密的私钥,我知道密码。 我需要用Java库解密它。 不过,我不想使用BouncyCastle,除非没有其他选择。根据之前的经验,变更太多,文档不足。 私钥的格式如下: 我相信密钥数据是Base64编码的,因为我在64个字符后看到。 我尝试了以下方法来解密密钥: 我得到这个例外 我是否将正确的参数传递给构造函数? 我怎样才能做到这一点? 我尝试了Ericsonn的建议,有一个小的变化,因为
我一直在搜索,但我似乎找不到一个简单的方法解密使用RSA。 我生成了一个公钥和私钥,它们存储在两个单独的文件中,并且是XML格式的。使用FromXmlString将公钥关联到RSACryptoServiceProvider对象,然后加密一个字符串,这一点没有问题。当我试图解密一个加密的字符串时,我的困惑就来了。我不确定如何将私钥数据与RSACryptoServiceProvider关联,以便使用D
今天,我写了一些代码,用AES加密字符串,用RSA加密密钥。当我试图解密所有内容时,Java给了我一个BadPaddingException。这是我的代码: 测验爪哇: 钥匙匠。爪哇: 加密机。爪哇: 解密程序。爪哇:
问题内容: 我正在尝试使用RSA私钥加密某些内容。 我遵循以下示例:http : //www.junkheap.net/content/public_key_encryption_java, 但将其转换为使用私钥而不是公共密钥。遵循该示例,我认为我需要做的是: 读取DER格式的私钥 生成PCKS8EncodedKeySpec 从KeyFactory调用generatePrivate()获得一个私钥
我有一个公钥和一个私钥,还有一个字符串,我想要解密。 公钥的格式如下: 私钥的格式如下: 我要解密的字符串已经使用公钥加密,然后我需要使用私钥解密它。
本章是前一章的延续,我们使用RSA算法逐步实现加密,并详细讨论它。 用于解密密文的函数如下 - def decrypt(ciphertext, priv_key): cipher = PKCS1_OAEP.new(priv_key) return cipher.decrypt(ciphertext) 对于公钥加密或非对称密钥加密,重要的是保持两个重要的功能,即Authenticati