【问题标题】:org.bouncycastle.asn1.DLSequence cannot be cast to org.bouncycastle.asn1.ASN1Integerorg.bouncycastle.asn1.DLSequence 不能转换为 org.bouncycastle.asn1.ASN1Integer
【发布时间】:2015-04-03 18:09:05
【问题描述】:

我正在尝试使用 BouncyCastle 类来加密和解密密码。我编写了一个测试程序并生成了 PEM 格式和 DER 格式的测试密钥/证书。我可以将密钥/证书读入我的程序并获取公钥并加密一个值。当我尝试设置解密该值时,在创建 AsymmetricKeyParameter 时出现错误“org.bouncycastle.asn1.DLSequence cannot be cast to org.bouncycastle.asn1.ASN1Integer”。似乎当我尝试通过执行 cert.getEncoded() 从证书中提取数据时,它也会提取标头值。我尝试仅读取文件并删除 BEGIN 和 END CERTIFCATE 行以及破折号,这使我遇到了同样的错误。我尝试使用下面的代码使用的 java.security.cert.Certificate 以及 X509Certificate。任何帮助将不胜感激。

我可以上传对您有帮助的密钥文件,因为它是我在本地计算机上生成的测试密钥,一旦我使用它就会被丢弃。

package com.cds.test;

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

public class RSAEncryptDecrypt {
    public X509Certificate cert = null;
    //
    public void readCertificate() throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        CertificateFactory factory = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
        InputStream fis = new FileInputStream("/opt/temp/keys/openssl_crt.pem");
        X509Certificate x509Cert = (X509Certificate) factory.generateCertificate(fis);
        this.cert = x509Cert;
        System.out.println("issuer: " + x509Cert.getIssuerX500Principal());
    }
    //
    public String encrypt(String inputData) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        //
        System.out.println("public key: " + new String(Base64.encode(cert.getPublicKey().getEncoded())));
        AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(cert.getPublicKey().getEncoded());
        AsymmetricBlockCipher cipher = new RSAEngine();
        cipher = new org.bouncycastle.crypto.encodings.PKCS1Encoding(cipher);
        cipher.init(true, publicKey);
        //
        byte[] messageBytes = inputData.getBytes();
        byte[] hexEncodedCipher = cipher.processBlock(messageBytes, 0, messageBytes.length);
        //
        return new String(Base64.encode(hexEncodedCipher));
    }
    //
    private String decrypt (String encryptedData) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        //
        byte[] certData = cert.getEncoded();
        //certData = Base64.decode(certData);
        AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(cert.getEncoded());
        AsymmetricBlockCipher cipher = new RSAEngine();
        cipher = new org.bouncycastle.crypto.encodings.PKCS1Encoding(cipher);
        cipher.init(false, privateKey);
        //
        byte[] decoded = Base64.decode(encryptedData.getBytes());
        byte[] result = cipher.processBlock(decoded, 0, decoded.length);
        //
        return new String(result);
    }   
    //
    public static void main(String[] args) throws Exception {
        String inputData = "This is the message I am trying to encrypt.";
        String encrypted = null;
        String decrypted = null;
        //
        RSAEncryptDecrypt rsa = new RSAEncryptDecrypt();
        //
        rsa.readCertificate();
        System.out.println("    input: " + inputData);
        encrypted = rsa.encrypt(inputData);
        System.out.println("encrypted: " + encrypted);
        decrypted = rsa.decrypt(encrypted);
        System.out.println("decrypted: " + decrypted);
    }
}

【问题讨论】:

    标签: java encryption bouncycastle


    【解决方案1】:

    证书只包含公钥,不包含私钥。当然,公钥有一个与之关联的私钥,但它并没有保存在证书中。证书是您分发给其他方的内容。

    可能是您使用 Microsoft 代码的次数过多。我在 .NET 代码中提到了 Microsoft,证书类可以在内部包含相关的私钥,这使得 API 变得过于简单。

    因此,要解密,您必须单独读取证书的私钥(使用 PKCS8EncodedKeySpec"RSA" KeyFactory)。

    另一种选择是将两者都放入 PKCS#12 密钥库中,然后使用 KeyStore.load 将其读入 Java。

    【讨论】:

    • 不要使用微软,但通常也不会处理密码学,所以我不知道证书不包含私钥。看了你的回答,就清楚多了。我能够将我的私钥编码为 PKCS8 格式并将其读入我的 Java 程序中。感谢您的帮助。
    • 证书用于分发信任。如果他们将包含私钥,那么任何接收证书的人也将有权冒充生成密钥对的人。只有公钥而没有私钥,整个 PKI 概念将变得相当无用 :) 很高兴你把它修好了。
    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 2021-03-01
    • 2022-01-18
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 2021-06-08
    相关资源
    最近更新 更多