`
火云剑Shanke
  • 浏览: 67848 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

关于ibm-jdk下的证书加密解密问题的讨论

阅读更多
现在需要java实现使用.pfx证书对字符串进行加密,最后用base64编码形成密文。
    在Sun-Jdk下即使用SUN提供的jsse.jar包,已经实现此功能。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import javax.security.auth.x500.X500Principal;
import sun.misc.BASE64Decoder;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

/**
 * PKCS7Tool.java pkcs7格式签名工具
 */
public class _PKCS7Tool {

    /** 签名 */
    private static final int SIGNER = 1;
    /** 验证 */
    private static final int VERIFIER = 2;
    /** 用途 */
    private int mode = 0;
    /** 摘要算法 */
    private String digestAlgorithm = "SHA1";
    /** 签名算法 */
    private String signingAlgorithm = "SHA1withRSA";
    /** 签名证书链 */
    private X509Certificate[] certificates = null;
    /** 签名私钥 */
    private PrivateKey privateKey = null;
    /** 根证书 */
    private Certificate rootCertificate = null;

    /**
     * 私有构造方法
     */
    private _PKCS7Tool(int mode) {
        this.mode = mode;
    }

    /**
     * 取得签名工具 加载证书库, 取得签名证书链和私钥
     * 
     * @param keyStorePath
     *            证书库路径
     * @param keyStorePassword
     *            证书库口令
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public static _PKCS7Tool getSigner(String keyStorePath,
            String keyStorePassword, String keyPassword)
            throws GeneralSecurityException, IOException {
        // 加载证书库
        KeyStore keyStore = null;
        if (keyStorePath.toLowerCase().endsWith(".pfx"))
            keyStore = KeyStore.getInstance("PKCS12");
        else
            keyStore = KeyStore.getInstance("JKS");
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(keyStorePath);
            keyStore.load(fis, keyStorePassword.toCharArray());
        } finally {
            if (fis != null)
                fis.close();
        }
        // 在证书库中找到签名私钥
        Enumeration aliases = keyStore.aliases();
        String keyAlias = null;
        if (aliases != null) {
            while (aliases.hasMoreElements()) {
                keyAlias = (String) aliases.nextElement();
                Certificate[] certs = keyStore.getCertificateChain(keyAlias);
                if (certs == null || certs.length == 0)
                    continue;
                X509Certificate cert = (X509Certificate) certs[0];
                if (matchUsage(cert.getKeyUsage(), 1)) {
                    try {
                        cert.checkValidity();
                    } catch (CertificateException e) {
                        continue;
                    }
                    break;
                }
            }
        }
        // 没有找到可用签名私钥
        if (keyAlias == null)
            throw new GeneralSecurityException(
                    "None certificate for sign in this keystore");

        X509Certificate[] certificates = null;
        if (keyStore.isKeyEntry(keyAlias)) {
            // 检查证书链
            Certificate[] certs = keyStore.getCertificateChain(keyAlias);
            for (int i = 0; i < certs.length; i++) {
                if (!(certs[i] instanceof X509Certificate))
                    throw new GeneralSecurityException("Certificate[" + i
                            + "] in chain '" + keyAlias
                            + "' is not a X509Certificate.");
            }
            // 转换证书链
            certificates = new X509Certificate[certs.length];
            for (int i = 0; i < certs.length; i++)
                certificates[i] = (X509Certificate) certs[i];
        } else if (keyStore.isCertificateEntry(keyAlias)) {
            // 只有单张证书
            Certificate cert = keyStore.getCertificate(keyAlias);
            if (cert instanceof X509Certificate) {
                certificates = new X509Certificate[] { (X509Certificate) cert };
            }
        } else {
            throw new GeneralSecurityException(keyAlias
                    + " is unknown to this keystore");
        }

        PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias,
                keyPassword.toCharArray());
        // 没有私钥抛异常
        if (privateKey == null) {
            throw new GeneralSecurityException(keyAlias
                    + " could not be accessed");
        }

        _PKCS7Tool tool = new _PKCS7Tool(SIGNER);
        tool.certificates = certificates;
        tool.privateKey = privateKey;
        return tool;
    }




/**
     * 签名
     * 
     * @param data
     *            数据
     * @return signature 签名结果
     * @throws GeneralSecurityException
     * @throws IOException
     * @throws IllegalArgumentException
     */
    public String sign(byte[] data) throws GeneralSecurityException,
            IOException {
        if (mode != SIGNER)
            throw new IllegalStateException(
                    "call a PKCS7Tool instance not for signature.");

        Signature signer = Signature.getInstance(signingAlgorithm);
        signer.initSign(privateKey);
        signer.update(data, 0, data.length);
        byte[] signedAttributes = signer.sign();

        ContentInfo contentInfo = null;

        contentInfo = new ContentInfo(ContentInfo.DATA_OID, null);
        // 根证书
        X509Certificate x509 = certificates[certificates.length - 1];
        
        // 如果jdk1.5则用以下语句
        java.math.BigInteger serial = x509.getSerialNumber();
        // 签名信息
        SignerInfo si = new SignerInfo(new X500Name(x509.getIssuerDN()
                .getName()), // X500Name, issuerName,
                serial, // x509.getSerialNumber(), BigInteger serial,
                AlgorithmId.get(digestAlgorithm), // AlgorithmId,
                                                    // digestAlgorithmId,
                null, // PKCS9Attributes, authenticatedAttributes,
                new AlgorithmId(AlgorithmId.RSAEncryption_oid), // AlgorithmId,
                                                                // digestEncryptionAlgorithmId,
                signedAttributes, // byte[] encryptedDigest,
                null); // PKCS9Attributes unauthenticatedAttributes) {

        SignerInfo[] signerInfos = { si };

        // 构造PKCS7数据
        AlgorithmId[] digestAlgorithmIds = { AlgorithmId.get(digestAlgorithm) };
        PKCS7 p7 = new PKCS7(digestAlgorithmIds, contentInfo, certificates,
                signerInfos);

        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        p7.encodeSignedData(baout);
        // Base64编码
        return Base64.encode(baout.toByteArray());
    }

/**
     * 匹配私钥用法
     * 
     * @param keyUsage
     * @param usage
     * @return
     */
    private static boolean matchUsage(boolean[] keyUsage, int usage) {
        if (usage == 0 || keyUsage == null)
            return true;
        for (int i = 0; i < Math.min(keyUsage.length, 32); i++) {
            if ((usage & (1 << i)) != 0 && !keyUsage[i])
                return false;
        }
        return true;
    }


 public static void main(String[] args) {
        String keyStorePath = "D:\\淘宝网.pfx";
        String keyStorePassword = "11111111";
        String keyPassword = "11111111";
        _PKCS7Tool tool = null;
        try {
            tool = getSigner(keyStorePath, keyStorePassword, keyPassword);
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String plaintext = "123456";
        try {
            System.out.println(tool.sign(plaintext.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


得到的签名密文为




现在根据项目的需要,使用Ibm-jdk,并且使用Ibm提供的安全开发包ibmjceprovider.jar、ibmjgssprovider.jar、ibmjsseprovider2.jar、ibmpkcs.jar等,不用sun的jsse.jar。查询了相关资料,将签名方法进行修改,加载签名工具即取得证书和私钥的方法基本不变。
import com.ibm.misc.BASE64Decoder;
import com.ibm.security.pkcs7.Data;
import com.ibm.security.pkcsutil.PKCSAttributes;
import com.ibm.security.pkcs7.ContentInfo;
import com.ibm.security.pkcs7.SignedData;

/**
     * 签名
     * 
     * @param data
     *            数据
     * @return signature 签名结果
     * @throws GeneralSecurityException
     * @throws IOException
     * @throws IllegalArgumentException
     */
    public String sign(byte[] data) throws GeneralSecurityException,
            IOException {
        byte[] byteArray = null;
        //
        Data ibmData = new Data();
        ibmData.setData(data);
        ContentInfo contentInfo = new ContentInfo(ibmData);

        // 
        Certificate[] signingCert = new Certificate[1];
        signingCert[0] = certificates[certificates.length - 1];
//--------
        CRL[] crls = null;
        PKCSAttributes signedAttributes = null;
        PKCSAttributes unsignedAttributes = null;
        PrivateKey[] privateKeys = new PrivateKey[1];
        privateKeys[0] = privateKey;    

        boolean signatureOnly = false;
        String AlgName = signingAlgorithm;//

        // 签名信息
        SignedData signData = new SignedData(signingCert, crls, contentInfo,
                AlgName, privateKeys, signedAttributes, unsignedAttributes,
                signatureOnly);

        

        ContentInfo contentInfo2 = new ContentInfo(signData);

        byte[] encodedSignedData = contentInfo2.encode();

        return Base64.encode(encodedSignedData);
    }


这时出现一个奇怪的现象,每次执行签名方法得到的签名密文都不一样,请大家指教。








​原文链接:https://riboseyim.github.io?source=iteye&pid=cert






  • 大小: 140.7 KB
  • 大小: 155.8 KB
  • 大小: 159.1 KB
分享到:
评论

相关推荐

    ibm jdk策略文件,解决加解密限制

    在"ibm jdk策略文件,解决加解密限制"这个主题中,我们关注的是IBM JDK 5.0版本中的加密限制问题。默认情况下,IBM JDK可能会限制某些密码算法的长度,例如RSA密钥的大小,以符合特定国家或地区的法规。这可能会影响...

    Java中常用的加密方法(JDK)

    这里我们主要讨论对称加密,因为它是Java中最常用且基础的加密方式。 对称加密是一种使用同一密钥进行加密和解密的加密技术。它的优点在于加解密速度快,适合处理大量数据。Java中实现对称加密的关键类包括`...

    java版DES通用加密解密

    java版DES通用加密解密,使用JDK通用类,所以支持sun JDK和ibm JDK等

    ibm_unrestrictedpolicyfiles for Java 5678.7z

    总结来说,"ibm_unrestrictedpolicyfiles for Java 5678.7z"提供了解除Java加密限制的手段,使得开发者能够利用JDK提供的全部加密能力,尤其适用于那些需要高级别安全性的应用。在使用这些文件时,应确保符合当地的...

    Java_加密解密之对称加密算法DES

    Java 加密解密之对称加密算法 DES Java 加密解密之对称加密算法 DES 是一种常用的对称加密算法,广泛应用于保护金融数据的安全中。它的全称是 Data Encryption Algorithm(DEA),最早由 IBM 开发,并曾拥有专利权...

    Java 加密解密之对称加密算法DES.doc

    Java中的DES(Data Encryption Standard)是对称加密算法的一种,它基于IBM的研究工作,并在1977年被美国政府采纳为标准。DES算法使用56位的密钥和额外的8位奇偶校验位来处理64位的数据块。由于其结构特性,它采用...

    local_policy.jar和US_export_policy.jar java解密

    比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件, 从官方网站下载JCE无限制权限策略文件,注意自己JDK的版本别下错了。将local_policy.jar和US_export_policy.jar这两个文件替换%JRE_HOME%\lib\...

    jdk1.6、1.7、1.8的local_policy.jar和US_export_policy.jar

    4. 解决无法使用AES192、256位加密解密的问题 当你需要在JDK 1.6、1.7 或 1.8 中使用192位和256位AES加密时,可能会遇到“非法关键字”或“不受支持的密钥大小”等错误。为了解决这个问题,你需要替换JRE目录下的 `...

    用于jdk1.6-1.8的local_policy.jar和US_export_policy.jar以及用法

    在Java中,`javax.crypto`包提供了AES加密和解密的API,使得开发者能够方便地在程序中集成加密功能。`local_policy.jar`和`US_export_policy.jar`的存在决定了Java应用程序可以使用多强的AES密钥,以及是否允许使用...

    local_policy.jar和US_export_policy.jar

    微信退款的解密时报java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/ECB/PKCS7Padding错误,囊括jdk1.6、1.7、1.8的local_policy.jar和...解决无法使用AES192、256位加密解密的问题

    jurisdiction_policy_files_ibm.zip

    标题中的"jurisdiction_policy_files_ibm.zip"是一个与IBM服务器相关的安全策略文件压缩包,主要用于处理微信消息的验证和加密解密。这个压缩包特别指出它适用于IBM的服务器环境,特别是Websphere应用服务器,但并未...

    des完整资料

    DES最初由IBM开发,后来被美国国家标准局(NIST)采纳为标准,它使用56位密钥对64位的数据块进行加密和解密。 描述中提到的“jsmooth-0.9.9-7工具”是一个Java应用打包工具,能够将Java应用程序转换为Windows平台下...

    DES加密算法实验报告.docx

    ### DES加密算法实验知识点 ...- **兼容性问题**:在不同平台上运行时,需要注意字节序等问题,确保加密解密过程的一致性和正确性。 通过这次实验的学习和实践,可以更好地理解对称加密算法的工作原理及其应用场景。

    UnlimitedJCEPolicyJDK8.rar

    Java Cryptography Extension (JCE) 是Java平台用于处理加密、解密、签名和密钥交换等安全操作的核心组件。在标准版本中,JCE对某些加密算法的强度有所限制,这些限制通常是为了遵循不同国家的出口法规。然而,...

    利用DES加密算法保护Java源代码

    DES是一种对称加密算法,最初由IBM公司开发并在1977年被美国国家标准局采纳为官方标准。它使用56位密钥对64位数据块进行加密。尽管现在已经被更安全的AES算法取代,但在特定场景下,DES仍然是一种有效的加密手段。 ...

    IBM Datastage Java 包开发手册简体中文版

    在DataStage中使用Java的主要目的是为了处理一些无法通过简单的转换或者映射来完成的数据操作,比如复杂的业务逻辑处理、数据的加密与解密、格式转换、数据校验等。DataStage提供了两种特定的组件来支持Java的运行...

    Java安全性.doc

    这篇中级教程旨在帮助已经熟悉Java编程的开发者理解并应用密码学原理,通过Java语言实现加密技术,包括私钥和公钥加密、RSA算法、SSL安全套接层以及证书等相关概念。 首先,Java语言的特性使其天生适合安全编程。无...

Global site tag (gtag.js) - Google Analytics