📄 pkcs12keystore.java
字号:
/****************************************************************************** * * Copyright (c) 1999-2004 AppGate Network Security AB. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code as * defined in and that are subject to the MindTerm Public Source License, * Version 2.0, (the 'License'). You may not use this file except in compliance * with the License. * * You should have received a copy of the MindTerm Public Source License * along with this software; see the file LICENSE. If not, write to * AppGate Network Security AB, Otterhallegatan 2, SE-41118 Goteborg, SWEDEN * *****************************************************************************/package com.mindbright.security.keystore;import java.io.InputStream;import java.io.OutputStream;import java.io.IOException;import java.io.ByteArrayInputStream;import java.util.Hashtable;import java.util.Vector;import java.util.Enumeration;import java.util.Date;import java.math.BigInteger;import com.mindbright.jca.security.Key;import com.mindbright.jca.security.MessageDigest;import com.mindbright.jca.security.KeyStoreSpi;import com.mindbright.jca.security.PrivateKey;import com.mindbright.jca.security.KeyFactory;import com.mindbright.jca.security.KeyStoreException;import com.mindbright.jca.security.UnrecoverableKeyException;import com.mindbright.jca.security.InvalidKeyException;import com.mindbright.jca.security.NoSuchAlgorithmException;import com.mindbright.jca.security.cert.Certificate;import com.mindbright.jca.security.cert.CertificateException;import com.mindbright.jca.security.spec.DSAPrivateKeySpec;import com.mindbright.jca.security.spec.RSAPrivateCrtKeySpec;import com.mindbright.jce.crypto.Cipher;import com.mindbright.jce.crypto.Mac;import com.mindbright.jce.crypto.spec.SecretKeySpec;import com.mindbright.jce.crypto.spec.IvParameterSpec;import com.mindbright.asn1.ASN1DER;import com.mindbright.asn1.ASN1Object;import com.mindbright.asn1.ASN1Integer;import com.mindbright.asn1.ASN1Sequence;import com.mindbright.asn1.ASN1OIDRegistry;import com.mindbright.asn1.ASN1OctetString;import com.mindbright.asn1.ASN1CharString;import com.mindbright.security.x509.Attribute;import com.mindbright.security.x509.X509Certificate;import com.mindbright.security.pkcs7.ContentInfo;import com.mindbright.security.pkcs7.EncryptedData;import com.mindbright.security.pkcs8.PrivateKeyInfo;import com.mindbright.security.pkcs8.EncryptedPrivateKeyInfo;import com.mindbright.security.pkcs12.PFX;import com.mindbright.security.pkcs12.AuthenticatedSafe;import com.mindbright.security.pkcs12.SafeContents;import com.mindbright.security.pkcs12.SafeBag;import com.mindbright.security.pkcs12.PKCS12PbeParams;import com.mindbright.security.pkcs12.CertBag;import com.mindbright.util.HexDump;public class PKCS12KeyStore extends KeyStoreSpi { private Hashtable privateKeys; private Hashtable certificates; private Hashtable name2id; private Vector aliases; public PKCS12KeyStore() { ASN1OIDRegistry.addModule("com.mindbright.security.pkcs12"); /* * Proprietary Micro$oft bag attribute type (probably showing preferred * MS CSP for content or something...). Value often (always?) seems to * be: 'Microsoft Base Cryptographic Provider v1.0' */ ASN1OIDRegistry.register("1.3.6.1.4.1.311.17.1", "ASN1BMPString"); privateKeys = new Hashtable(); certificates = new Hashtable(); aliases = new Vector(); name2id = new Hashtable(); } public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { String localKeyId = (String)name2id.get(alias); if(localKeyId == null) { return null; } EncryptedPrivateKeyInfo epki = (EncryptedPrivateKeyInfo)privateKeys.get(localKeyId); return extractPrivateKey(epki, password); } public Certificate[] engineGetCertificateChain(String alias) { // TODO return null; } public Certificate engineGetCertificate(String alias) { if (alias == null) return null; X509Certificate x509Cert = null; byte[] derCert = null; String localKeyId = (String)name2id.get(alias); if(localKeyId == null) { localKeyId = alias; } derCert = (byte[])certificates.get(localKeyId); if(derCert != null) { x509Cert = new X509Certificate(derCert); } return x509Cert; } public Date engineGetCreationDate(String alias) { // N/A return null; } public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { // TODO } public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { // TODO } public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException { // TODO } public void engineDeleteEntry(String alias) throws KeyStoreException { // TODO } public Enumeration engineAliases() { return aliases.elements(); } public boolean engineContainsAlias(String alias) { return aliases.contains(alias); } public int engineSize() { return aliases.size(); } public boolean engineIsKeyEntry(String alias) { return (name2id.get(alias) != null); } public boolean engineIsCertificateEntry(String alias) { return (!engineIsKeyEntry(alias) && certificates.get(alias) != null); } public String engineGetCertificateAlias(Certificate cert) { // TODO return null; } public void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { // TODO } public void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { try { ASN1DER ber = new ASN1DER(); PFX pfx = new PFX(); ber.decode(stream, pfx); checkMac(pfx, password); AuthenticatedSafe authSafe = new AuthenticatedSafe(); ASN1OctetString data = pfx.getDataContent(); ByteArrayInputStream ba = new ByteArrayInputStream(data.getRaw()); ber.decode(ba, authSafe); for(int i = 0; i < authSafe.getCount(); i++) { ContentInfo ci = authSafe.getContentInfo(i); String cit = ci.contentType.getString(); if(cit.equals("1.2.840.113549.1.7.1")) { data = (ASN1OctetString)ci.content.getValue(); processSafeContents(data.getRaw()); } else if(cit.equals("1.2.840.113549.1.7.6")) { EncryptedData ed = (EncryptedData)ci.content.getValue(); String alg = ed.encryptedContentInfo.contentEncryptionAlgorithm.algorithmName(); byte[] enc = ed.encryptedContentInfo.encryptedContent.getRaw(); PKCS12PbeParams params = (PKCS12PbeParams) ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters.getValue(); byte[] salt = params.salt.getRaw(); int iterations = params.iterations.getValue().intValue(); byte[] dec = new byte[enc.length]; doCipher(Cipher.DECRYPT_MODE, password, enc, enc.length, dec, salt, iterations, alg); processSafeContents(dec); } else { throw new IOException("ContentInfo type not supported: " + cit); } } } catch (IOException e) { e.printStackTrace(); throw e; } } private void checkMac(PFX pfx, char[] password) throws CertificateException { if(!pfx.macData.isSet()) { return; } try { String digAlg = pfx.macData.mac.digestAlgorithm.algorithm.getString(); Mac mac = Mac.getInstance(digAlg); byte[] data = pfx.getDataContent().getRaw(); byte[] storedDig = pfx.macData.mac.digest.getRaw(); byte[] salt = pfx.macData.macSalt.getRaw(); int iterations = pfx.macData.getIterations(); byte[] key = deriveKey(password, 20, salt, iterations, 3, digAlg); mac.init(new SecretKeySpec(key, mac.getAlgorithm())); mac.update(data); byte[] dataDig = mac.doFinal(); for(int i = 0; i < storedDig.length; i++) { if(dataDig[i] != storedDig[i]) { throw new CertificateException("MAC check failed"); } } } catch (Exception e) { throw new CertificateException("Error when verifying MAC: " + e.getMessage()); } } private void processSafeContents(byte[] scBer) throws IOException, NoSuchAlgorithmException { ByteArrayInputStream ba = new ByteArrayInputStream(scBer); SafeContents sc = new SafeContents(); ASN1DER ber = new ASN1DER(); ber.decode(ba, sc); for(int j = 0; j < sc.getCount(); j++) { SafeBag safeBag = sc.getSafeBag(j); String friendlyName = getAttribute(safeBag, "1.2.840.113549.1.9.20"); String localKeyId = getAttribute(safeBag, "1.2.840.113549.1.9.21"); if(friendlyName != null) { if(localKeyId != null) { name2id.put(friendlyName, localKeyId); } if(!aliases.contains(friendlyName)) { aliases.addElement(friendlyName); } } else if (localKeyId != null) { name2id.put(localKeyId, localKeyId); if(!aliases.contains(localKeyId)) { aliases.addElement(localKeyId); } } switch(safeBag.getBagType()) { case SafeBag.TYPE_PKCS8_SHROUDED_KEYBAG: EncryptedPrivateKeyInfo keyBag = (EncryptedPrivateKeyInfo)safeBag.bagValue.getValue(); privateKeys.put(localKeyId, keyBag); break; case SafeBag.TYPE_CERTBAG: CertBag cb = (CertBag)safeBag.bagValue.getValue(); byte[] derCert = ((ASN1OctetString)cb.certValue.getValue()).getRaw(); if(localKeyId == null) { /* * Trusted certs don't have a localKeyId */ localKeyId = friendlyName; } if (localKeyId != null) certificates.put(localKeyId, derCert); break; default: throw new IOException("SafeBag type not supported: " + safeBag.bagId.getString()); } } } private static PrivateKey extractPrivateKey(EncryptedPrivateKeyInfo keyBag, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { ASN1DER ber = new ASN1DER(); PKCS12PbeParams params = (PKCS12PbeParams) keyBag.encryptionAlgorithm.parameters.getValue();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -