1041 }
1042
1043 /**
1044 * Returns true if the entry identified by the given alias is a
1045 * <i>trusted certificate entry</i>, and false otherwise.
1046 *
1047 * @return true if the entry identified by the given alias is a
1048 * <i>trusted certificate entry</i>, false otherwise.
1049 */
1050 public boolean engineIsCertificateEntry(String alias) {
1051 Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
1052 if (entry != null && entry instanceof CertEntry &&
1053 ((CertEntry) entry).trustedKeyUsage != null) {
1054 return true;
1055 } else {
1056 return false;
1057 }
1058 }
1059
1060 /**
1061 * Returns the (alias) name of the first keystore entry whose certificate
1062 * matches the given certificate.
1063 *
1064 * <p>This method attempts to match the given certificate with each
1065 * keystore entry. If the entry being considered
1066 * is a <i>trusted certificate entry</i>, the given certificate is
1067 * compared to that entry's certificate. If the entry being considered is
1068 * a <i>key entry</i>, the given certificate is compared to the first
1069 * element of that entry's certificate chain (if a chain exists).
1070 *
1071 * @param cert the certificate to match with.
1072 *
1073 * @return the (alias) name of the first entry with matching certificate,
1074 * or null if no such entry exists in this keystore.
1075 */
1076 public String engineGetCertificateAlias(Certificate cert) {
1077 Certificate certElem = null;
1078
1079 for (Enumeration<String> e = engineAliases(); e.hasMoreElements(); ) {
1080 String alias = e.nextElement();
1081 Entry entry = entries.get(alias);
1082 if (entry instanceof PrivateKeyEntry) {
1083 if (((PrivateKeyEntry) entry).chain != null) {
1084 certElem = ((PrivateKeyEntry) entry).chain[0];
1085 }
1086 } else if (entry instanceof CertEntry &&
1087 ((CertEntry) entry).trustedKeyUsage != null) {
1088 certElem = ((CertEntry) entry).cert;
1089 } else {
1090 continue;
1091 }
1092 if (certElem.equals(cert)) {
1093 return alias;
1094 }
1095 }
1096 return null;
1097 }
1098
1099 /**
1100 * Stores this keystore to the given output stream, and protects its
1101 * integrity with the given password.
1102 *
1103 * @param stream the output stream to which this keystore is written.
1104 * @param password the password to generate the keystore integrity check
1105 *
1106 * @exception IOException if there was an I/O problem with data
1107 * @exception NoSuchAlgorithmException if the appropriate data integrity
1108 * algorithm could not be found
1109 * @exception CertificateException if any of the certificates included in
1110 * the keystore data could not be stored
1111 */
1112 public synchronized void engineStore(OutputStream stream, char[] password)
1915 */
1916 for (int i = 0; i < count; i++) {
1917 byte[] safeContentsData;
1918 ContentInfo safeContents;
1919 DerInputStream sci;
1920 byte[] eAlgId = null;
1921
1922 sci = new DerInputStream(safeContentsArray[i].toByteArray());
1923 safeContents = new ContentInfo(sci);
1924 contentType = safeContents.getContentType();
1925 safeContentsData = null;
1926 if (contentType.equals((Object)ContentInfo.DATA_OID)) {
1927
1928 if (debug != null) {
1929 debug.println("Loading PKCS#7 data content-type");
1930 }
1931
1932 safeContentsData = safeContents.getData();
1933 } else if (contentType.equals((Object)ContentInfo.ENCRYPTED_DATA_OID)) {
1934 if (password == null) {
1935 continue;
1936 }
1937
1938 if (debug != null) {
1939 debug.println("Loading PKCS#7 encryptedData content-type");
1940 }
1941
1942 DerInputStream edi =
1943 safeContents.getContent().toDerInputStream();
1944 int edVersion = edi.getInteger();
1945 DerValue[] seq = edi.getSequence(2);
1946 ObjectIdentifier edContentType = seq[0].getOID();
1947 eAlgId = seq[1].toByteArray();
1948 if (!seq[2].isContextSpecific((byte)0)) {
1949 throw new IOException("encrypted content not present!");
1950 }
1951 byte newTag = DerValue.tag_OctetString;
1952 if (seq[2].isConstructed())
1953 newTag |= 0x20;
1954 seq[2].resetTag(newTag);
1957 // parse Algorithm parameters
1958 DerInputStream in = seq[1].toDerInputStream();
1959 ObjectIdentifier algOid = in.getOID();
1960 AlgorithmParameters algParams = parseAlgParameters(algOid, in);
1961
1962 while (true) {
1963 try {
1964 // Use JCE
1965 SecretKey skey = getPBEKey(password);
1966 Cipher cipher = Cipher.getInstance(algOid.toString());
1967 cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
1968 safeContentsData = cipher.doFinal(safeContentsData);
1969 break;
1970 } catch (Exception e) {
1971 if (password.length == 0) {
1972 // Retry using an empty password
1973 // without a NULL terminator.
1974 password = new char[1];
1975 continue;
1976 }
1977 throw new IOException(
1978 "failed to decrypt safe contents entry: " + e, e);
1979 }
1980 }
1981 } else {
1982 throw new IOException("public key protected PKCS12" +
1983 " not supported");
1984 }
1985 DerInputStream sc = new DerInputStream(safeContentsData);
1986 loadSafeContents(sc, password);
1987 }
1988
1989 // The MacData is optional.
1990 if (password != null && s.available() > 0) {
1991 MacData macData = new MacData(s);
1992 try {
1993 String algName =
1994 macData.getDigestAlgName().toUpperCase(Locale.ENGLISH);
1995
1996 // Change SHA-1 to SHA1
1997 algName = algName.replace("-", "");
1998
|
1041 }
1042
1043 /**
1044 * Returns true if the entry identified by the given alias is a
1045 * <i>trusted certificate entry</i>, and false otherwise.
1046 *
1047 * @return true if the entry identified by the given alias is a
1048 * <i>trusted certificate entry</i>, false otherwise.
1049 */
1050 public boolean engineIsCertificateEntry(String alias) {
1051 Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
1052 if (entry != null && entry instanceof CertEntry &&
1053 ((CertEntry) entry).trustedKeyUsage != null) {
1054 return true;
1055 } else {
1056 return false;
1057 }
1058 }
1059
1060 /**
1061 * Determines if the keystore {@code Entry} for the specified
1062 * {@code alias} is an instance or subclass of the specified
1063 * {@code entryClass}.
1064 *
1065 * @param alias the alias name
1066 * @param entryClass the entry class
1067 *
1068 * @return true if the keystore {@code Entry} for the specified
1069 * {@code alias} is an instance or subclass of the
1070 * specified {@code entryClass}, false otherwise
1071 *
1072 * @since 1.5
1073 */
1074 @Override
1075 public boolean
1076 engineEntryInstanceOf(String alias,
1077 Class<? extends KeyStore.Entry> entryClass)
1078 {
1079 if (entryClass == KeyStore.TrustedCertificateEntry.class) {
1080 return engineIsCertificateEntry(alias);
1081 }
1082
1083 Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
1084 if (entryClass == KeyStore.PrivateKeyEntry.class) {
1085 return (entry != null && entry instanceof PrivateKeyEntry);
1086 }
1087 if (entryClass == KeyStore.SecretKeyEntry.class) {
1088 return (entry != null && entry instanceof SecretKeyEntry);
1089 }
1090 return false;
1091 }
1092
1093 /**
1094 * Returns the (alias) name of the first keystore entry whose certificate
1095 * matches the given certificate.
1096 *
1097 * <p>This method attempts to match the given certificate with each
1098 * keystore entry. If the entry being considered
1099 * is a <i>trusted certificate entry</i>, the given certificate is
1100 * compared to that entry's certificate. If the entry being considered is
1101 * a <i>key entry</i>, the given certificate is compared to the first
1102 * element of that entry's certificate chain (if a chain exists).
1103 *
1104 * @param cert the certificate to match with.
1105 *
1106 * @return the (alias) name of the first entry with matching certificate,
1107 * or null if no such entry exists in this keystore.
1108 */
1109 public String engineGetCertificateAlias(Certificate cert) {
1110 Certificate certElem = null;
1111
1112 for (Enumeration<String> e = engineAliases(); e.hasMoreElements(); ) {
1113 String alias = e.nextElement();
1114 Entry entry = entries.get(alias);
1115 if (entry instanceof PrivateKeyEntry) {
1116 if (((PrivateKeyEntry) entry).chain != null) {
1117 certElem = ((PrivateKeyEntry) entry).chain[0];
1118 }
1119 } else if (entry instanceof CertEntry &&
1120 ((CertEntry) entry).trustedKeyUsage != null) {
1121 certElem = ((CertEntry) entry).cert;
1122 } else {
1123 continue;
1124 }
1125 if (certElem != null && certElem.equals(cert)) {
1126 return alias;
1127 }
1128 }
1129 return null;
1130 }
1131
1132 /**
1133 * Stores this keystore to the given output stream, and protects its
1134 * integrity with the given password.
1135 *
1136 * @param stream the output stream to which this keystore is written.
1137 * @param password the password to generate the keystore integrity check
1138 *
1139 * @exception IOException if there was an I/O problem with data
1140 * @exception NoSuchAlgorithmException if the appropriate data integrity
1141 * algorithm could not be found
1142 * @exception CertificateException if any of the certificates included in
1143 * the keystore data could not be stored
1144 */
1145 public synchronized void engineStore(OutputStream stream, char[] password)
1948 */
1949 for (int i = 0; i < count; i++) {
1950 byte[] safeContentsData;
1951 ContentInfo safeContents;
1952 DerInputStream sci;
1953 byte[] eAlgId = null;
1954
1955 sci = new DerInputStream(safeContentsArray[i].toByteArray());
1956 safeContents = new ContentInfo(sci);
1957 contentType = safeContents.getContentType();
1958 safeContentsData = null;
1959 if (contentType.equals((Object)ContentInfo.DATA_OID)) {
1960
1961 if (debug != null) {
1962 debug.println("Loading PKCS#7 data content-type");
1963 }
1964
1965 safeContentsData = safeContents.getData();
1966 } else if (contentType.equals((Object)ContentInfo.ENCRYPTED_DATA_OID)) {
1967 if (password == null) {
1968
1969 if (debug != null) {
1970 debug.println("Warning: skipping PKCS#7 encryptedData" +
1971 " content-type - no password was supplied");
1972 }
1973 continue;
1974 }
1975
1976 if (debug != null) {
1977 debug.println("Loading PKCS#7 encryptedData content-type");
1978 }
1979
1980 DerInputStream edi =
1981 safeContents.getContent().toDerInputStream();
1982 int edVersion = edi.getInteger();
1983 DerValue[] seq = edi.getSequence(2);
1984 ObjectIdentifier edContentType = seq[0].getOID();
1985 eAlgId = seq[1].toByteArray();
1986 if (!seq[2].isContextSpecific((byte)0)) {
1987 throw new IOException("encrypted content not present!");
1988 }
1989 byte newTag = DerValue.tag_OctetString;
1990 if (seq[2].isConstructed())
1991 newTag |= 0x20;
1992 seq[2].resetTag(newTag);
1995 // parse Algorithm parameters
1996 DerInputStream in = seq[1].toDerInputStream();
1997 ObjectIdentifier algOid = in.getOID();
1998 AlgorithmParameters algParams = parseAlgParameters(algOid, in);
1999
2000 while (true) {
2001 try {
2002 // Use JCE
2003 SecretKey skey = getPBEKey(password);
2004 Cipher cipher = Cipher.getInstance(algOid.toString());
2005 cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
2006 safeContentsData = cipher.doFinal(safeContentsData);
2007 break;
2008 } catch (Exception e) {
2009 if (password.length == 0) {
2010 // Retry using an empty password
2011 // without a NULL terminator.
2012 password = new char[1];
2013 continue;
2014 }
2015 throw new IOException("keystore password was incorrect",
2016 new UnrecoverableKeyException(
2017 "failed to decrypt safe contents entry: " + e));
2018 }
2019 }
2020 } else {
2021 throw new IOException("public key protected PKCS12" +
2022 " not supported");
2023 }
2024 DerInputStream sc = new DerInputStream(safeContentsData);
2025 loadSafeContents(sc, password);
2026 }
2027
2028 // The MacData is optional.
2029 if (password != null && s.available() > 0) {
2030 MacData macData = new MacData(s);
2031 try {
2032 String algName =
2033 macData.getDigestAlgName().toUpperCase(Locale.ENGLISH);
2034
2035 // Change SHA-1 to SHA1
2036 algName = algName.replace("-", "");
2037
|