读书人

关于ibm-jdk上的证书加密解密有关问题

发布时间: 2012-10-24 14:15:58 作者: rapoo

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


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













读书人网 >软件架构设计

热点推荐