X509 RSA充气城堡标志数据和验证

Posted

技术标签:

【中文标题】X509 RSA充气城堡标志数据和验证【英文标题】:X509 RSA bouncy castle sign data and verification 【发布时间】:2020-07-03 07:51:40 【问题描述】:

我正在尝试使用数字证书对数据进行签名和验证。验证签名时出现以下错误

线程“主”java.lang.IllegalArgumentException 中的异常:缺失 提供者在 java.security.MessageDigest.getInstance(MessageDigest.java:237) 在 org.bouncycastle.jcajce.util.NamedJcaJceHelper.createDigest(未知 来源)在 org.bouncycastle.operator.jcajce.OperatorHelper.createDigest(未知 来源)在 org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder$1.get(未知 来源)在 org.bouncycastle.cms.SignerInformationVerifier.getDigestCalculator(未知 来源)在 org.bouncycastle.cms.SignerInformation.doVerify(未知 来源)在 org.bouncycastle.cms.SignerInformation.verify(未知 来源)在 Crypto.verifySignedData(Crypto.java:257) 在 Crypto.main(Crypto.java:361)

有什么想法吗? 使用 bcpkix-jdk15on-1.58.jar 代码如下。提前致谢

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Base64;

import org.apache.commons.lang.StringUtils;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x500.style.IETFUtils;
import org.bouncycastle.operator.*;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.SignerInformationVerifier;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;


