📄 pkcs12keystore.java
字号:
String alg = keyBag.encryptionAlgorithm.algorithmName(); byte[] enc = keyBag.encryptedData.getRaw(); 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); return extractPrivateKey(dec); } public static class DSAyx extends ASN1Sequence { public ASN1Integer x; public ASN1Integer y; public DSAyx() { y = new ASN1Integer(); x = new ASN1Integer(); addComponent(y); addComponent(x); } } /* * !!! TODO generalize handling and move to pkcs8 or pkcs1 */ public static PrivateKey extractPrivateKey(byte[] berPrivateKeyInfo) throws UnrecoverableKeyException { ASN1DER ber = new ASN1DER(); ByteArrayInputStream ba = new ByteArrayInputStream(berPrivateKeyInfo); PrivateKeyInfo pki = new PrivateKeyInfo(); try { ber.decode(ba, pki); boolean isrsakey = true; try { String alg = pki.privateKeyAlgorithm.algorithmName().toLowerCase(); if (alg.indexOf("dsa") >= 0) isrsakey = false; } catch (Throwable t) { } ba = new ByteArrayInputStream(pki.privateKey.getRaw()); if (isrsakey) { com.mindbright.security.pkcs1.RSAPrivateKey rsa = new com.mindbright.security.pkcs1.RSAPrivateKey(); ber.decode(ba, rsa); BigInteger n, e, d, p, q, pe, qe, u; n = rsa.modulus.getValue(); e = rsa.publicExponent.getValue(); d = rsa.privateExponent.getValue(); p = rsa.prime1.getValue(); q = rsa.prime2.getValue(); pe = rsa.exponent1.getValue(); qe = rsa.exponent2.getValue(); u = rsa.coefficient.getValue(); RSAPrivateCrtKeySpec prvSpec = new RSAPrivateCrtKeySpec(n, e, d, p, q, pe, qe, u); KeyFactory keyFact = KeyFactory.getInstance("RSA"); return keyFact.generatePrivate(prvSpec); } BigInteger x = null; try { // Normally, we should have just one ASN.1 integer here... ASN1Integer dsax = new ASN1Integer(); ber.decode(ba, dsax); x = dsax.getValue(); } catch (Throwable t) { } if (x == null) { // ... but Mozilla returns SEQUENCE { y? INTEGER, x INTEGER } DSAyx dsayx = new DSAyx(); ber.decode(new ByteArrayInputStream(pki.privateKey.getRaw()), dsayx); x = dsayx.x.getValue(); } com.mindbright.security.pkcs1.DSAParams params = (com.mindbright.security.pkcs1.DSAParams)pki.privateKeyAlgorithm.parameters.getValue(); DSAPrivateKeySpec prvSpec = new DSAPrivateKeySpec(x, params.p.getValue(), params.q.getValue(), params.g.getValue()); KeyFactory keyFact = KeyFactory.getInstance("DSA"); return keyFact.generatePrivate(prvSpec); } catch (Exception e) { throw new UnrecoverableKeyException(e.getMessage()); } } private String getAttribute(SafeBag safeBag, String attrType) { int cnt = safeBag.bagAttributes.getCount(); String value = null; for(int i = 0; i < cnt; i++) { Attribute a = (Attribute)safeBag.bagAttributes.getComponent(i); if(attrType.equals(a.type.getString())) { ASN1Object v = a.values.getComponent(0); if(v instanceof ASN1CharString) { value = ((ASN1CharString)v).getValue(); } else if(v instanceof ASN1OctetString) { value = HexDump.toString(((ASN1OctetString)v).getRaw()); } else { value = v.toString(); } } } return value; } private static byte[] deriveKey(char[] password, int keyLen, byte[] salt, int iterations, int id, String digAlg) { try { MessageDigest digest = MessageDigest.getInstance(digAlg); int u = digest.getDigestLength(); byte[] Ai = new byte[u]; byte[] key = new byte[keyLen]; int v = 64; // TODO Set this from digest (bad API!) byte[] pb = new byte[password.length * 2 + 2]; int sl = ((salt.length + v - 1) / v) * v; int pl = ((pb.length + v - 1) / v) * v; byte[] D = new byte[v]; byte[] I = new byte[sl + pl]; byte[] B = new byte[v]; int i; for(i = 0; i < password.length; i++) { pb[i * 2] = (byte)(password[i] >>> 8); pb[(i * 2) + 1] = (byte)(password[i] & 0xff); } for(i = 0; i < v; i++) { D[i] = (byte)id; } for(i = 0; i < sl; i++) { I[i] = salt[i % salt.length]; } for(i = 0; i < pl; i++) { I[sl + i] = pb[i % pb.length]; } int cnt = 0; BigInteger one = BigInteger.valueOf(1L); byte[] ijRaw = new byte[v]; while(true) { digest.update(D); digest.update(I); digest.digest(Ai, 0, u); for(i = 1; i < iterations; i++) { digest.update(Ai); digest.digest(Ai, 0, u); } int n = ((u > (keyLen - cnt)) ? keyLen - cnt : u); System.arraycopy(Ai, 0, key, cnt, n); cnt += n; if(cnt >= keyLen) { break; } for(i = 0; i < v; i++) { B[i] = Ai[i % u]; } BigInteger Bplus1 = (new BigInteger(1, B)).add(one); for(i = 0; i < I.length; i += v) { System.arraycopy(I, i, ijRaw, 0, v); BigInteger Ij = new BigInteger(1, ijRaw); Ij = Ij.add(Bplus1); ijRaw = unsignedBigIntToBytes(Ij, v); System.arraycopy(ijRaw, 0, I, i, v); } } return key; } catch (Exception e) { throw new Error("Error in PKCS12.deriveKey: " + e); } } private static byte[] unsignedBigIntToBytes(BigInteger bi, int size) { byte[] tmp = bi.toByteArray(); byte[] tmp2 = null; if(tmp.length > size) { tmp2 = new byte[size]; System.arraycopy(tmp, tmp.length - size, tmp2, 0, size); } else if(tmp.length < size) { tmp2 = new byte[size]; System.arraycopy(tmp, 0, tmp2, size - tmp.length, tmp.length); } else { tmp2 = tmp; } return tmp2; } private static byte[] deriveKeyPKCS5(char[] password, byte[] salt, int iterations, int dklen, String digAlg) { try { MessageDigest digest = MessageDigest.getInstance(digAlg); byte[] pass = new byte[password.length]; for (int i=0; i<password.length; i++) pass[i] = (byte)(password[i]&0xff); digest.update(pass); digest.update(salt); byte[] dig = digest.digest(); int len = dig.length; for(int i = 1; i < iterations; i++) { digest.update(dig); digest.digest(dig, 0, len); } byte[] ret = new byte[dklen]; System.arraycopy(dig, 0, ret, 0, dklen); return ret; } catch (Throwable t) { t.printStackTrace(); } return null; } private static void doCipher(int mode, char[] password, byte[] input, int len, byte[] output, byte[] salt, int iterations, String cipherType) throws NoSuchAlgorithmException { try { int keyLen = 40; boolean pkcs5 = false; String hashType = "SHA"; if (cipherType.equals("pbeWithSHAAnd3-KeyTripleDES-CBC")) { keyLen = 192; cipherType = "3DES/CBC/PKCS5Padding"; } else if (cipherType.equals("pbeWithSHAAnd2-KeyTripleDES-CBC")) { keyLen = 128; cipherType = "3DES/CBC/PKCS5Padding"; }else if (cipherType.equals("pbeWithSHAAnd40BitRC2-CBC")) { // keyLen = 40; cipherType ="RC2/CBC/PKCS5Padding"; } else if (cipherType.equals("pbeWithSHAAnd128BitRC2-CBC")) { keyLen = 128; cipherType ="RC2/CBC/PKCS5Padding"; } else if (cipherType.equals("pbeWithSHAAnd40BitRC4")) { // keyLen = 40; cipherType = "RC4/OFB/PKCS5Padding"; } else if (cipherType.equals("pbeWithSHAAnd128BitRC4")) { keyLen = 128; cipherType = "RC4/OFB/PKCS5Padding"; } else if (cipherType.equals("pbeWithSHA1AndRC2-CBC")) { pkcs5 = true; keyLen = 64; cipherType = "RC2/CBC/PKCS5Padding"; hashType = "SHA1"; } else if (cipherType.equals("pbeWithMD2AndRC2-CBC")) { pkcs5 = true; keyLen = 64; cipherType = "RC2/CBC/PKCS5Padding"; hashType = "MD2"; } else if (cipherType.equals("pbeWithMD5AndRC2-CBC")) { pkcs5 = true; keyLen = 64; cipherType = "RC2/CBC/PKCS5Padding"; hashType = "MD5"; } else if (cipherType.equals("pbeWithMD2AndDES-CBC")) { pkcs5 = true; keyLen = 64; cipherType = "DES/CBC/PKCS5Padding"; hashType = "MD2"; } else if (cipherType.equals("pbeWithMD5AndDES-CBC")) { pkcs5 = true; keyLen = 64; cipherType = "DES/CBC/PKCS5Padding"; hashType = "MD5"; } else if (cipherType.equals("pbeWithSHA1AndDES-CBC")) { pkcs5 = true; keyLen = 64; cipherType = "DES/CBC/PKCS5Padding"; hashType = "SHA1"; } keyLen /= 8; Cipher cipher = Cipher.getInstance(cipherType); cipherType = cipher.getAlgorithm(); byte[] key; byte[] iv; if (pkcs5) { byte[] dk = deriveKeyPKCS5(password, salt, iterations, 16, hashType); key = new byte[8]; System.arraycopy(dk, 0, key, 0, 8); iv = new byte[8]; System.arraycopy(dk, 8, iv, 0, 8); } else { key = deriveKey(password, keyLen, salt, iterations, 1, hashType); iv = deriveKey(password, 8, salt, iterations, 2, hashType); } cipher.init(mode, new SecretKeySpec(key, cipherType), new IvParameterSpec(iv)); cipher.doFinal(input, 0, len, output, 0); } catch (InvalidKeyException e) { throw new Error("Invalid key derived in " + "PKCS12KeyStore.doCipher: " + e); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -