要转换为PrivateKey Object的字节



我的JKS (Java Key Store)文件中有一个对称密钥,我想用对称密钥包装我的私钥。

我再次使用wrappedBytes到PrivateKey对象。最后我想要KeyPair对象

下面的代码给出了以下错误消息:

java.security.spec。InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=125, too big.**

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);;
}

我该如何解决这个问题?

在您的示例中,wrappedBytes不是pkcs# 8格式。它只是一些AES加密的块——本质上是随机数据——没有编码结构。

如果您想创建一个加密的 pkcs# 8(正式名称为EncryptedPrivateKeyInfo),您将需要一个库来处理它。您尝试使用的内置API仅处理其明文有效载荷PrivateKeyInfo(如其文档中所述)。

包装器没有太多内容,您可以自己编写必要的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);
  }
}

相关内容

最新更新