public class Crypto 
    private static String provider;
    private static String algorithm;
    private static String privateKsType;
    private static String privateKsPath;
    private static String privateKsPassword;
    private static String alias;
    private static String privateKeyPassword;
    private static PrivateKey privateKey;
    private static PublicKey publicKey;
    private static X509Certificate certToSign;
    private static PrivateKey encryptPrivateKey;
    private static X509Certificate encryptCert;
    private final static DefaultCMSSignatureAlgorithmNameGenerator defaultNameGenerator = 
            new DefaultCMSSignatureAlgorithmNameGenerator();
    private final static DefaultSignatureAlgorithmIdentifierFinder
            defaultIdentifierFinder = new DefaultSignatureAlgorithmIdentifierFinder();
    private final static Map<String, Map<BigInteger, X509Certificate>> mCert = new HashMap<>();
    private static final Hashtable<ASN1ObjectIdentifier, String> DefaultSymbols = new Hashtable<>();
    private static DigestCalculatorProvider jcaDigestCalculatorProviderBuilder;
    static
     
     DefaultSymbols.put(BCStyle.C, "c");
     DefaultSymbols.put(BCStyle.O, "o");
     DefaultSymbols.put(BCStyle.T, "title");
     DefaultSymbols.put(BCStyle.OU, "ou");
     DefaultSymbols.put(BCStyle.CN, "cn");
     DefaultSymbols.put(BCStyle.L, "l");
     DefaultSymbols.put(BCStyle.ST, "st");
     DefaultSymbols.put(BCStyle.SN, "serialNumber");
     DefaultSymbols.put(BCStyle.EmailAddress, "e");
     DefaultSymbols.put(BCStyle.DC, "dc");
     DefaultSymbols.put(BCStyle.UID, "uid");
     DefaultSymbols.put(BCStyle.STREET, "street");
     DefaultSymbols.put(BCStyle.SURNAME, "sn");
     DefaultSymbols.put(BCStyle.GIVENNAME, "givenName");
     DefaultSymbols.put(BCStyle.INITIALS, "initials");
     DefaultSymbols.put(BCStyle.GENERATION, "generation");
     DefaultSymbols.put(BCStyle.UnstructuredAddress, "unstructuredAddress");
     DefaultSymbols.put(BCStyle.UnstructuredName, "unstructuredName");
     DefaultSymbols.put(BCStyle.UNIQUE_IDENTIFIER, "uniqueIdentifier");
     DefaultSymbols.put(BCStyle.DN_QUALIFIER, "dn");
     DefaultSymbols.put(BCStyle.PSEUDONYM, "pseudonym");
     DefaultSymbols.put(BCStyle.POSTAL_ADDRESS, "postalAddress");
     DefaultSymbols.put(BCStyle.NAME_AT_BIRTH, "nameAtBirth");
     DefaultSymbols.put(BCStyle.COUNTRY_OF_CITIZENSHIP, "countryOfCitizenship");
     DefaultSymbols.put(BCStyle.COUNTRY_OF_RESIDENCE, "countryOfResidence");
     DefaultSymbols.put(BCStyle.GENDER, "gender");
     DefaultSymbols.put(BCStyle.PLACE_OF_BIRTH, "placeOfBirth");
     DefaultSymbols.put(BCStyle.DATE_OF_BIRTH, "dateOfBirth");
     DefaultSymbols.put(BCStyle.POSTAL_CODE, "postalCode");
     DefaultSymbols.put(BCStyle.BUSINESS_CATEGORY, "businessCategory");
     DefaultSymbols.put(BCStyle.TELEPHONE_NUMBER, "telephoneNumber");
     DefaultSymbols.put(BCStyle.NAME, "name");

     

    
    public static void appendTypeAndValue(StringBuilder buf,
            AttributeTypeAndValue typeAndValue,
            Hashtable<ASN1ObjectIdentifier, String> oidSymbols) 
        String sym = oidSymbols.get(typeAndValue.getType());
        if (sym != null) 
            buf.append(sym);
         else 
            buf.append(typeAndValue.getType().getId());
        
        buf.append('=');
        buf.append(IETFUtils.valueToString(typeAndValue.getValue()));
    
    
    public static byte[] signData(byte[] data,
            X509Certificate signingCertificate, PrivateKey signingKey, String signatureAlgorithm, String certProvider)
            throws Exception 
        if (privateKey == null)
            throw new IllegalStateException(
                    "Crypto error, failed to load private key");
        if (certProvider == null || data == null || signatureAlgorithm == null)
            return null;
        byte[] signedMessage = null;
        try 
        
    
            CMSTypedData cmsData = new CMSProcessableByteArray(data);
    
            CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator();
            ContentSigner contentSigner = new JcaContentSignerBuilder(
                    signatureAlgorithm).setProvider(certProvider).build(signingKey);
            cmsGenerator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
                    new JcaDigestCalculatorProviderBuilder()
                            .build()).build(contentSigner, signingCertificate));
            
            CMSSignedData cms = cmsGenerator.generate(cmsData, false);
            signedMessage = cms.getEncoded();
            
        catch (Exception e) 
            System.out.println(e.getMessage());
            throw e;
        
        return signedMessage;
    
    
    private static X509Certificate getCertificate(final String issuerDN,
            final BigInteger certSN) 
        Map<BigInteger, X509Certificate> hmI = mCert.get(issuerDN);
        
        if (hmI != null) 
            final X509Certificate cert = hmI.get(certSN);
            if (cert != null) 
                return cert;
            
        
        throw new IllegalStateException(
                "Crypto error, failed to load certificate");
    

    public static String toStringReversed(X500Name name) 
        final StringBuilder buf = new StringBuilder();
        boolean first = true;
        final RDN[] rdns = name.getRDNs();
        for (int i = rdns.length - 1; i >= 0; i--) 
            if (first) 
                first = false;
             else 
                buf.append(',');
            
            if (rdns[i].isMultiValued()) 
                AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
                boolean firstAtv = true;
                for (int j = 0; j != atv.length; j++) 
                    if (firstAtv) 
                        firstAtv = false;
                     else 
                        buf.append('+');
                    
                    appendTypeAndValue(buf, atv[j], DefaultSymbols);
                
             else 
                appendTypeAndValue(buf, rdns[i].getFirst(), DefaultSymbols);
            
        
        return buf.toString();
    

    private static String getSubject(final X509Certificate cert)
            throws CertificateEncodingException 
        final JcaX509CertificateHolder jcaX509CertificateHolder = new JcaX509CertificateHolder(
                cert);
        final X500Name x500Subject = jcaX509CertificateHolder.getSubject();
        return toStringReversed(x500Subject);
    

    private static boolean verifySignedData(String providerName,
            final String signature, final String stringData,
            final String signatureAlgorithm) throws Exception 
        if (signature == null || stringData == null
                || signatureAlgorithm == null)
            return false;
        final byte[] pkcs7 = Base64.getDecoder().decode(signature);
        final byte[] bytesToCheck = stringData.getBytes("UTF-8");
        final CMSProcessableByteArray typedData = new CMSProcessableByteArray(
                bytesToCheck); 
        final CMSSignedData cms = new CMSSignedData(typedData, pkcs7);
        final SignerInformationStore signers = cms.getSignerInfos();
        final Iterator<SignerInformation> iter = signers.getSigners().iterator();
        boolean bRes = false;
        while (iter.hasNext()) 
            final SignerInformation signer = iter.next();
            final BigInteger certSN = signer.getSID().getSerialNumber();
            final String issuerDN = toStringReversed(X500Name
                    .getInstance(signer.getSID().getIssuer().getEncoded()));
            System.out.println(signer.getSID().getIssuer());
            System.out.println(issuerDN);
            final X509Certificate cert = getCertificate(issuerDN, certSN);
            cert.checkValidity();
            final String subject = getSubject(cert);
            final ContentVerifierProvider contentVerifierProvider;
            
            contentVerifierProvider = new JcaContentVerifierProviderBuilder()
                    .setProvider(providerName).build(cert.getPublicKey());
            System.out.println(contentVerifierProvider);
            SignerInformationVerifier signerInformation = new SignerInformationVerifier(defaultNameGenerator,
                    defaultIdentifierFinder, contentVerifierProvider, jcaDigestCalculatorProviderBuilder);
            
            System.out.println(signerInformation);
            
            if (!signer.verify(signerInformation)) 
                System.out.println("checkSign BAD, subj:" + subject);
                throw new Exception("Failed to check signature: " + subject);
            
            System.out.println("checkSign OK, subj:" + subject);
            bRes = true;
        
        return bRes;
    
    
    public static String initPrivateKey() throws Exception 
        if ("BC".equals(provider) && Security.getProvider("BC") == null)
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        jcaDigestCalculatorProviderBuilder = new JcaDigestCalculatorProviderBuilder()
                .setProvider(provider).build();
        if (!StringUtils.isEmpty(privateKsType)) 
            System.out.println("Crypto init:PrivateKS, KeyStoreType:"
                    + privateKsType + ", KeyStorePath:" + privateKsPath
                    + ", Alias:" + alias);
            KeyStore privateKS;
            try 
                System.out.println("opening keyStore");
                final InputStream is;
                if (!StringUtils.isEmpty(privateKsPath))
                    is = new FileInputStream(new File(privateKsPath));
                else
                    is = null;
                privateKS = KeyStore.getInstance(privateKsType);
                privateKS.load(is, privateKsPassword.toCharArray());
                certToSign = (X509Certificate) privateKS.getCertificate(alias);
                System.out.println("reading private key");
                privateKey = (PrivateKey) privateKS.getKey(alias,
                        privateKeyPassword.toCharArray());
                if (privateKey == null)
                    throw new IllegalStateException(
                            "Crypto error, failed to load private key " + alias);
                if (encryptCert == null) 
                    encryptCert = certToSign;
                    encryptPrivateKey = privateKey;
                
             catch (KeyStoreException | NoSuchAlgorithmException | IOException
                    | CertificateException | UnrecoverableKeyException e) 
                System.out.println(e.getMessage());
                throw new Exception(e);
            
            System.out.println("Crypto init:PrivateKS done, Provider - "
                    + privateKS.getProvider().getName());
            return privateKS.getProvider().getName();
         else
            return null;
    

【问题讨论】:

您的类路径中有提供程序 jar 吗? mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on 是的,我已经在类路径中包含了这个 jar。 代码不完整是吗?你在哪里调用verifySignedData?您之前是否调用过 initPrivateKey 以便将 BC 添加为提供程序? 我调用 initPrivateKey 从 .jks 文件中提取私钥用于签名数据。使用函数 signData 对数据进行签名后,我调用 verifySignedData 来验证签名。我实际上必须在验证部分工作,但显然,在验证之前创建签名是必要的。我现在也添加了我的主要方法。 【参考方案1】:

问题已解决。我在函数中错过了以下行

jcaDigestCalculatorProviderBuilder = new JcaDigestCalculatorProviderBuilder() .setProvider(providerName).build(); 这是完整的代码

public class CryptoUtils 
    private final static DefaultCMSSignatureAlgorithmNameGenerator defaultNameGenerator = new DefaultCMSSignatureAlgorithmNameGenerator();
    private final static DefaultSignatureAlgorithmIdentifierFinder defaultIdentifierFinder = new DefaultSignatureAlgorithmIdentifierFinder();
    private static final Hashtable<ASN1ObjectIdentifier, String> DefaultSymbols = new Hashtable<ASN1ObjectIdentifier, String>();
    static 
        DefaultSymbols.put(BCStyle.C, "c");
        DefaultSymbols.put(BCStyle.O, "o");
        DefaultSymbols.put(BCStyle.T, "title");
        DefaultSymbols.put(BCStyle.OU, "ou");
        DefaultSymbols.put(BCStyle.CN, "cn");
        DefaultSymbols.put(BCStyle.L, "l");
        DefaultSymbols.put(BCStyle.ST, "st");
        DefaultSymbols.put(BCStyle.SN, "serialNumber");
        DefaultSymbols.put(BCStyle.EmailAddress, "e");
        DefaultSymbols.put(BCStyle.DC, "dc");
        DefaultSymbols.put(BCStyle.UID, "uid");
        DefaultSymbols.put(BCStyle.STREET, "street");
        DefaultSymbols.put(BCStyle.SURNAME, "sn");
        DefaultSymbols.put(BCStyle.GIVENNAME, "givenName");
        DefaultSymbols.put(BCStyle.INITIALS, "initials");
        DefaultSymbols.put(BCStyle.GENERATION, "generation");
        DefaultSymbols.put(BCStyle.UnstructuredAddress, "unstructuredAddress");
        DefaultSymbols.put(BCStyle.UnstructuredName, "unstructuredName");
        DefaultSymbols.put(BCStyle.UNIQUE_IDENTIFIER, "uniqueIdentifier");
        DefaultSymbols.put(BCStyle.DN_QUALIFIER, "dn");
        DefaultSymbols.put(BCStyle.PSEUDONYM, "pseudonym");
        DefaultSymbols.put(BCStyle.POSTAL_ADDRESS, "postalAddress");
        DefaultSymbols.put(BCStyle.NAME_AT_BIRTH, "nameAtBirth");
        DefaultSymbols.put(BCStyle.COUNTRY_OF_CITIZENSHIP,
                "countryOfCitizenship");
        DefaultSymbols.put(BCStyle.COUNTRY_OF_RESIDENCE, "countryOfResidence");
        DefaultSymbols.put(BCStyle.GENDER, "gender");
        DefaultSymbols.put(BCStyle.PLACE_OF_BIRTH, "placeOfBirth");
        DefaultSymbols.put(BCStyle.DATE_OF_BIRTH, "dateOfBirth");
        DefaultSymbols.put(BCStyle.POSTAL_CODE, "postalCode");
        DefaultSymbols.put(BCStyle.BUSINESS_CATEGORY, "businessCategory");
        DefaultSymbols.put(BCStyle.TELEPHONE_NUMBER, "telephoneNumber");
        DefaultSymbols.put(BCStyle.NAME, "name");

    

    public static void appendTypeAndValue(StringBuilder buf,
            AttributeTypeAndValue typeAndValue,
            Hashtable<ASN1ObjectIdentifier, String> oidSymbols) 
        String sym = oidSymbols.get(typeAndValue.getType());
        if (sym != null) 
            buf.append(sym);
         else 
            buf.append(typeAndValue.getType().getId());
        
        buf.append('=');
        buf.append(IETFUtils.valueToString(typeAndValue.getValue()));
    

    // private static X509Certificate getCertificate(final String issuerDN,
    // final BigInteger certSN) 
    // Map<BigInteger, X509Certificate> hmI = mCert.get(issuerDN);
    //
    // if (hmI != null) 
    // final X509Certificate cert = hmI.get(certSN);
    // if (cert != null) 
    // return cert;
    // 
    // 
    // throw new IllegalStateException(
    // "Crypto error, failed to load certificate");
    // 

    public static String toStringReversed(X500Name name) 
        final StringBuilder buf = new StringBuilder();
        boolean first = true;
        final RDN[] rdns = name.getRDNs();
        for (int i = rdns.length - 1; i >= 0; i--) 
            if (first) 
                first = false;
             else 
                buf.append(',');
            
            if (rdns[i].isMultiValued()) 
                AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
                boolean firstAtv = true;
                for (int j = 0; j != atv.length; j++) 
                    if (firstAtv) 
                        firstAtv = false;
                     else 
                        buf.append('+');
                    
                    appendTypeAndValue(buf, atv[j], DefaultSymbols);
                
             else 
                appendTypeAndValue(buf, rdns[i].getFirst(), DefaultSymbols);
            
        
        return buf.toString();
    

    private static String getSubject(final X509Certificate cert)
            throws CertificateEncodingException 
        final JcaX509CertificateHolder jcaX509CertificateHolder = new JcaX509CertificateHolder(
                cert);
        final X500Name x500Subject = jcaX509CertificateHolder.getSubject();
        return toStringReversed(x500Subject);
    

    public static Boolean verifySignedData(String providerName,
            final String signature, final String stringData,
            final String signatureAlgorithm) 
        try 
            if (signature == null || stringData == null
                    || signatureAlgorithm == null) 
                logInfo("default", "Signature/ Data/ Algorithm not found");
                return false;
            
            final byte[] pkcs7 = Base64.getDecoder().decode(signature);
            final byte[] bytesToCheck = stringData.getBytes("UTF-8");
            final CMSProcessableByteArray typedData = new CMSProcessableByteArray(
                    bytesToCheck); //$NON-NLS-1$
            final CMSSignedData cms = new CMSSignedData(typedData, pkcs7);
            final SignerInformationStore signers = cms.getSignerInfos();
            final Iterator<SignerInformation> iter = signers.getSigners()
                    .iterator();
            boolean bRes = false;
            while (iter.hasNext()) 
                final SignerInformation signer = iter.next();
                FileInputStream fin = new FileInputStream("D:\\JB\\jb.cer");
                CertificateFactory f = CertificateFactory.getInstance("X.509");
                X509Certificate cert = (X509Certificate) f
                        .generateCertificate(fin);
                PublicKey pk = cert.getPublicKey();

                cert.checkValidity();
                final String subject = getSubject(cert);
                final ContentVerifierProvider contentVerifierProvider;

                DigestCalculatorProvider jcaDigestCalculatorProviderBuilder = new JcaDigestCalculatorProviderBuilder()
                        .setProvider(providerName).build();

                contentVerifierProvider = new JcaContentVerifierProviderBuilder()
                        .setProvider(providerName).build(pk);

                SignerInformationVerifier signerInformation = new SignerInformationVerifier(
                        defaultNameGenerator, defaultIdentifierFinder,
                        contentVerifierProvider,
                        jcaDigestCalculatorProviderBuilder);

                try 
                    if (!signer.verify(signerInformation)) 
                        logInfo("default", "CheckSign BAD, subj:" + subject);
                        return false;
                    
                 catch (Exception e) 
                    logException("default",
                            "Exception occurred in verifying signature: ", e);
                    return false;
                
                // System.out.println("checkSign OK, subj:" + subject);
                bRes = true;
            
            return bRes;
         catch (Exception e) 
            logException("default",
                    "Exception occurred in verifying signature: ", e);
            return false;
        
    

    public static List<Serializable> initPrivateKey(String KeystorePath,
            String keystorePassword, String keystoreAlias, String keystoreType)
            throws Exception 
        PrivateKey privateKey = null;
        X509Certificate certificateToSign;

        if (!StringUtils.isEmpty(keystoreType)) 
            // System.out.println("Crypto init:PrivateKS, KeyStoreType: "
            // + keystoreType + ", KeyStorePath:" + KeystorePath
            // + ", Alias:" + keystoreAlias);
            KeyStore privateKS;
            try 
                // System.out.println("opening keyStore");
                final InputStream is;
                if (!StringUtils.isEmpty(KeystorePath))
                    is = new FileInputStream(new File(KeystorePath));
                else
                    is = null;
                privateKS = KeyStore.getInstance(keystoreType);
                privateKS.load(is, keystorePassword.toCharArray());
                certificateToSign = (X509Certificate) privateKS
                        .getCertificate(keystoreAlias);
                // System.out.println("reading private key");
                privateKey = (PrivateKey) privateKS.getKey(keystoreAlias,
                        keystorePassword.toCharArray());
                if (privateKey == null) 
                    logInfo("default", "Failed to load private key");
                    return null;
                
             catch (KeyStoreException | NoSuchAlgorithmException | IOException
                    | CertificateException | UnrecoverableKeyException e) 
                logException("default",
                        "Exception occurred in genersting privateKey: ", e);
                return null;
            

            return Arrays.asList(privateKS.getProvider().getName(), privateKey,
                    certificateToSign);
         else 
            logInfo("default", "Keystore type is null");
            return null;
        
    

    public static String generateSignature(String stringData,
            String signatureAlgorithm, String KeystorePath,
            String keystorePassword, String keystoreAlias, String keystoreType) 
        try 
            List<Serializable> certificateDetails = initPrivateKey(
                    KeystorePath, keystorePassword, keystoreAlias, keystoreType);
            String providerName = (String) certificateDetails.get(0);
            PrivateKey certPrivateKey = (PrivateKey) certificateDetails.get(1);
            X509Certificate certificateToSign = (X509Certificate) certificateDetails
                    .get(2);

            if (certificateToSign == null) 
                logInfo("default", "Failed to load certificate");
                return null;
            

            if (certPrivateKey == null) 
                logInfo("default", "Failed to load private key");
                return null;
            

            if (providerName == null || stringData == null
                    || signatureAlgorithm == null)
                return null;

            final byte[] buf = stringData.getBytes("UTF-8");
            CMSTypedData typedData = new CMSProcessableByteArray(buf);
            CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
            ContentSigner signer;
            signer = new JcaContentSignerBuilder(signatureAlgorithm)
                    .setProvider(providerName).build(certPrivateKey);

            DigestCalculatorProvider digProvider = new JcaDigestCalculatorProviderBuilder()
                    .setProvider(providerName).build();

            JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(
                    digProvider);
            gen.addSignerInfoGenerator(builder.build(signer, certificateToSign));

            CMSSignedData signed = gen.generate(typedData, false);
            byte[] der = signed.getEncoded();
            final String result = Base64.getEncoder().encodeToString(der);

            return result;
         catch (Exception e) 
            logException("default",
                    "Exception occurred in generating signature: ", e);
            return null;
        
    

【讨论】:

你能不能这么好,并发布完整的代码,以便其他人能够获得一个运行示例 - 谢谢?

以上是关于X509 RSA充气城堡标志数据和验证的主要内容,如果未能解决你的问题,请参考以下文章

使用充气城堡验证签名

验证充气城堡上的 javacard 签名 ALG_ECDSA_SHA

使用充气城堡和证书私钥的数字签名

如何在netbeans java中使用充气城堡(DES)加密和解密文件?

充气城堡 C# 中的 PBKDF2

使用充气桥X509v3CertificateBuilder生成X509证书