📄 mekeytool.java
字号:
} finally { input.close(); } }; /** * Constructs a MEKeyTool and loads its keystore from a stream. * @param meKeystoreStream serialized keystore stream * @exception IOException if the key storage was corrupted */ public MEKeyTool(InputStream meKeystoreStream) throws IOException { keystore = new PublicKeyStoreBuilderBase(meKeystoreStream); }; /** * Copies a key from a Standard Edition keystore into the ME keystore. * @param jcakeystoreFilename name of the serialized keystore * @param keystorePassword password to unlock the keystore * @param alias the ID of the key in the SE keystore * @param domain security domain of any application authorized * with the corresponding private key */ public void importKeyFromJcaKeystore(String jcakeystoreFilename, String keystorePassword, String alias, String domain) throws IOException, GeneralSecurityException { FileInputStream keystoreStream; KeyStore jcaKeystore; // Load the keystore keystoreStream = new FileInputStream(new File(jcakeystoreFilename)); try { jcaKeystore = KeyStore.getInstance(KeyStore.getDefaultType()); if (keystorePassword == null) { jcaKeystore.load(keystoreStream, null); } else { jcaKeystore.load(keystoreStream, keystorePassword.toCharArray()); } } finally { keystoreStream.close(); } importKeyFromJcaKeystore(jcaKeystore, alias, domain); } /** * Copies a key from a Standard Edition keystore into the ME keystore. * @param jcaKeystore loaded JCA keystore * @param alias the ID of the key in the SE keystore * @param domain security domain of any application authorized * with the corresponding private key */ public void importKeyFromJcaKeystore(KeyStore jcaKeystore, String alias, String domain) throws IOException, GeneralSecurityException { X509Certificate cert; byte[] der; TLV tbsCert; TLV subjectName; RSAPublicKey rsaKey; String owner; long notBefore; long notAfter; byte[] rawModulus; int i; int keyLen; byte[] modulus; byte[] exponent; Vector keys; // get the cert from the keystore try { cert = (X509Certificate)jcaKeystore.getCertificate(alias); } catch (ClassCastException cce) { throw new CertificateException("Certificate not X.509 type"); } if (cert == null) { throw new CertificateException("Certificate not found"); } /* * J2SE reorders the attributes when building a printable name * so we must build a printable name on our own. */ /* * TBSCertificate ::= SEQUENCE { * version [0] EXPLICIT Version DEFAULT v1, * serialNumber CertificateSerialNumber, * signature AlgorithmIdentifier, * issuer Name, * validity Validity, * subject Name, * subjectPublicKeyInfo SubjectPublicKeyInfo, * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * extensions [3] EXPLICIT Extensions OPTIONAL * -- If present, version shall be v3 * } */ der = cert.getTBSCertificate(); tbsCert = new TLV(der, 0); // walk down the tree of TLVs to find the subject name try { // Top level a is Sequence, drop down to the first child subjectName = tbsCert.child; // skip the version if present. if (subjectName.type == TLV.VERSION_TYPE) { subjectName = subjectName.next; } // skip the serial number subjectName = subjectName.next; // skip the signature alg. id. subjectName = subjectName.next; // skip the issuer subjectName = subjectName.next; // skip the validity subjectName = subjectName.next; owner = parseDN(der, subjectName); } catch (NullPointerException e) { throw new CertificateException("TBSCertificate corrupt 1"); } catch (IndexOutOfBoundsException e) { throw new CertificateException("TBSCertificate corrupt 2"); } notBefore = cert.getNotBefore().getTime(); notAfter = cert.getNotAfter().getTime(); // get the key from the cert try { rsaKey = (RSAPublicKey)cert.getPublicKey(); } catch (ClassCastException cce) { throw new RuntimeException("Key in certificate is not an RSA key"); } // get the key parameters from the key rawModulus = rsaKey.getModulus().toByteArray(); /* * the modulus is given as the minimum positive integer, * will not padded to the bit size of the key, or may have a extra * pad to make it positive. SSL expects the key to be signature * bit size. but we cannot get that from the key, so we should * remove any zero pad bytes and then pad out to a multiple of 8 bytes */ for (i = 0; i < rawModulus.length && rawModulus[i] == 0; i++); keyLen = rawModulus.length - i; keyLen = (keyLen + 7) / 8 * 8; modulus = new byte[keyLen]; int k, j; for (k = rawModulus.length - 1, j = keyLen - 1; k >= 0 && j >= 0; k--, j--) { modulus[j] = rawModulus[k]; } exponent = rsaKey.getPublicExponent().toByteArray(); // add the key keys = keystore.findKeys(owner); if (keys != null) { boolean duplicateKey = false; for (int n = 0; !duplicateKey && n < keys.size(); n++) { PublicKeyInfo key = (PublicKeyInfo)keys.elementAt(n); if (key.getOwner().equals(owner)) { byte[] temp = key.getModulus(); if (modulus.length == temp.length) { duplicateKey = true; for (int m = 0; j < modulus.length && m < temp.length; m++) { if (modulus[m] != temp[m]) { duplicateKey = false; break; } } } } } if (duplicateKey) { throw new CertificateException( "Owner already has this key in the ME keystore"); } } keystore.addKey(new PublicKeyInfo(owner, notBefore, notAfter, modulus, exponent, domain)); } /** * Deletes the first public key matching the owner's distinguished name. * @param owner name of the key's owner * @return true, if the key was deleted, else false */ public boolean deleteKey(String owner) { PublicKeyInfo key; for (int i = 0; i < keystore.numberOfKeys(); i++) { key = keystore.getKey(i); if (key.getOwner().equals(owner)) { keystore.deleteKey(i); return true; } } return false; }; /** * Deletes a key by key number, 0 being the first public key. * * @param number number of the key * * @exception ArrayIndexOutOfBoundsException if an invalid number was * given. */ public void deleteKey(int number) { keystore.deleteKey(number); }; /** * Gets the first key in the keystore. * @return all the information related to the first key */ protected PublicKeyInfo getFirstKey() { nextKeyToGet = 0; return getNextKey(); }; /** * Gets the next key after the previous one returned by * {@link #getFirstKey} or this method. If getFirstKey is not called * before the first call to this method, null will be returned. * @return all the information related to the next key, or null if * there are no more keys */ protected PublicKeyInfo getNextKey() { PublicKeyInfo key; try { key = keystore.getKey(nextKeyToGet); } catch (ArrayIndexOutOfBoundsException e) { return null; } nextKeyToGet++; return key; }; /** * Saves the keystore to a file. * @param meKeystoreFile serialized keystore file */ public void saveKeystore(File meKeystoreFile) throws IOException { FileOutputStream output; output = new FileOutputStream(meKeystoreFile); keystore.serialize(output); output.close(); } /** * Gets the read-write keystore this tool is manipulating. * For advanced users. * @return read-write keystore */ public PublicKeyStoreBuilderBase getKeystore() { return keystore; } /** * Creates a string representation of a key that is displayed to a * user during a list command. The string does not include the modulus * and exponent. * @param keyInfo key to display * @return printable representation of the key */ public static String formatKeyInfo(PublicKeyInfo keyInfo) { return " Owner: " + keyInfo.getOwner() + "\n Valid from " + (new Date(keyInfo.getNotBefore())).toString() + " to " + (new Date(keyInfo.getNotAfter())).toString() + "\n Security Domain: " + keyInfo.getDomain(); }; /** * Parses a DER TLV tree into a printable distinguished name. * * @param buffer DER buffer * @param dn sequence of TLV nodes. * * @return printable name. * * @exception NullPointerException if the name is corrupt * @exception IndexOutOfBoundsException if the name is corrupt */ private String parseDN(byte[] buffer, TLV dn) { TLV attribute; TLV type; TLV value; StringBuffer name = new StringBuffer(256); /* * Name ::= CHOICE { RDNSequence } # CHOICE does not encoded * * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * * basically this means that each attribute value is 3 levels down */ // sequence drop down a level attribute = dn.child; while (attribute != null) { if (attribute != dn.child) { name.append(";"); } /* * we do not handle relative distingushed names yet * which should not be used by CAs anyway * so only take the first element of the sequence */ type = attribute.child.child; /* * At this point we tag the name component, e.g. C= or hex * if unknown. */ if ((type.length == 3) && (buffer[type.valueOffset] == 0x55) && (buffer[type.valueOffset + 1] == 0x04)) { // begins with id-at, so try to see if we have a label int temp = buffer[type.valueOffset + 2] & 0xFF; if ((temp < AttrLabel.length) && (AttrLabel[temp] != null)) { name.append(AttrLabel[temp]); } else { name.append(TLV.hexEncode(buffer, type.valueOffset, type.length, -1)); } } else if (TLV.byteMatch(buffer, type.valueOffset, type.length, EMAIL_ATTR_OID, 0, EMAIL_ATTR_OID.length)) { name.append(EMAIL_ATTR_LABEL); } else { name.append(TLV.hexEncode(buffer, type.valueOffset, type.length, -1)); } name.append("="); value = attribute.child.child.next; if (value.type == TLV.PRINTSTR_TYPE || value.type == TLV.TELETEXSTR_TYPE || value.type == TLV.UTF8STR_TYPE || value.type == TLV.IA5STR_TYPE || value.type == TLV.UNIVSTR_TYPE) { try { name.append(new String(buffer, value.valueOffset, value.length, "UTF-8")); } catch (UnsupportedEncodingException e) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -