设为首页 收藏本站
查看: 1383|回复: 0

[经验分享] 关于ibm-jdk下的证书加密解密问题的讨论

[复制链接]

尚未签到

发表于 2017-5-27 08:47:50 | 显示全部楼层 |阅读模式
现在需要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 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 = (X509Certificate) certs;
} 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)
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();
}
}


得到的签名密文为
DSC0000.jpg

现在根据项目的需要,使用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);
}


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


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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-381537-1-1.html 上篇帖子: IBM欲造首个仿真人脑 探询人类思考记忆秘密[zz] 下篇帖子: [书摘]吴士宏曾经这样回忆最初在IBM的岁月
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表