要转换为 PrivateKey 对象的字节
Posted
技术标签:
【中文标题】要转换为 PrivateKey 对象的字节【英文标题】:bytes to be converted into PrivateKey Object 【发布时间】:2015-07-08 11:54:45 【问题描述】:我的 JKS(Java 密钥存储)文件中有一个对称密钥,我想用一个对称密钥包装我的私钥。
我再次使用 WrappedBytes 到 PrivateKey 对象。最后我想要 KeyPair 对象。
以下代码给出以下错误消息:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=125, 太大。**
public KeyPair wrapPrivateKeyWithSymmetricKey(KeyPair keyPair)
try
PrivateKey priv = keyPair.getPrivate();
SecretKey symmetricKey = "bjksabfkasdbgvkasbvkkj";//symmetricKey from jks file
//wrapping Private Key
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.WRAP_MODE, symmetricKey);
byte[] wrappedKey = cipher.wrap(priv);
//wrappedKey bytes to PrivateKey Object
KeyFactory keyFactory = KeyFactory.getInstance(priv.getAlgorithm());
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(wrappedKey);
PrivateKey privateKey2 = keyFactory.generatePrivate(privateKeySpec); //above Error Throwing in this line
return new KeyPair(keyPair.getPublic(), privateKey2);;
我该如何解决这个问题?
【问题讨论】:
欢迎来到信息安全堆栈交换!我认为这个问题更适合Stack Overflow。您可以标记您的帖子以引起版主的注意并要求迁移。为了清楚起见,您可能希望显示catch
语句中的内容。此外,它有助于显示错误发生在哪一行 - 您可以在异常附带的堆栈跟踪中找到它。祝你好运!
【参考方案1】:
在您的示例中,wrappedBytes
不是PKCS #8 格式。它只是一些没有编码结构的 AES 加密块——本质上是随机数据。
如果您想创建一个加密 PKCS #8(正式名称为EncryptedPrivateKeyInfo
),您需要一个库来处理它。您尝试使用的内置 API 仅处理其明文负载 PrivateKeyInfo
(如 its documentation 中所述)。
包装器并不多,您可以自己编写必要的 DER 编码,或者使用像 BouncyCastle. 这样的库
这是代码,使用 BouncyCastle 对 EncryptyedPrivateKeyInfo
结构进行编码和解码。 JCE 提供的无用类不起作用,因为对密钥加密算法标识符及其参数的处理不当。
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
final class PKCS8
private static final ASN1ObjectIdentifier AES = ASN1ObjectIdentifier.getInstance(NISTObjectIdentifiers.id_aes128_CBC);
static RSAPublicKey toPublic(RSAPrivateCrtKey pvt)
throws GeneralSecurityException
RSAPublicKeySpec pub = new RSAPublicKeySpec(pvt.getModulus(), pvt.getPublicExponent());
KeyFactory f = KeyFactory.getInstance("RSA");
return (RSAPublicKey) f.generatePublic(pub);
static byte[] encrypt(SecretKey secret, PrivateKey pvt)
throws Exception
Cipher enc = Cipher.getInstance("AES/CBC/PKCS5Padding");
enc.init(Cipher.WRAP_MODE, secret);
ASN1Encodable params = new DEROctetString(enc.getIV());
AlgorithmIdentifier algId = new AlgorithmIdentifier(AES, params);
byte[] ciphertext = enc.wrap(pvt);
return new EncryptedPrivateKeyInfo(algId, ciphertext).getEncoded();
static PrivateKey decrypt(SecretKey secret, byte[] pkcs8)
throws Exception
EncryptedPrivateKeyInfo info = new PKCS8EncryptedPrivateKeyInfo(pkcs8).toASN1Structure();
AlgorithmIdentifier id = info.getEncryptionAlgorithm();
byte[] iv = ((ASN1OctetString) id.getParameters()).getOctets();
Cipher dec = Cipher.getInstance("AES/CBC/PKCS5Padding");
dec.init(Cipher.UNWRAP_MODE, secret, new IvParameterSpec(iv));
return (PrivateKey) dec.unwrap(info.getEncryptedData(), "RSA", Cipher.PRIVATE_KEY);
【讨论】:
感谢您的回复,我在 BouncyCastle 中找不到同等课程。我怎样才能将wrappedBytes 放入PKCS #8。你能建议吗? 您是否使用基于密码的加密?还是您使用随机生成的SecretKey
进行加密?
我们的 jks 文件中有一个固定的密钥。我们正在使用 Secret Key 加密私钥。在我的示例程序中,我将 KeyPair 对象传递给 wrapPrivateKeyWithSymmetricKey 方法,并用 Secret Key 包装私钥,最后将 KeyPair 对象返回给该方法。如何从 WrappedBytes 获取私钥对象?你能建议吗?
@user3240160 你真的需要编码为EncryptedPrivateKeyInfo
的密钥吗?例如,您是否需要与其他一些需要 PKCS #8 密钥的软件进行互操作?您正在使用受密码保护的密钥对私钥进行加密,因此您的私钥并不比该密码更安全;您为什么不按预期将私钥直接存储在KeyStore
中?我不想为你不需要的东西提供代码。你应该解释你想要完成的什么,而不是如何你认为你应该这样做。
我有 KeyPair 对象,我正在用密钥加密私钥并再次需要 KeyPair 对象。我将序列化的 KeyPair 对象保存到数据库中。你能建议吗?以上是关于要转换为 PrivateKey 对象的字节的主要内容,如果未能解决你的问题,请参考以下文章
EC 将字符串转换为 PublicKey / PrivateKey
如何将 Byte 数组转换为 PrivateKey 或 PublicKey 类型?