undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8136534
* @summary The input stream supplied to KeyStore.load should remain open.
*/
import java.io.*;
import java.security.*;
public class CheckInputStream {
private final static String DIR = System.getProperty("test.src", ".");
private static final char[] PASSWORD = "passphrase".toCharArray();
private static final String KEYSTORE = DIR + "/keystore.jks";
public static final void main(String[] args) throws Exception {
KeyStore keystore = KeyStore.getInstance("JKS");
try (FileInputStream inStream = new FileInputStream(KEYSTORE)) {
System.out.println("Loading JKS keystore: " + KEYSTORE);
keystore.load(inStream, PASSWORD);
// check that the stream is still open
inStream.available();
System.out.println("OK");
}
}
}

View file

@ -0,0 +1,137 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.security.KeyStore;
import java.util.HashSet;
import java.util.Set;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
/*
* @test
* @bug 8303465 8320362
* @library /test/lib
* @requires os.family == "mac"
* @summary Check whether loading of certificates from MacOS Keychain correctly
* honors trust settings
* @run main CheckMacOSKeyChainTrust KEYCHAINSTORE
* @run main CheckMacOSKeyChainTrust KEYCHAINSTORE-ROOT
*/
public class CheckMacOSKeyChainTrust {
private static Set<String> trusted = new HashSet<>();
private static Set<String> distrusted = new HashSet<>();
public static void main(String[] args) throws Throwable {
String keystore = args[0];
if (keystore.equals("KEYCHAINSTORE")) {
loadUser(true);
loadAdmin(true);
} else {
// check user and admin trustsettings to find distrusted certs
loadUser(false);
loadAdmin(false);
loadSystem(true);
}
System.out.println("Trusted Certs: " + trusted);
System.out.println("Distrusted Certs: " + distrusted);
KeyStore ks = KeyStore.getInstance(keystore);
ks.load(null, null);
for (String alias : trusted) {
if (!ks.containsAlias(alias)) {
throw new RuntimeException("Not found: " + alias);
}
}
for (String alias : distrusted) {
if (ks.containsAlias(alias)) {
throw new RuntimeException("Found: " + alias);
}
}
}
private static void loadUser(boolean addTrusted) throws Throwable {
populate(ProcessTools.executeProcess("security", "dump-trust-settings"), addTrusted);
}
private static void loadAdmin(boolean addTrusted) throws Throwable {
populate(ProcessTools.executeProcess("security", "dump-trust-settings", "-d"), addTrusted);
}
private static void loadSystem(boolean addTrusted) throws Throwable {
populate(ProcessTools.executeProcess("security", "dump-trust-settings", "-s"), addTrusted);
}
private static void populate(OutputAnalyzer output, boolean addTrusted) throws Throwable {
if (output.getExitValue() != 0) {
return; // No Trust Settings were found
}
String certName = null;
boolean trustRootFound = false;
boolean trustAsRootFound = false;
boolean denyFound = false;
boolean unspecifiedFound = false;
for (String line : output.asLines()) {
if (line.startsWith("Cert ")) {
if (certName != null) {
if (!denyFound &&
!(unspecifiedFound && !(trustRootFound || trustAsRootFound)) &&
!distrusted.contains(certName)) {
if (addTrusted) {
trusted.add(certName);
}
} else {
distrusted.add(certName);
trusted.remove(certName);
}
}
certName = line.split(":", 2)[1].trim().toLowerCase();
trustRootFound = false;
trustAsRootFound = false;
denyFound = false;
unspecifiedFound = false;
} else if (line.contains("kSecTrustSettingsResultTrustRoot")) {
trustRootFound = true;
} else if (line.contains("kSecTrustSettingsResultTrustAsRoot")) {
trustAsRootFound = true;
} else if (line.contains("kSecTrustSettingsResultDeny")) {
denyFound = true;
} else if (line.contains("kSecTrustSettingsResultUnspecified")) {
unspecifiedFound = true;
}
}
if (certName != null) {
if (!denyFound &&
!(unspecifiedFound && !(trustRootFound || trustAsRootFound)) &&
!distrusted.contains(certName)) {
if (addTrusted) {
trusted.add(certName);
}
} else {
distrusted.add(certName);
trusted.remove(certName);
}
}
}
}

View file

@ -0,0 +1,235 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test 1.1, 03/06/24
* @bug 4850376
* @summary Provide generic storage KeyStore storage facilities
*/
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Principal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Set;
import java.util.HashSet;
import java.math.BigInteger;
import javax.security.auth.x500.X500Principal;
public class DefaultEntryType {
private static class PrivKey1 implements PrivateKey {
public String getAlgorithm() { return ("matching_alg"); }
public String getFormat() { return "privkey1"; }
public byte[] getEncoded() { return (byte[])null; }
}
private static class PubKey1 implements PublicKey {
public String getAlgorithm() { return ("non_matching_alg"); }
public String getFormat() { return "pubkey1"; }
public byte[] getEncoded() { return (byte[])null; }
}
private static class PubKey2 implements PublicKey {
public String getAlgorithm() { return ("matching_alg"); }
public String getFormat() { return "pubkey2"; }
public byte[] getEncoded() { return (byte[])null; }
}
private static class Cert extends Certificate {
public Cert() { super("cert"); }
public byte[] getEncoded()
throws CertificateEncodingException { return (byte[])null; }
public void verify(PublicKey key)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException,
SignatureException { }
public void verify(PublicKey key, String sigProvider)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException,
SignatureException { }
public String toString() { return "cert"; }
public PublicKey getPublicKey() { return new PubKey1(); }
}
private static class X509Cert extends X509Certificate {
public byte[] getEncoded()
throws CertificateEncodingException { return (byte[])null; }
public void verify(PublicKey key)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException,
SignatureException { }
public void verify(PublicKey key, String sigProvider)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException,
SignatureException { }
public String toString() { return "x509cert"; }
public PublicKey getPublicKey() { return new PubKey2(); }
public void checkValidity()
throws CertificateExpiredException,
CertificateNotYetValidException { }
public void checkValidity(java.util.Date date)
throws CertificateExpiredException,
CertificateNotYetValidException { }
public int getVersion() { return 1; }
public BigInteger getSerialNumber() { return new BigInteger("5", 10); }
public Principal getIssuerDN()
{ return new X500Principal("cn=x509cert"); }
public X500Principal getIssuerX500Principal()
{ return new X500Principal("cn=x509cert"); }
public Principal getSubjectDN()
{ return new X500Principal("cn=x509cert"); }
public X500Principal getSubjectX500Principal()
{ return new X500Principal("cn=x509cert"); }
public Date getNotBefore() { return new Date(); }
public Date getNotAfter() { return new Date(); }
public byte[] getTBSCertificate() throws CertificateEncodingException
{ return (byte[])null; }
public byte[] getSignature() { return (byte[])null; }
public String getSigAlgName() { return "x509cert"; }
public String getSigAlgOID() { return "x509cert"; }
public byte[] getSigAlgParams() { return (byte[])null; }
public boolean[] getIssuerUniqueID() { return (boolean[])null; }
public boolean[] getSubjectUniqueID() { return (boolean[])null; }
public boolean[] getKeyUsage() { return (boolean[]) null; }
public int getBasicConstraints() { return 1; }
public boolean hasUnsupportedCriticalExtension() { return true; }
public Set getCriticalExtensionOIDs() { return new HashSet(); }
public Set getNonCriticalExtensionOIDs() { return new HashSet(); }
public byte[] getExtensionValue(String oid) { return (byte[])null; }
}
public static void main(String[] args) throws Exception {
testPrivateKeyEntry();
testSecretKeyEntry();
testTrustedCertificateEntry();
}
private static void testPrivateKeyEntry() throws Exception {
// TEST null private key
try {
Certificate[] chain = new Certificate[0];
KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
(null, chain);
throw new SecurityException("test 1 failed");
} catch (NullPointerException npe) {
// good
System.out.println("test 1 passed");
}
// TEST null chain
try {
KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
(new PrivKey1(), null);
throw new SecurityException("test 2 failed");
} catch (NullPointerException npe) {
// good
System.out.println("test 2 passed");
}
// TEST empty chain
try {
Certificate[] chain = new Certificate[0];
KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
(new PrivKey1(), chain);
throw new SecurityException("test 3 failed");
} catch (IllegalArgumentException npe) {
// good
System.out.println("test 3 passed");
}
// TEST non-homogenous chain
try {
Certificate[] chain = new Certificate[2];
chain[0] = new Cert();
chain[1] = new X509Cert();
KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
(new PrivKey1(), chain);
throw new SecurityException("test 4 failed");
} catch (IllegalArgumentException npe) {
// good
System.out.println("test 4 passed");
}
// TEST non matching algorithms
try {
Certificate[] chain = new Certificate[1];
chain[0] = new Cert();
KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
(new PrivKey1(), chain);
throw new SecurityException("test 5 failed");
} catch (IllegalArgumentException npe) {
// good
System.out.println("test 5 passed");
}
// TEST correct behavior
Certificate[] chain = new Certificate[2];
chain[0] = new X509Cert();
chain[1] = new X509Cert();
PrivateKey pkey = new PrivKey1();
KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
(pkey, chain);
Certificate[] gotChain = pke.getCertificateChain();
if (gotChain instanceof X509Certificate[]) {
System.out.println("test 6 passed");
} else {
throw new SecurityException("test 6 failed");
}
if (gotChain.length == 2 &&
gotChain[0] == chain[0] &&
gotChain[1] == chain[1]) {
System.out.println("test 7 passed");
} else {
throw new SecurityException("test 7 failed");
}
if (pke.getPrivateKey() == pkey) {
System.out.println("test 8 passed");
} else {
throw new SecurityException("test 8 failed");
}
}
private static void testSecretKeyEntry() throws Exception {
}
private static void testTrustedCertificateEntry() throws Exception {
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8373690
* @summary verify that the exception message indicates the keystore type
* when the type is disabled instead of being unrecognized
* @run main/othervm -Djdk.crypto.disabledAlgorithms=KeyStore.PKCS12 DisabledKnownType
*/
import java.security.KeyStore;
import java.security.KeyStoreException;
public class DisabledKnownType {
public static void main(String[] args) throws Exception {
String cacertsPath = System.getProperty("java.home") +
"/lib/security/cacerts";
try {
KeyStore ks = KeyStore.getInstance(new java.io.File(cacertsPath),
"changeit".toCharArray());
throw new RuntimeException("Expected KeyStoreException not thrown");
} catch (KeyStoreException kse) {
if (kse.getMessage().contains("PKCS12")) {
System.out.println("Passed: expected ex thrown: " + kse);
} else {
// pass it up
throw kse;
}
}
}
}

View file

@ -0,0 +1,578 @@
/*
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test 1.5, 03/06/24
* @bug 4850376 8130850 8130181
* @summary Provide generic storage KeyStore storage facilities
*/
import java.security.*;
import java.security.cert.*;
import java.util.*;
import java.io.*;
public class EntryMethods
extends Provider
implements KeyStore.Entry
{
private static FileInputStream pre15fis;
private static char[] password = {'f', 'o', 'o', 'b', 'a', 'r'};
private static char[] badPwd = {'b', 'a', 'd', 'p', 'w', 'd'};
public static class FooProtect implements KeyStore.ProtectionParameter { }
public static class FooParameter implements KeyStore.LoadStoreParameter {
public KeyStore.ProtectionParameter getProtectionParameter() {
return null;
}
}
public static class MyLoadStoreParameter
implements KeyStore.LoadStoreParameter {
private KeyStore.ProtectionParameter protection;
MyLoadStoreParameter(KeyStore.ProtectionParameter protection) {
this.protection = protection;
}
public KeyStore.ProtectionParameter getProtectionParameter() {
return protection;
}
}
public static class FooEntry implements KeyStore.Entry { }
public EntryMethods() throws Exception {
super("EntryMethods", "0.0", "EntryMethods");
pre15fis = new FileInputStream
(System.getProperty("test.src") + "/EntryMethods.pre15.keystore");
put("KeyStore.Pre15KeyStore", "EntryMethods$Pre15");
put("KeyStore.Post15KeyStore", "EntryMethods$Post15");
put("KeyStore.UnrecoverableKeyStore", "EntryMethods$UnrecoverableKS");
}
public static void main(String[] args) throws Exception {
EntryMethods entry = new EntryMethods();
// test pre-JDK1.5 KeyStore throws UnsupportedOperationExceptions
// for new methods
KeyStore pre15KS = KeyStore.getInstance("Pre15KeyStore", entry);
testPre15(pre15KS);
// test post-JDK1.5 KeyStore does right thing with new methods
KeyStore post15KS = KeyStore.getInstance("Post15KeyStore", entry);
testPost15(post15KS);
// test post-JDK1.5 KeyStore can throw new UnrecoverableEntryException
KeyStore uKS = KeyStore.getInstance("UnrecoverableKeyStore", entry);
testUnrecoverable(uKS);
}
private static void testPre15(KeyStore ks) throws Exception {
int tNum = 1;
KeyStore.Entry e = null;
// TEST load null param
ks.load((KeyStore.LoadStoreParameter)null);
System.out.println("[Pre1.5] test " + tNum++ + " passed");
// TEST load random param
try {
ks.load(new FooParameter());
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
} catch (UnsupportedOperationException uoe) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} catch (NoSuchAlgorithmException nsae) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST load custom param
ks.load(new MyLoadStoreParameter(
new KeyStore.PasswordProtection(password)));
System.out.println("[Pre1.5] test " + tNum++ + " passed");
// TEST store random param
ks.load(pre15fis, password);
// setup for later user
KeyStore.Entry pkeNew = ks.getEntry("privkey",
new KeyStore.PasswordProtection(password));
KeyStore.Entry tceNew = ks.getEntry("trustedcert", null);
try {
ks.store(new FooParameter());
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
} catch (UnsupportedOperationException uoe) {
// good
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST store null param
try {
ks.store(null);
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
} catch (UnsupportedOperationException uoe) {
// good
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST getEntry with alias/protParam - use invalid alias
e = ks.getEntry("notPresent",
new KeyStore.PasswordProtection(password));
if (e == null) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected null entry returned");
}
// TEST getEntry with alias/null protParam - get private key
try {
e = ks.getEntry("privkey", null);
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected UnrecoverableEntryException");
} catch (UnrecoverableEntryException uee) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST getEntry with alias/bad password - get private key
try {
e = ks.getEntry("privkey",
new KeyStore.PasswordProtection(badPwd));
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected UnrecoverableEntryException");
} catch (UnrecoverableEntryException uee) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST getEntry with alias/unknown protection - get private key
try {
e = ks.getEntry("privkey", new FooProtect());
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected UnsupportedOperationException");
} catch (UnsupportedOperationException uoe) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST getEntry with alias/protParam - get private key
e = ks.getEntry("privkey", new KeyStore.PasswordProtection(password));
if (e instanceof KeyStore.PrivateKeyEntry) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected PrivateKeyEntry");
}
// TEST getEntry with alias/null protParam - get trusted cert
e = ks.getEntry("trustedcert", null);
if (e instanceof KeyStore.TrustedCertificateEntry) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
}
// TEST getEntry with alias/non-null protParam - get trusted cert
try {
e = ks.getEntry("trustedcert",
new KeyStore.PasswordProtection(password));
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
} catch (UnsupportedOperationException uoe) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST setEntry with alias/entry/protParam - use invalid alias
try {
ks.setEntry("foo", new FooEntry(),
new KeyStore.PasswordProtection(password));
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected KeyStoreException");
} catch (KeyStoreException kse) {
// good
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST setEntry with alias/entry/null protParam - set private key
try {
ks.setEntry("newPrivKey", pkeNew, null);
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected KeyStoreException");
} catch (KeyStoreException kse) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST setEntry with alias/entry/random protParam - set private key
try {
ks.setEntry("newPrivKey", pkeNew, new FooProtect());
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected KeyStoreException");
} catch (KeyStoreException kse) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST setEntry with alias/entry/protParam - set private key
ks.setEntry("newPrivKey", pkeNew,
new KeyStore.PasswordProtection(password));
e = ks.getEntry("newPrivKey",
new KeyStore.PasswordProtection(password));
if (e instanceof KeyStore.PrivateKeyEntry) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected PrivateKeyEntry");
}
// TEST setEntry with alias/entry/non null protParam - set trusted cert
try {
ks.setEntry("newTrustedcert", tceNew,
new KeyStore.PasswordProtection(password));
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected KeyStoreException");
} catch (KeyStoreException kse) {
// good
System.out.println("[Pre1.5] test " + tNum++ + " passed");
}
// TEST setEntry with alias/entry/null protParam - set trusted cert
ks.setEntry("newTrustedcert", tceNew, null);
e = ks.getEntry("newTrustedcert", null);
if (e instanceof KeyStore.TrustedCertificateEntry) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed - " +
"expected TrustedCertificateEntry");
}
// TEST entryInstanceOf - invalid alias
if (ks.entryInstanceOf("foo", EntryMethods.class) == false) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
}
// TEST entryInstanceOf - false case
if (ks.entryInstanceOf("privkey", EntryMethods.class) == false) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
}
// TEST entryInstanceOf - true case, trustedcert entry
if (ks.entryInstanceOf("trustedcert",
KeyStore.TrustedCertificateEntry.class)) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
}
// TEST entryInstanceOf - true case, private key entry
if (ks.entryInstanceOf("privkey",
KeyStore.PrivateKeyEntry.class)) {
System.out.println("[Pre1.5] test " + tNum++ + " passed");
} else {
throw new SecurityException("[Pre1.5] test " + tNum + " failed");
}
}
private static void testPost15(KeyStore ks) throws Exception {
KeyStore.Entry e = null;
ks.load(new EntryMethods.FooParameter());
ks.store(new EntryMethods.FooParameter());
e = ks.getEntry("foo", new KeyStore.PasswordProtection(password));
if (!(e instanceof EntryMethods.FooEntry)) {
throw new SecurityException
("testPost15 getEntry(String, ProtParm) " +
"expected EntryMethods.FooEntry returned");
}
ks.setEntry("foo", new EntryMethods.FooEntry(),
new KeyStore.PasswordProtection(password));
if (!ks.entryInstanceOf("foo", KeyStore.PrivateKeyEntry.class)) {
throw new SecurityException
("testPost15 entryInstanceOf(String, Class) " +
"expected true returned");
}
System.out.println("[Post1.5] tests all passed");
}
private static void testUnrecoverable(KeyStore ks) throws Exception {
ks.load(new EntryMethods.FooParameter());
try {
ks.getEntry("foo", new KeyStore.PasswordProtection(password));
throw new SecurityException
("UnrecoverableEntryException not thrown for " +
"getEntry(String, ProtectionParam)");
} catch (UnrecoverableEntryException uee) {
// good
System.out.println("[UnrecoverableEntry] test passed");
}
}
public static class Pre15 extends KeyStoreSpi {
private static KeyStore jks = getJKS();
private static KeyStore getJKS() {
try {
return (KeyStore) KeyStore.getInstance("JKS");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public Pre15() {
}
public Key engineGetKey(String alias, char[] password)
throws NoSuchAlgorithmException, UnrecoverableKeyException {
try {
return jks.getKey(alias, password);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public java.security.cert.Certificate[] engineGetCertificateChain
(String alias) {
try {
return jks.getCertificateChain(alias);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public java.security.cert.Certificate engineGetCertificate
(String alias) {
try {
return jks.getCertificate(alias);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public Date engineGetCreationDate(String alias) {
try {
return jks.getCreationDate(alias);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public void engineSetKeyEntry(String alias, Key key,
char[] password,
java.security.cert.Certificate[] chain)
throws KeyStoreException {
jks.setKeyEntry(alias, key, password, chain);
}
public void engineSetKeyEntry(String alias, byte[] key,
java.security.cert.Certificate[] chain)
throws KeyStoreException {
jks.setKeyEntry(alias, key, chain);
}
public void engineSetCertificateEntry(String alias,
java.security.cert.Certificate cert)
throws KeyStoreException {
jks.setCertificateEntry(alias, cert);
}
public void engineDeleteEntry(String alias)
throws KeyStoreException {
jks.deleteEntry(alias);
}
public Enumeration engineAliases() {
try {
return jks.aliases();
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public boolean engineContainsAlias(String alias) {
try {
return jks.containsAlias(alias);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public int engineSize() {
try {
return jks.size();
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public boolean engineIsKeyEntry(String alias) {
try {
return jks.isKeyEntry(alias);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public boolean engineIsCertificateEntry(String alias) {
try {
return jks.isCertificateEntry(alias);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public String engineGetCertificateAlias
(java.security.cert.Certificate cert) {
try {
return jks.getCertificateAlias(cert);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public void engineStore(OutputStream stream, char[] password)
throws IOException, NoSuchAlgorithmException, CertificateException {
try {
jks.store(stream, password);
} catch (KeyStoreException ke) {
throw new RuntimeException("Unexpected exception", ke);
}
}
public void engineLoad(InputStream stream, char[] password)
throws IOException, NoSuchAlgorithmException, CertificateException {
jks.load(stream, password);
}
}
public static class Post15 extends Pre15 {
public void engineStore(KeyStore.LoadStoreParameter parameter)
throws IOException, NoSuchAlgorithmException, CertificateException {
if (!(parameter instanceof EntryMethods.FooParameter)) {
throw new IOException("Post15 engineStore method expected " +
"FooParameter");
}
}
public void engineLoad(KeyStore.LoadStoreParameter parameter)
throws IOException, NoSuchAlgorithmException, CertificateException {
if (!(parameter instanceof EntryMethods.FooParameter)) {
throw new IOException("Post15 engineLoadFrom method expected " +
"FooParameter");
}
}
public KeyStore.Entry engineGetEntry(String alias,
KeyStore.ProtectionParameter protectionParam)
throws UnrecoverableEntryException {
if (!alias.equals("foo")) {
throw new SecurityException
("Post15 engineGetEntry(String, ProtectionParam) " +
"expected [foo] alias");
}
KeyStore.PasswordProtection pwdParam =
(KeyStore.PasswordProtection)protectionParam;
if (pwdParam.getPassword().length != 6) {
throw new SecurityException
("Post15 engineGetEntry(String, ProtectionParam) " +
"expected [foobar] password");
}
return new EntryMethods.FooEntry();
}
public void engineSetEntry(String alias, KeyStore.Entry entry,
KeyStore.ProtectionParameter protectionParam) {
if (!alias.equals("foo") ||
!(entry instanceof EntryMethods.FooEntry)) {
throw new SecurityException
("Post15 engineSetEntry(String, entry, ProtParm) " +
"expected [foo] alias and EntryMethods.FooEntry");
}
KeyStore.PasswordProtection pwdParam =
(KeyStore.PasswordProtection)protectionParam;
if (pwdParam.getPassword().length != 6) {
throw new SecurityException
("Post15 engineSetEntry(String, entry, ProtParm) " +
"expected [foobar] password");
}
}
public boolean engineEntryInstanceOf(String alias,
Class<? extends KeyStore.Entry> entryClass)
{
if (!alias.equals("foo") ||
entryClass != KeyStore.PrivateKeyEntry.class) {
throw new SecurityException
("Post15 engineEntryInstanceOf(String, Class) " +
"expected [foo] alias " +
"and [KeyStore.PrivateKeyEntry] class");
}
return true;
}
}
public static class UnrecoverableKS extends Post15 {
public KeyStore.Entry engineGetEntry(String alias,
KeyStore.ProtectionParameter protectionParam)
throws UnrecoverableEntryException {
throw new UnrecoverableEntryException();
}
}
}

View file

@ -0,0 +1,227 @@
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 4938922 4961104 5071293 6236533 8130181
* @summary verify that the KeyStore.Builder API works
* @author Andreas Sterbenz
*/
import java.io.*;
import java.util.*;
import java.security.*;
import java.security.KeyStore.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import javax.security.auth.callback.*;
public class KeyStoreBuilder {
private final static String DIR = System.getProperty("test.src", ".");
private static final char[] password = "passphrase".toCharArray();
private static final char[] wrongPassword = "wrong".toCharArray();
public static void main(String[] args) throws Exception {
File KSFILE = new File(DIR, "keystore.jks");
KeyStore ks;
String alias = "vajra";
Entry entry = null;
Builder builder;
builder = Builder.newInstance("JKS", null, KSFILE, new PasswordProtection(password));
ks = builder.getKeyStore();
System.out.println("-KeyStore: " + ks.size());
entry = ks.getEntry(alias, builder.getProtectionParameter(alias));
showEntry(entry);
builder = Builder.newInstance("JKS", Security.getProvider("Sun"), KSFILE,
new CallbackHandlerProtection(new DummyHandler()));
ks = builder.getKeyStore();
System.out.println("-KeyStore: " + ks.size());
entry = ks.getEntry(alias, builder.getProtectionParameter(alias));
showEntry(entry);
builder = Builder.newInstance("JKS", null, new PasswordProtection(password));
ks = builder.getKeyStore();
int k = ks.size();
System.out.println("-KeyStore: " + k);
if (k != 0) {
throw new Exception("Size not zero: " + k);
}
DummyHandler handler = new DummyHandler();
handler.useWrongPassword = 2;
builder = Builder.newInstance("JKS", null, KSFILE, new CallbackHandlerProtection(handler));
ks = builder.getKeyStore();
System.out.println("-KeyStore: " + ks.size());
entry = ks.getEntry(alias, builder.getProtectionParameter(alias));
showEntry(entry);
handler.useWrongPassword = 3;
builder = Builder.newInstance("JKS", null, KSFILE, new CallbackHandlerProtection(handler));
try {
ks = builder.getKeyStore();
throw new Exception("should not succeed");
} catch (KeyStoreException e) {
System.out.println(e);
}
try {
ks = builder.getKeyStore();
throw new Exception("should not succeed");
} catch (KeyStoreException e) {
System.out.println(e);
}
Provider p = new MyProvider();
handler.useWrongPassword = 2;
builder = Builder.newInstance("My", p, new CallbackHandlerProtection(handler));
ks = builder.getKeyStore();
k = ks.size();
System.out.println("-KeyStore: " + k);
if (k != 0) {
throw new Exception("Size not zero: " + k);
}
handler.useWrongPassword = 3;
builder = Builder.newInstance("My", p, new CallbackHandlerProtection(handler));
try {
ks = builder.getKeyStore();
throw new Exception("should not succeed");
} catch (KeyStoreException e) {
System.out.println(e);
}
try {
ks = builder.getKeyStore();
throw new Exception("should not succeed");
} catch (KeyStoreException e) {
System.out.println(e);
}
System.out.println("-OK");
}
private static void showEntry(Entry entry) {
PrivateKeyEntry pke = (PrivateKeyEntry)entry;
X509Certificate cert = (X509Certificate)pke.getCertificate();
System.out.println("subject: " + cert.getSubjectX500Principal());
}
private static class DummyHandler implements CallbackHandler {
int useWrongPassword;
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
System.out.println("** Callbackhandler invoked");
for (int i = 0; i < callbacks.length; i++) {
Callback cb = callbacks[i];
if (cb instanceof PasswordCallback) {
System.out.println("Found PasswordCallback");
PasswordCallback pcb = (PasswordCallback)cb;
if (useWrongPassword == 0) {
pcb.setPassword(password);
} else {
pcb.setPassword(wrongPassword);
useWrongPassword--;
}
break;
}
}
}
}
private static class BaseKeyStoreSpi extends KeyStoreSpi {
public Key engineGetKey(String alias, char[] password) {
return null;
}
public Certificate[] engineGetCertificateChain(String alias) {
return null;
}
public Certificate engineGetCertificate(String alias) {
return null;
}
public Date engineGetCreationDate(String alias) {
return null;
}
public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] certs) {
//
}
public void engineSetKeyEntry(String alias, byte[] key, Certificate[] certs) {
//
}
public void engineSetCertificateEntry(String alias, Certificate cert) {
//
}
public void engineDeleteEntry(String alias) {
//
}
public Enumeration<String> engineAliases() {
return new Vector<String>().elements();
}
public boolean engineContainsAlias(String alias) {
return false;
}
public int engineSize() {
return 0;
}
public boolean engineIsKeyEntry(String alias) {
return false;
}
public boolean engineIsCertificateEntry(String alias) {
return false;
}
public String engineGetCertificateAlias(Certificate cert) {
return null;
}
public void engineStore(OutputStream stream, char[] password) {
//
}
public void engineLoad(InputStream stream, char[] password) throws IOException {
//
}
}
public static class MyKeyStoreSpi extends BaseKeyStoreSpi {
public void engineLoad(InputStream stream, char[] pw) throws IOException {
if (Arrays.equals(password, pw) == false) {
Throwable t = new UnrecoverableKeyException("Wrong password: " + new String(pw));
throw (IOException)new IOException("load() failed").initCause(t);
}
}
}
private static class MyProvider extends Provider {
MyProvider() {
super("My", "1.0", null);
put("KeyStore.My", "KeyStoreBuilder$MyKeyStoreSpi");
}
}
}

View file

@ -0,0 +1,92 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8245679
* @summary KeyStore cannot probe PKCS12 keystore if BouncyCastle is the top security provider
* @run main/othervm OneProbeOneNot
*/
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.*;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.Enumeration;
public class OneProbeOneNot {
public static final void main(String[] args) throws Exception {
Files.write(Path.of("ks"), "".getBytes());
// 1st provider do not support probe
Security.insertProviderAt(new P1(), 1);
// 2nd provider support probe
Security.insertProviderAt(new P2(), 2);
KeyStore ks = KeyStore.getInstance(new File("ks"), (char[])null);
System.out.println(ks.getProvider().getName());
System.out.println(ks.getType());
}
public static class P1 extends Provider {
public P1() {
super("P1", "P1", "P1");
putService(new Service(this, "KeyStore", "Oops",
K1.class.getName(), null, null));
}
}
public static class P2 extends Provider {
public P2() {
super("P2", "P2", "P2");
putService(new Service(this, "KeyStore", "Oops",
K2.class.getName(), null, null));
}
}
public static class K1 extends KeyStoreSpi {
public Key engineGetKey(String a, char[] p) { return null; }
public Certificate[] engineGetCertificateChain(String a) { return null; }
public Certificate engineGetCertificate(String a) { return null; }
public Date engineGetCreationDate(String a) { return null; }
public void engineSetKeyEntry(String a, Key k, char[] p, Certificate[] c) { }
public void engineSetKeyEntry(String a, byte[] k, Certificate[] c) { }
public void engineSetCertificateEntry(String a, Certificate c) { }
public void engineDeleteEntry(String a) { }
public Enumeration<String> engineAliases() { return null; }
public boolean engineContainsAlias(String a) { return false; }
public int engineSize() { return 0; }
public boolean engineIsKeyEntry(String a) { return false; }
public boolean engineIsCertificateEntry(String a) { return false; }
public String engineGetCertificateAlias(Certificate c) { return null; }
public void engineStore(OutputStream stream, char[] password) { }
public void engineLoad(InputStream stream, char[] password) { }
}
public static class K2 extends K1 {
public boolean engineProbe(InputStream s) {
return true;
}
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006591
* @summary Protect keystore entries using stronger PBE algorithms
*/
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
// Retrieve a keystore entry, protected by the default encryption algorithm.
// Set the keystore entry, protected by a stronger encryption algorithm.
public class PBETest {
private final static String DIR = System.getProperty("test.src", ".");
private final static String KEY_PROTECTION_PROPERTY =
"keystore.PKCS12.keyProtectionAlgorithm";
private static final String[] PBE_ALGOS = {
"PBEWithSHA1AndDESede",
"PBEWithHmacSHA1AndAES_128",
"PBEWithHmacSHA224AndAES_128",
"PBEWithHmacSHA256AndAES_128",
"PBEWithHmacSHA384AndAES_128",
"PBEWithHmacSHA512AndAES_128"
};
private static final char[] PASSWORD = "passphrase".toCharArray();
private static final String KEYSTORE_TYPE = "JKS";
private static final String KEYSTORE = DIR + "/keystore.jks";
private static final String NEW_KEYSTORE_TYPE = "PKCS12";
private static final String ALIAS = "vajra";
private static final byte[] IV = {
0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20
};
private static final byte[] SALT = {
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08
};
private static final int ITERATION_COUNT = 1024;
public static void main(String[] args) throws Exception {
for (String algo : PBE_ALGOS) {
String filename = algo + ".p12";
main0(algo, filename, true);
main0(algo, filename, false);
Security.setProperty(KEY_PROTECTION_PROPERTY, algo);
main0(null, "PBE.p12", false);
Security.setProperty(KEY_PROTECTION_PROPERTY, "");
}
main0(null, "default.p12", false); // default algorithm
}
private static void main0(String algo, String filename, boolean useParams)
throws Exception {
KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
KeyStore.Entry entry =
keystore.getEntry(ALIAS,
new KeyStore.PasswordProtection(PASSWORD));
System.out.println("Retrieved key entry named '" + ALIAS + "'");
Key originalKey = null;
if (entry instanceof KeyStore.PrivateKeyEntry) {
originalKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
} else if (entry instanceof KeyStore.SecretKeyEntry) {
originalKey = ((KeyStore.SecretKeyEntry) entry).getSecretKey();
}
// Set entry
KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null);
if (useParams) {
keystore2.setEntry(ALIAS, entry,
new KeyStore.PasswordProtection(PASSWORD, algo,
new PBEParameterSpec(SALT, ITERATION_COUNT,
new IvParameterSpec(IV))));
System.out.println("Encrypted key entry using: " + algo +
" (with PBE parameters)");
} else if (algo != null) {
keystore2.setEntry(ALIAS, entry,
new KeyStore.PasswordProtection(PASSWORD, algo, null));
System.out.println("Encrypted key entry using: " + algo +
" (without PBE parameters)");
} else {
keystore2.setEntry(ALIAS, entry,
new KeyStore.PasswordProtection(PASSWORD));
String prop = Security.getProperty(KEY_PROTECTION_PROPERTY);
if (prop == null || prop.isEmpty()) {
System.out.println("Encrypted key entry using: " +
"default PKCS12 key protection algorithm");
} else {
System.out.println("Encrypted key entry using: " +
"keyProtectionAlgorithm=" + prop);
}
}
try (FileOutputStream outStream = new FileOutputStream(filename)) {
System.out.println("Storing keystore to: " + filename);
keystore2.store(outStream, PASSWORD);
}
try {
keystore2 = load(NEW_KEYSTORE_TYPE, filename, PASSWORD);
entry = keystore2.getEntry(ALIAS,
new KeyStore.PasswordProtection(PASSWORD));
Key key;
if (entry instanceof KeyStore.PrivateKeyEntry) {
key = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
} else if (entry instanceof KeyStore.SecretKeyEntry) {
key = ((KeyStore.SecretKeyEntry) entry).getSecretKey();
} else {
throw new Exception("Failed to retrieve key entry");
}
if (originalKey.equals(key)) {
System.out.println("Retrieved key entry named '" + ALIAS + "'");
System.out.println();
} else {
throw new Exception(
"Failed: recovered key does not match the original key");
}
} finally {
new File(filename).delete();
}
}
private static KeyStore load(String type, String path, char[] password)
throws Exception {
KeyStore keystore = KeyStore.getInstance(type);
if (path != null) {
try (FileInputStream inStream = new FileInputStream(path)) {
System.out.println("Loading keystore from: " + path);
keystore.load(inStream, password);
System.out.println("Loaded keystore with " + keystore.size() +
" entries");
}
} else {
keystore.load(null, null);
}
return keystore;
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.security.KeyStore;
import java.security.Security;
import static java.lang.System.out;
/**
* @test
* @bug 8048830
* @summary Set up keystore.type secure property and check that
* KeyStore.getDefaultType() value is related to property value. Expect a full
* match the value 'keystore.type' and the value of the
* KeyStore.getDefaultType()
* @run main/othervm CheckDefaults
*/
public class CheckDefaults {
private static final String DEFAULT_KEY_STORE_TYPE = "pkcs12";
private static final String[] KEY_STORE_TYPES = {"jks", "pkcs12", "jceks",
"Unregistered_type_of_KS"};
private void runTest(String[] args) {
if (!KeyStore.getDefaultType().
equalsIgnoreCase(DEFAULT_KEY_STORE_TYPE)) {
throw new RuntimeException(String.format("Default keystore type "
+ "Expected '%s' . Actual: '%s' ", DEFAULT_KEY_STORE_TYPE,
KeyStore.getDefaultType()));
}
for (String ksDefaultType : KEY_STORE_TYPES) {
Security.setProperty("keystore.type", ksDefaultType);
if (!KeyStore.getDefaultType().equals(ksDefaultType)) {
throw new RuntimeException(String.format(
"Keystore default type value: '%s' cannot be set up via"
+ " keystore.type "
+ "security property, Actual: '%s'",
ksDefaultType, KeyStore.getDefaultType()));
}
}
out.println("Test Passed");
}
public static void main(String[] args) {
CheckDefaults checkDefaultsTest = new CheckDefaults();
checkDefaultsTest.runTest(args);
}
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.security.KeyStore;
import static java.lang.System.out;
/**
* @test
* @bug 8304956
* @summary Set keystore.type as null and check that
* KeyStore.getDefaultType() returns pkcs12
* @run main/othervm
* -Djava.security.properties==${test.src}/java.security CheckDefaults
*/
public class CheckNullDefault {
public static void main(String[] args) {
if (!KeyStore.getDefaultType().
equalsIgnoreCase("pkcs12")) {
throw new RuntimeException(String.format("Default keystore type "
+ "Expected '%s' . Actual: '%s' ", "pkcs12",
KeyStore.getDefaultType()));
}
out.println("Test Passed");
}
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import static java.lang.System.out;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Base64;
import java.util.Enumeration;
/*
* @test
* @bug 8048619
* @author Bill Situ
* @summary Test converting keystore from jceks to P12 and from P12 to other
* (jceks,jks). including following test cases:
* Read jceks key store and convert to the p12 key store, then compare entries
* in the two key stores.
* Read p12 key store and convert to the jceks key store, then compare entries
* in the two key stores.
* Read p12 key store (contains only private key and a self-signed certificate)
* and convert to the jceks key store, then compare entries of two key stores.
* Read p12 key store (contains 2 entries) and convert to the jceks key store,
* then compare entries in the two key stores.
* Read p12 key store (entry password and key store password are different) and
* convert to the jceks key store, then compare entries in the two key stores.
* Read p12 key store and convert to the jks key store, then compare entries
* in the two key stores.
* Read p12 key store (contains only private key and a self-signed certificate)
* and convert to the jks key store, then compare entries in the two key stores.
* Read p12 key store (contains 2 entries) and convert to the jks key store,
* then compare entries in the two key stores.
* Read p12 key store (entry password and key store password are different) and
* convert to the jks key store, then compare entries in the two key stores.
*/
public class ConvertP12Test {
private static final String SUN_JSSE = "SunJSSE";
private static final String SUN_JCE = "SunJCE";
private static final String SUN = "SUN";
private static final String PKCS12 = "pkcs12";
private static final String JCE_KS = "JceKS";
private static final String JKS = "JKS";
public static void main(String args[]) throws Exception {
ConvertP12Test jstest = new ConvertP12Test();
jstest.driver("JceksToP12", "keystoreCA.jceks.data", JCE_KS, SUN_JCE,
"storepass", "keypass", PKCS12, SUN_JSSE);
jstest.driver("P12ToJceks_Chain", "ie_jceks_chain.pfx.data", PKCS12,
SUN_JSSE, "pass", "pass", JCE_KS, SUN_JCE);
jstest.driver("P12ToJceks_SelfSigned", "jdk_jceks_selfsigned.p12.data",
PKCS12, SUN_JSSE, "pass", "pass", JCE_KS, SUN_JCE);
jstest.driver("P12ToJceks_TwoEntry", "jdk_jceks_twoentry.p12.data",
PKCS12, SUN_JSSE, "pass", "pass", JCE_KS, SUN_JCE);
jstest.driver("P12ToJceks_TwoPass", "jdk_jceks_twopass.p12.data",
PKCS12, SUN_JSSE, "storepass", "keypass", JCE_KS, SUN_JCE);
jstest.driver("P12ToJks_Chain", "ie_jks_chain.pfx.data", PKCS12,
SUN_JSSE, "pass", "pass", JKS, SUN);
jstest.driver("P12ToJks_SelfSigned", "jdk_jks_selfsigned.p12.data",
PKCS12, SUN_JSSE, "pass", "pass", JKS, SUN);
jstest.driver("P12ToJks_TwoEntry", "jdk_jks_twoentry.p12.data", PKCS12,
SUN_JSSE, "pass", "pass", JKS, SUN);
jstest.driver("P12ToJks_TwoPass", "jdk_jks_twopass.p12.data", PKCS12,
SUN_JSSE, "storepass", "keypass", JKS, SUN);
}
private void driver(String testCase, String inKeyStore,
String inKeyStoreType, String inKeyStoreTypePrv,
String inStorePass, String inKeyPass, String outKeyStoreType,
String outKeyStorePrv) throws Exception {
String outStorePass = "pass";
String outKeyPass = "pass";
KeyStore inputKeyStore, outputKeyStore;
out.println("Testing " + testCase);
String keystorePath = System.getProperty("test.src", ".")
+ File.separator + "certs" + File.separator + "convertP12";
out.println("Output KeyStore : " + inKeyStore + ".out");
String outKeyStoreName = inKeyStore + ".out";
try (FileOutputStream fout = new FileOutputStream(outKeyStoreName);) {
inputKeyStore = KeyStore.getInstance(inKeyStoreType,
inKeyStoreTypePrv);
// KeyStore have encoded by Base64.getMimeEncoder().encode(),need
// decode first.
byte[] input = Files.readAllBytes(Paths.get(keystorePath,
inKeyStore));
ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64
.getMimeDecoder().decode(input));
out.println("Input KeyStore : " + inKeyStore);
inputKeyStore.load(arrayIn, inStorePass.toCharArray());
outputKeyStore = KeyStore.getInstance(outKeyStoreType,
outKeyStorePrv);
outputKeyStore.load(null, null);
run(inputKeyStore, outputKeyStore, inKeyPass, outKeyPass);
outputKeyStore.store(fout, outStorePass.toCharArray());
// for P12ToJks_TwoEntry test case will test includes each other,
// others just test compareKeystore
if (testCase.contains("TwoEntry")) {
compareKeyStore(inputKeyStore, outputKeyStore, inKeyPass,
outKeyPass, 2);
compareKeyStore(outputKeyStore, inputKeyStore, outKeyPass,
inKeyPass, 2);
} else {
compareKeyStore(inputKeyStore, outputKeyStore, inKeyPass,
outKeyPass, 1);
}
out.println("Test " + testCase + " STATUS: Pass!!");
} catch (Exception ex) {
out.println("Test " + testCase + " STATUS: failed with exception: "
+ ex.getMessage());
throw ex;
}
}
private void run(KeyStore inputKeyStore, KeyStore outputKeyStore,
String inKeyPass, String outKeyPass) throws Exception {
Enumeration<String> e = inputKeyStore.aliases();
String alias;
while (e.hasMoreElements()) {
alias = e.nextElement();
Certificate[] certs = inputKeyStore.getCertificateChain(alias);
boolean isCertEntry = inputKeyStore.isCertificateEntry(alias);
// Test KeyStore only contain key pair entries.
if (isCertEntry == true) {
throw new RuntimeException(
"inputKeystore should not be certEntry because test"
+ " keystore only contain key pair entries"
+ " for alias:" + alias);
}
boolean isKeyEntry = inputKeyStore.isKeyEntry(alias);
Key key = null;
if (isKeyEntry) {
key = inputKeyStore.getKey(alias, inKeyPass.toCharArray());
} else {
throw new RuntimeException("Entry type unknown for alias:"
+ alias);
}
outputKeyStore.setKeyEntry(alias, key, outKeyPass.toCharArray(),
certs);
}
}
private void compareKeyStore(KeyStore a, KeyStore b, String inKeyPass,
String outKeyPass, int keyStoreSize) throws Exception {
if (a.size() != keyStoreSize || b.size() != keyStoreSize) {
throw new RuntimeException("size not match or size not equal to "
+ keyStoreSize);
}
Enumeration<String> eA = a.aliases();
while (eA.hasMoreElements()) {
String aliasA = eA.nextElement();
if (!b.containsAlias(aliasA)) {
throw new RuntimeException("alias not match for alias:"
+ aliasA);
}
compareKeyEntry(a, b, inKeyPass, outKeyPass, aliasA);
}
}
private void compareKeyEntry(KeyStore a, KeyStore b, String aPass,
String bPass, String alias) throws KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException {
Certificate[] certsA = a.getCertificateChain(alias);
Certificate[] certsB = b.getCertificateChain(alias);
if (!Arrays.equals(certsA, certsB)) {
throw new RuntimeException("Certs don't match for alias:" + alias);
}
Key keyA = a.getKey(alias, aPass.toCharArray());
Key keyB = b.getKey(alias, bPass.toCharArray());
if (!keyA.equals(keyB)) {
throw new RuntimeException(
"Key don't match for alias:" + alias);
}
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import static java.lang.System.err;
import java.security.*;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.crypto.spec.PBEParameterSpec;
import jdk.test.lib.RandomFactory;
import static java.lang.System.out;
import java.util.Arrays;
/**
* @test
* @bug 8048830
* @summary Test for feature 'support stronger entry protection'. An entry is
* stored to keystore with different PasswordProtection objects which are
* specified by different PBE algorithms (use -Dseed=X to set PRNG seed)
* @library /test/lib ../
* @key randomness
* @build jdk.test.lib.RandomFactory
* @run main EntryProtectionTest
*/
public class EntryProtectionTest {
private static final char[] PASSWORD = "passwd".toCharArray();
private static final String ALIAS = "testkey";
private static final byte[] SALT = new byte[8];
private static final int ITERATION_COUNT = 1024;
private static final List<KeyStore.PasswordProtection> PASSWORD_PROTECTION
= new ArrayList<>();
private static final String KEYSTORE_PATH = System.getProperty(
"test.classes" + File.separator + "ks.pkcs12",
"." + File.separator + "ks.pkcs12");
private void runTest() throws Exception {
KeyStore ksIn = Utils.loadKeyStore(KEYSTORE_PATH,
Utils.KeyStoreType.pkcs12, PASSWORD);
KeyStore ksTest = KeyStore
.getInstance(Utils.KeyStoreType.pkcs12.name());
ksTest.load(null);
Certificate cert = ksIn.getCertificate(ALIAS);
Key key = ksIn.getKey(ALIAS, PASSWORD);
KeyStore.Entry keyStoreEntry = new KeyStore.PrivateKeyEntry(
(PrivateKey) key, new Certificate[]{cert});
for (KeyStore.PasswordProtection passwordAlgorithm :
PASSWORD_PROTECTION) {
out.println("Try to use: " +
passwordAlgorithm.getProtectionAlgorithm());
ksTest.setEntry(ALIAS, keyStoreEntry, passwordAlgorithm);
KeyStore.Entry entryRead = ksTest.getEntry(ALIAS,
new KeyStore.PasswordProtection(PASSWORD));
if (!isPrivateKeyEntriesEqual((KeyStore.PrivateKeyEntry)
keyStoreEntry, (KeyStore.PrivateKeyEntry)entryRead)) {
err.println("Original entry in KeyStore: " + keyStoreEntry);
err.println("Enc/Dec entry : " + entryRead);
throw new RuntimeException(
String.format(
"Decrypted & original enities do "
+ "not match. Algo: %s, Actual: %s, "
+ "Expected: %s",
passwordAlgorithm.getProtectionAlgorithm(),
entryRead, keyStoreEntry));
}
ksTest.deleteEntry(ALIAS);
}
out.println("Test Passed");
}
public static void main(String args[]) throws Exception {
EntryProtectionTest entryProtectionTest = new EntryProtectionTest();
entryProtectionTest.setUp();
entryProtectionTest.runTest();
}
private void setUp() {
out.println("Using KEYSTORE_PATH:"+KEYSTORE_PATH);
Utils.createKeyStore(Utils.KeyStoreType.pkcs12, KEYSTORE_PATH, ALIAS);
Random rand = RandomFactory.getRandom();
rand.nextBytes(SALT);
out.print("Salt: ");
for (byte b : SALT) {
out.format("%02X ", b);
}
out.println("");
PASSWORD_PROTECTION
.add(new KeyStore.PasswordProtection(PASSWORD,
"PBEWithMD5AndDES", new PBEParameterSpec(SALT,
ITERATION_COUNT)));
PASSWORD_PROTECTION.add(new KeyStore.PasswordProtection(PASSWORD,
"PBEWithSHA1AndDESede", null));
PASSWORD_PROTECTION.add(new KeyStore.PasswordProtection(PASSWORD,
"PBEWithSHA1AndRC2_40", null));
PASSWORD_PROTECTION.add(new KeyStore.PasswordProtection(PASSWORD,
"PBEWithSHA1AndRC2_128", null));
PASSWORD_PROTECTION.add(new KeyStore.PasswordProtection(PASSWORD,
"PBEWithSHA1AndRC4_40", null));
PASSWORD_PROTECTION.add(new KeyStore.PasswordProtection(PASSWORD,
"PBEWithSHA1AndRC4_128", null));
}
/**
* Checks whether given two KeyStore.PrivateKeyEntry parameters are equal
* The KeyStore.PrivateKeyEntry fields like {privateKey, certificateChain[]}
* are checked for equality and another field Set<attributes> is not checked
* as default implementation adds few PKCS12 attributes during read
* operation
* @param first
* parameter is of type KeyStore.PrivateKeyEntry
* @param second
* parameter is of type KeyStore.PrivateKeyEntry
* @return boolean
* true when both the KeyStore.PrivateKeyEntry fields are equal
*/
boolean isPrivateKeyEntriesEqual(KeyStore.PrivateKeyEntry first,
KeyStore.PrivateKeyEntry second) {
//compare privateKey
if (!Arrays.equals(first.getPrivateKey().getEncoded(),
second.getPrivateKey().getEncoded())) {
err.println("Mismatch found in privateKey!");
return false;
}
//compare certificateChain[]
if (!Arrays.equals(first.getCertificateChain(),
second.getCertificateChain())) {
err.println("Mismatch found in certificate chain!");
return false;
}
return true;
}
}

View file

@ -0,0 +1,157 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.Base64;
import jdk.test.lib.process.OutputAnalyzer;
import static java.lang.System.out;
import java.nio.file.Paths;
import java.util.List;
/**
* @test
* @bug 8048830
* @summary Test for PKCS12 keystore list , export commands. Refer README for
* keystore files information
* @library ../
* @library /test/lib
* @run main KeytoolReaderP12Test
*/
public class KeytoolReaderP12Test {
private static final String WORKING_DIRECTORY = System.getProperty(
"test.classes", "."+ File.separator);
//private static final String KS_PASSWD = "pass";
private static final String KS_PASSWD = "storepass";
private static final String CERT_CHAIN_PASSWD = "password";
private static final String SOURCE_DIRECTORY =
System.getProperty("test.src", "." + File.separator);
public static void main(String[] args) throws Exception {
List<String> expectedValues = null;
out.println("Self signed test");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"api_private_key.p12_expected.data"));
readTest("api_private_key.p12.data", KS_PASSWD, expectedValues);
out.println("Self signed test Passed");
out.println("private key with selfsigned cert, key pair not match");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"api_private_key_not_match.p12_expected.data"));
readTest("api_private_key_not_match.p12.data", KS_PASSWD,
expectedValues);
out.println("private key with selfsigned cert, key pair "
+ "not match passed");
out.println("cert chain test");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"api_cert_chain.p12_expected.data"));
readTest("api_cert_chain.p12.data", CERT_CHAIN_PASSWD, expectedValues);
out.println("cert chain test passed");
out.println("IE self test");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"ie_self.pfx.pem"));
exportTest("ie_self.pfx.data", "pkcs12testenduser1",
KS_PASSWD, expectedValues);
out.println("IE self test passed");
out.println("IE chain test");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"ie_chain.pfx.pem"));
exportTest("ie_chain.pfx.data", "servercert",
CERT_CHAIN_PASSWD, expectedValues);
out.println("IE chain test passed");
out.println("Netscape self");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"netscape_self.p12.pem"));
exportTest("netscape_self.p12.data", "pkcs12testenduser1",
KS_PASSWD, expectedValues);
out.println("Netscape self passed");
out.println("Mozilla self test");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"mozilla_self.p12.pem"));
exportTest("mozilla_self.p12.data", "pkcs12testenduser1",
KS_PASSWD, expectedValues);
out.println("Mozilla self test passed");
out.println("Openssl test");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"openssl.p12.pem"));
exportTest("openssl.p12.data", "servercert", CERT_CHAIN_PASSWD, expectedValues);
out.println("openssl test passed");
out.println("with different keystore and entrykey password");
expectedValues = Files.readAllLines(Paths.get(SOURCE_DIRECTORY,
"api_two_pass.p12_expected.data"));
readTest("api_two_pass.p12.data", KS_PASSWD,
expectedValues);
out.println("two pass test passed");
}
private static void readTest(String name, String password,
List<String> expectedValues)
throws IOException {
convertToPFX(name);
final String[] command = new String[]{"-debug", "-list", "-v",
"-keystore", WORKING_DIRECTORY + File.separator + name,
"-storetype", "pkcs12", "-storepass", password};
runAndValidate(command, expectedValues);
}
private static void exportTest(String name, String alias,
String password, List<String> expectedValues)
throws IOException {
convertToPFX(name);
final String[] command = new String[]{"-debug", "-export", "-alias",
alias, "-keystore", WORKING_DIRECTORY + File.separator + name,
"-storepass", password, "-storetype", "pkcs12", "-rfc"};
runAndValidate(command, expectedValues);
}
private static void runAndValidate(String[] command,
List<String> expectedValues) throws IOException {
OutputAnalyzer output = Utils.executeKeytoolCommand(command);
if (expectedValues != null) {
expectedValues.stream().forEach(line -> {
output.shouldContain(line);
});
}
}
/**
* Decodes the base64 encoded keystore and writes into new file
* @param name base64 encoded keystore name
*/
private static void convertToPFX(String name) throws IOException{
File base64File = new File(SOURCE_DIRECTORY, name);
File pkcs12File = new File(WORKING_DIRECTORY, name);
byte[] input = Files.readAllBytes(base64File.toPath());
Files.write(pkcs12File.toPath(), Base64.getMimeDecoder().
decode(input), StandardOpenOption.CREATE);
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
import static java.lang.System.out;
/**
* @test
* @bug 8048830
* @summary Tests for creating pkcs12 keystore with various algorithms
* @library ../
* @library /test/lib
* @run main KeytoolWriteP12Test
*/
public class KeytoolWriteP12Test {
private static final String ALIAS = "pkcs12testCA";
private static final Utils.KeyStoreType PKCS12 = Utils.KeyStoreType.pkcs12;
private static final int FAILED_EXIT_CODE = 1;
private static final String CERT_FILE_NAME = "cert.data";
private static final String DNAME = "CN=PKCS12 Test CA, OU=Security SQE, "
+ "O=JavaSoft, C=US";
private static final String WORKING_DIRECTORY = System.
getProperty("test.classes", "." + File.separator);
private enum Algorithm {
DSA, RSA, ECC
};
private void run() {
out.println("Running DSA Test");
keytoolListTest("kt_DSA.p12", Algorithm.DSA);
out.println("DSA Test passed");
out.println("Running RSA Test");
final String rsaKeyStoreName = "kt_RSA_MD5.p12";
keytoolListTest(rsaKeyStoreName, Algorithm.RSA);
out.println("RSA Test passed");
out.println("Running RSA and Signing Algorithm SHA1withRSA Test");
keytoolListTest("kt_RSA_SHA1.p12", Algorithm.RSA,
"-sigalg", "SHA1withRSA");
out.println("RSA and Signing Algorithm SHA1withRSA Test Passed");
out.println("Running Keysize 256 Test");
keytoolListNegativeTest("kt_DSA_256.p12", Algorithm.DSA, "-keysize",
"256");
out.println("Keysize 256 Test Passed");
out.println("Running Keysize 1023 Test");
keytoolListTest("kt_RSA_MD5_1023.p12", Algorithm.RSA, "-keysize",
"1023");
out.println("Keysize 1023 Test Passed");
out.println("Running Export certificate Test");
exportTest(rsaKeyStoreName);
out.println("Export certificate Test Passed");
}
private void exportTest(String keyStore) {
final String keyStoreName = WORKING_DIRECTORY + File.separator
+ keyStore;
deleteKeyStoreFile(keyStoreName);
Utils.createKeyStore(DNAME, PKCS12, keyStore, ALIAS,
Algorithm.RSA.name());
final String certFilePath = WORKING_DIRECTORY + File.separator
+ CERT_FILE_NAME;
Utils.exportCert(PKCS12, keyStore,
ALIAS, certFilePath);
final String[] command = new String[]{"-debug", "-printcert", "-v",
"-file", certFilePath};
Utils.executeKeytoolCommand(command);
}
private void keytoolListTest(String keyStore, Algorithm algorithm,
String ...optionalArgs) {
final String keyStoreName = WORKING_DIRECTORY + File.separator
+ keyStore;
final String[] command = new String[]{"-debug", "-list", "-v", "-alias",
ALIAS, "-keystore", keyStoreName, "-storetype", "pkcs12",
"-storepass", Utils.DEFAULT_PASSWD};
deleteKeyStoreFile(keyStoreName);
Utils.createKeyStore(DNAME, PKCS12, keyStoreName, ALIAS,
algorithm.name(), optionalArgs);
OutputAnalyzer output = Utils.executeKeytoolCommand(command);
output.shouldContain(DNAME);
}
private void keytoolListNegativeTest(String keyStore, Algorithm algorithm,
String... optionalArgs) {
final String keyStoreName = WORKING_DIRECTORY + File.separator
+ keyStore;
deleteKeyStoreFile(keyStoreName);
Utils.createKeyStore(DNAME, PKCS12, keyStoreName, ALIAS,
algorithm.name(), optionalArgs, FAILED_EXIT_CODE);
}
public static void main(String[] args) {
KeytoolWriteP12Test test = new KeytoolWriteP12Test();
test.run();
out.println("Test Passed");
}
private void deleteKeyStoreFile(String fileName) {
File file = new File(fileName);
if (file.exists()) {
file.delete();
}
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.io.IOException;
import java.security.cert.CertificateException;
import static java.lang.System.out;
/**
* @test
* @bug 8048830
* @summary Entry's attribute set should be empty
* @library ../
* @library /test/lib
* @run main MetadataEmptyTest
*/
public class MetadataEmptyTest {
private static final char[] PASSWORD = "passwd".toCharArray();
private static final String ALIAS = "testkey";
private static final String KEYSTORE_PATH = System.getProperty(
"test.classes" + File.separator + "ks.pkcs12",
"." + File.separator + "ks.pkcs12");
private void runTest() throws IOException, KeyStoreException,
NoSuchAlgorithmException, CertificateException,
UnrecoverableKeyException {
KeyStore ks = Utils.loadKeyStore(KEYSTORE_PATH,
Utils.KeyStoreType.pkcs12, PASSWORD);
Key key = ks.getKey(ALIAS, PASSWORD);
Certificate cert = ks
.getCertificate(ALIAS);
KeyStore.Entry entry = new KeyStore.PrivateKeyEntry(
(PrivateKey) key,
new Certificate[]{cert});
if (!entry.getAttributes().isEmpty()) {
throw new RuntimeException("Entry's attributes set "
+ "must be empty");
}
out.println("Test Passed");
}
public static void main(String[] args) throws Exception{
MetadataEmptyTest test = new MetadataEmptyTest();
test.setUp();
test.runTest();
}
private void setUp() {
Utils.createKeyStore(Utils.KeyStoreType.pkcs12, KEYSTORE_PATH, ALIAS);
}
}

View file

@ -0,0 +1,147 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PKCS12Attribute;
import java.security.PrivateKey;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Set;
import static java.lang.System.out;
import java.util.HashSet;
/**
* @test
* @bug 8048830
* @summary Test store metadata attributes to PKCS12 keystore.
* @library ../
* @library /test/lib
* @run main MetadataStoreLoadTest
*/
public class MetadataStoreLoadTest {
private static final char[] PASSWORD = "passwd".toCharArray();
private static final char[] KEY_PASSWORD = "keypasswd".toCharArray();
private static final String ALIAS = "testkey_metadata";
private static final String KEYSTORE = "ks.pkcs12";
private static final String KESTORE_NEW = "ks-attr.pkcs12";
private static final int MAX_HUGE_SIZE = 2000000;
private static final String WORKING_DIRECTORY = System.getProperty(
"test.classes", "." + File.separator);
private static final String KEYSTORE_PATH = WORKING_DIRECTORY
+ File.separator + KEYSTORE;
private static KeyStore.Entry.Attribute[] ATTR_SET;
private void runTest() throws GeneralSecurityException,
UnrecoverableEntryException, NoSuchAlgorithmException,
KeyStoreException, IOException {
storeAttrs();
checkAttrs();
}
private void storeAttrs() throws UnrecoverableEntryException,
GeneralSecurityException, NoSuchAlgorithmException,
KeyStoreException, IOException {
KeyStore ksIn = Utils.loadKeyStore(KEYSTORE_PATH,
Utils.KeyStoreType.pkcs12, PASSWORD);
KeyStore ksAttr = KeyStore
.getInstance(Utils.KeyStoreType.pkcs12.name());
ksAttr.load(null);
Key key = ksIn.getKey(ALIAS, PASSWORD);
Certificate cert = ksIn.getCertificate(ALIAS);
Set<KeyStore.Entry.Attribute> attrs =
new HashSet<>(Arrays.asList(ATTR_SET));
KeyStore.Entry e = new KeyStore.PrivateKeyEntry((PrivateKey) key,
new Certificate[]{cert}, attrs);
ksAttr.setEntry(ALIAS, e, new KeyStore.PasswordProtection(
KEY_PASSWORD));
out.println("Attributes before store:");
e.getAttributes().stream().forEach((attr) -> {
out.println(attr.getName() + ", '" + attr.getValue() + "'");
});
Utils.saveKeyStore(ksAttr, WORKING_DIRECTORY + File.separator
+ KESTORE_NEW, PASSWORD);
}
private void checkAttrs() throws UnrecoverableEntryException,
GeneralSecurityException, NoSuchAlgorithmException,
KeyStoreException, IOException {
KeyStore ks = Utils.loadKeyStore(WORKING_DIRECTORY
+ File.separator
+ KESTORE_NEW, Utils.KeyStoreType.pkcs12, PASSWORD);
KeyStore.Entry keyStoreEntry = ks.getEntry(ALIAS,
new KeyStore.PasswordProtection(KEY_PASSWORD));
out.println("Attributes after store:");
//print attribute values
keyStoreEntry.getAttributes().stream().forEach((attr) -> {
out.println(attr.getName() + ", '" + attr.getValue() + "'");
});
Arrays.stream(ATTR_SET).forEach((attr) -> {
if (!keyStoreEntry.getAttributes().contains(attr)) {
throw new RuntimeException("Entry doesn't contain attribute: ("
+ attr.getName() + ", '" + attr.getValue() + "')");
}
});
}
public static void main(String[] args) throws Exception {
MetadataStoreLoadTest test = new MetadataStoreLoadTest();
test.setUp();
test.runTest();
out.println("Test Passed");
}
private void setUp() {
Utils.createKeyStore(Utils.KeyStoreType.pkcs12, KEYSTORE_PATH, ALIAS);
final String allCharsString = "`1234567890-=qwertyuiop[]asdfghjkl;'\\zx"
+ "cvbnm,./!@#$%^&*()_+QWERTYUIOP{}ASDFGHJKL:|>ZXCVBNM<>?\"";
StringBuilder sbPrintable = new StringBuilder();
while (sbPrintable.length() < MAX_HUGE_SIZE) {
sbPrintable.append(allCharsString);
}
final String hugePrintable = sbPrintable.toString();
final String binaryString = "00:11:22:33:44:55:66:77:88:99:AA:BB:DD:"
+ "EE:FF:";
StringBuilder sbBinary = new StringBuilder();
sbBinary.append(binaryString);
while (sbBinary.length() < MAX_HUGE_SIZE) {
sbBinary.append(":").append(binaryString);
}
sbBinary.insert(0, "[").append("]");
final String hugeBinary = sbBinary.toString();
ATTR_SET = new PKCS12Attribute[5];
ATTR_SET[0] = new PKCS12Attribute("1.2.840.113549.1.9.1",
"Test email addres attr <test@oracle.com>");
ATTR_SET[1] = new PKCS12Attribute("1.2.110.1", "not registered attr");
ATTR_SET[2] = new PKCS12Attribute("1.2.110.2", hugePrintable);
ATTR_SET[3] = new PKCS12Attribute("1.2.110.3", hugeBinary);
ATTR_SET[4] = new PKCS12Attribute("1.2.110.2", " ");
}
}

View file

@ -0,0 +1,28 @@
The test KeytoolReaderP12Test.java depends on keystore data files and validates
with output generated by keystore list/export commands
KeyStore File storetype aliasname keyalg SignatureAlgorithm
------ ------ ------ ------ ---
api_private_key.p12.data pkcs12 pkcs12testenduser1 RSA 1024 MD5withRSA
api_private_key_not_match.p12.data pkcs12 pkcs12testca RSA 2048 SHA1withRSA
api_cert_chain.p12.data pkcs12 pkcs12testenduser1 RSA 1024 MD5withRSA
api_two_pass.p12.data pkcs12 pkcs12testca RSA 2048 SHA1withRSA
netscape_self.p12.data pkcs12 pkcs12testenduser1 RSA 1023 MD5withRSA
mozilla_self.p12.data pkcs12 pkcs12testenduser1 RSA 1023 MD5withRSA
ie_self.pfx.data pkcs12 a3aa3db3-3ec2-4d8b-8cf1-4d3c54afe386 RSA 1023 MD5withRSA
ie_chain.pfx.data pkcs12 4e3053da-ff8e-46d2-b6d1-c38e431dea1f RSA 1023 MD5withRSA
Following keystore commands were used
1. Generate keystore and along with keypair
<JAVA-HOME>/bin/keytool -genkey -v -alias pkcs12test -keyalg "RSA" -keysize 2048
-sigalg "SHA1withRSA" -dname "cn=PKCS12 Test CA, ou=Security SQE, o=JavaSoft,
c=US" -validity 7300 -keypass storepass -keystore ks-pkcs.data -storepass
storepass -storetype pkcs12
2. Export certificate
<JAVA-HOME>/bin/keytool -export -alias pkcs12test -keystore ks-pkcs.data
-storetype pkcs12 -storepass storepass -file pkcs12testCA.cer.data
3. Import certificate
<JAVA-HOME>/bin/keytool -import -alias pkcs12test -keystore ks-pkcs.data
-storepass storepass -file pkcs12testCA.cer.data

View file

@ -0,0 +1,191 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import static java.lang.System.out;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Enumeration;
/*
* @test
* @bug 8048617
* @author Bill Situ
* @summary Read different types p12 key store to Check the read related APIs.
* including following test cases:
* ReadP12_IE_Chain: Read p12 key store (contains private key and associated
* certificate chain) from IE.
* ReadP12_IE_Self: Read p12 key store (contains only private key and
* self-signed certificate) from IE.
* ReadP12_JDK_Chain: Read p12 key store (contains private key and associated
* certificate chain) from JDK
* ReadP12_JDK_Self: Read p12 key store (contains only private key and
* self-signed certificate) from JDK.
* ReadP12_Mozilla_Self: Read p12 key store (contains only private key and
* self-signed certificate) from Mozilla.
* ReadP12_Mozilla_Chain: Read p12 key store (contains private key and
* associated certificate chain) from Mozilla.
* ReadP12_Mozilla_TwoEntries: Read p12 key store (contains 2 entries) from
* Mozilla.
* ReadP12_Netscape_Chain: Read p12 key store (contains private key and
* associated certificate chain) from Netscape.
* ReadP12_Netscape_Self: Read p12 key store (contains only private key and
* self-signed certificate) from Netscape.
* ReadP12_Netscape_TwoEntries: Read p12 key store (contains 2 entries) from
* Netscape.
* ReadP12_OpenSSL: Read p12 key store from OpenSSL.
*/
public class ReadP12Test {
private final static String IN_KEYSTORE_TYPE = "pkcs12";
private final static String IN_STORE_PASS = "pass";
public static void main(String args[]) throws Exception {
ReadP12Test jstest = new ReadP12Test();
String testCase = "";
try {
testCase = "ReadP12_IE_Chain";
jstest.readTest("ie_chain.pfx.data");
testCase = "ReadP12_IE_Self";
jstest.readTest("ie_self.pfx.data");
testCase = "ReadP12_JDK_Chain";
jstest.readTest("jdk_chain.p12.data");
testCase = "ReadP12_JDK_Self";
jstest.readTest("jdk_self.p12.data");
testCase = "ReadP12_Mozilla_Chain";
jstest.readTest("mozilla_chain.p12.data");
testCase = "ReadP12_Mozilla_Self";
jstest.readTest("mozilla_self.p12.data");
testCase = "ReadP12_Mozilla_TwoEntries";
jstest.readTest("mozilla_twoentries.p12.data");
testCase = "ReadP12_Netscape_Chain";
jstest.readTest("netscape_chain.p12.data");
testCase = "ReadP12_Netscape_Self";
jstest.readTest("netscape_self.p12.data");
testCase = "ReadP12_Netscape_TwoEntries";
jstest.readTest("netscape_twoentries.p12.data");
testCase = "ReadP12_openssl";
jstest.readTest("openssl.p12.data");
} catch (Exception e) {
System.err.println(testCase + ": failed with execption: "
+ e.getMessage());
throw e;
}
out.println(testCase + ": Pass!!");
}
private void readTest(String inKeyStore) throws Exception {
KeyStore inputKeyStore;
// Initialize KeyStore
String dir = System.getProperty("test.src", ".");
String keystorePath = dir + File.separator + "certs" + File.separator
+ "readP12";
inputKeyStore = KeyStore.getInstance(IN_KEYSTORE_TYPE);
// KeyStore have encoded by Base64.getMimeEncoder().encode(),need decode
// first.
byte[] input = Files.readAllBytes(Paths.get(keystorePath, inKeyStore));
ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64
.getMimeDecoder().decode(input));
inputKeyStore.load(arrayIn, IN_STORE_PASS.toCharArray());
out.println("Initialize KeyStore : " + inKeyStore + " success");
out.println("getProvider : " + inputKeyStore.getProvider());
out.println("getType : " + inputKeyStore.getType());
out.println("getDefaultType : " + KeyStore.getDefaultType());
int idx = 0;
Enumeration<String> e = inputKeyStore.aliases();
String alias;
while (e.hasMoreElements()) {
alias = e.nextElement();
out.println("Alias " + idx + " : " + alias);
if (inputKeyStore.containsAlias(alias) == false) {
throw new RuntimeException("Alias not found");
}
out.println("getCreationDate : "
+ inputKeyStore.getCreationDate(alias));
X509Certificate cert = (X509Certificate) inputKeyStore
.getCertificate(alias);
out.println("getCertificate : " + cert.getSubjectDN());
String retAlias = inputKeyStore.getCertificateAlias(cert);
if (!retAlias.equals(alias)) {
throw new RuntimeException("Alias mismatch");
}
out.println("getCertificateAlias : " + retAlias);
Certificate[] certs = inputKeyStore.getCertificateChain(alias);
for (int i = 0; i < certs.length; i++) {
out.println("getCertificateChain " + i + " : "
+ ((X509Certificate) certs[i]).getSubjectDN());
}
boolean isCertEntry = inputKeyStore.isCertificateEntry(alias);
// test KeyStore only contain key pair entries.
if (isCertEntry == true) {
throw new RuntimeException(
"inputKeystore should not be certEntry because test keystore only contain key pair entries.");
}
boolean isKeyEntry = inputKeyStore.isKeyEntry(alias);
if (isKeyEntry) {
Key key = inputKeyStore.getKey(alias,
IN_STORE_PASS.toCharArray());
out.println("Key : " + key.toString());
} else {
throw new RuntimeException("Entry type unknown\n");
}
idx++;
}
int size = inputKeyStore.size();
if (idx != size) {
throw new RuntimeException("Size not match");
}
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import static java.lang.System.err;
import static java.lang.System.out;
/**
* @test
* @bug 8048830
* @summary Test imports certificate from file to PKCS12 keystore store it as
* trusted certificate Check import errors (must be not errors) & check keystore
* content after import
* @library ../
* @library /test/lib
* @run main StoreTrustedCertAPITest
*/
public class StoreTrustedCertAPITest {
private static final char[] PASSWORD = "passwd".toCharArray();
private static final String ALIAS = "testkey_stcapi";
private static final String WORKING_DIRECTORY = System.getProperty(
"test.classes", "." + File.separator);
private static final String CERT_PATH = WORKING_DIRECTORY + File.separator
+ "cert.data";
private static final String KEYSTORE_PATH = WORKING_DIRECTORY
+ File.separator + "ks.pkcs12";
/**
* Test logic (environment has set up)
*/
private void runTest() throws FileNotFoundException, CertificateException,
KeyStoreException, IOException, NoSuchAlgorithmException {
Certificate cert;
CertificateFactory cf;
try (FileInputStream fi = new FileInputStream(CERT_PATH)) {
cf = CertificateFactory.getInstance("X.509");
cert = cf.generateCertificate(fi);
KeyStore ks = KeyStore.getInstance(
Utils.KeyStoreType.pkcs12.name());
ks.load(null, null);
ks.setCertificateEntry(ALIAS, cert);
Utils.saveKeyStore(ks, KEYSTORE_PATH, PASSWORD);
ks = Utils.loadKeyStore(KEYSTORE_PATH, Utils.KeyStoreType.pkcs12,
PASSWORD);
final Certificate ksCert = ks.getCertificate(ALIAS);
if (!ksCert.equals(cert)) {
err.println("Orig cert: " + cert.toString());
err.println("Cert from keystore: " + ksCert.toString());
throw new RuntimeException("Certificates don't match");
}
}
}
public static void main(String[] args) throws Exception {
StoreTrustedCertAPITest test = new StoreTrustedCertAPITest();
test.setUp();
test.runTest();
out.println("Test Passed");
}
private void setUp() {
Utils.createKeyStore(Utils.KeyStoreType.pkcs12, KEYSTORE_PATH, ALIAS);
Utils.exportCert(Utils.KeyStoreType.pkcs12, KEYSTORE_PATH,
ALIAS, CERT_PATH);
new File(KEYSTORE_PATH).delete();
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import jdk.test.lib.process.OutputAnalyzer;
import static java.lang.System.out;
/**
* @test
* @bug 8048830
* @summary Tests keytool command imports certificate , list keystore, print
* certificate and import password help.
* @library ../
* @library /test/lib
* @run main StoreTrustedCertKeytool
*/
public class StoreTrustedCertKeytool {
private static final String PASSWORD = "passwd";
private static final String ALIAS = "testkey_stckey";
private static final String FILE_SEPARATOR = File.separator;
private static final String WORKING_DIRECTORY = System.getProperty(
"test.classes", "." + FILE_SEPARATOR);
private static final String CERT_PATH = WORKING_DIRECTORY
+ FILE_SEPARATOR
+ "cert.data";
private static final String KEYSTORE_PATH = WORKING_DIRECTORY
+ FILE_SEPARATOR + "ks.pkcs12";
protected void run() throws IOException, KeyStoreException,
NoSuchAlgorithmException, CertificateException {
setUp();
importCert();
out.println("Import Cert test passed");
listCerts();
out.println("listCerts test passed");
printCert();
out.println("print cert test passed");
helpImportPassword();
out.println("help import test passed");
}
private void importCert() {
final String[] command = new String[]{"-debug", "-importcert",
"-alias", ALIAS, "-file", CERT_PATH, "-noprompt", "-keystore",
KEYSTORE_PATH, "-storetype", "pkcs12", "-storepass", PASSWORD};
// If the keystore exists delete it.
File keystoreFile = new File(KEYSTORE_PATH);
if (keystoreFile.exists()) {
keystoreFile.delete();
}
Utils.executeKeytoolCommand(command);
}
private void listCerts() throws IOException, KeyStoreException,
NoSuchAlgorithmException, CertificateException {
final String[] command = new String[]{"-debug", "-list", "-v",
"-alias", ALIAS, "-keystore", KEYSTORE_PATH, "-storetype", "pkcs12",
"-storepass", PASSWORD};
OutputAnalyzer output = Utils.executeKeytoolCommand(command);
if (output == null) {
throw new RuntimeException("Keystore print fails");
}
X509Certificate ksCert = null;
final KeyStore ks = Utils.loadKeyStore(KEYSTORE_PATH,
Utils.KeyStoreType.pkcs12, PASSWORD.toCharArray());
ksCert = (X509Certificate) ks.getCertificate(ALIAS);
if (ksCert == null) {
throw new RuntimeException("Certificate " + ALIAS
+ " not found in Keystore " + KEYSTORE_PATH);
}
String serialNumber = ksCert.getSerialNumber().toString(16);
output.shouldContain(serialNumber);
}
private void printCert() {
final String[] command = new String[]{"-debug", "-printcert",
"-file", CERT_PATH};
Utils.executeKeytoolCommand(command);
}
private void helpImportPassword() {
final String[] command = new String[]{"-debug", "-help",
"-importpassword"};
Utils.executeKeytoolCommand(command);
}
public static void main(String[] args) throws Exception {
final StoreTrustedCertKeytool test = new StoreTrustedCertKeytool();
test.run();
out.println("Test Passed");
}
private void setUp() {
Utils.createKeyStore(Utils.KeyStoreType.pkcs12, KEYSTORE_PATH, ALIAS);
Utils.exportCert(Utils.KeyStoreType.pkcs12, KEYSTORE_PATH, ALIAS,
CERT_PATH);
new File(KEYSTORE_PATH).delete();
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8278744
* @summary KeyStore:getAttributes() not returning unmodifiable Set
* @library /test/lib
*/
import jdk.test.lib.SecurityTools;
import jdk.test.lib.Utils;
import java.io.File;
import java.security.KeyStore;
public class UnmodifiableAttributes {
public static final void main(String[] args) throws Exception {
var oneAttr = new KeyStore.Entry.Attribute() {
@Override
public String getName() {
return "1.2.3";
}
@Override
public String getValue() {
return "testVal";
}
};
char[] pass = "changeit".toCharArray();
SecurityTools.keytool("-keystore ks -storepass changeit -genkeypair -alias a -dname CN=A -keyalg EC")
.shouldHaveExitValue(0);
KeyStore ks = KeyStore.getInstance(new File("ks"), pass);
var attrs = ks.getAttributes("a");
Utils.runAndCheckException(() -> attrs.add(oneAttr), UnsupportedOperationException.class);
var attrs2 = ks.getEntry("a", new KeyStore.PasswordProtection(pass)).getAttributes();
Utils.runAndCheckException(() -> attrs2.add(oneAttr), UnsupportedOperationException.class);
}
}

View file

@ -0,0 +1,138 @@
/*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.List;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import static java.lang.System.out;
import java.util.ArrayList;
/**
* Helper class for creating keystore and executing keytool commands
*/
public class Utils {
public enum KeyStoreType {
jks, pkcs12;
}
public static final String DEFAULT_DNAME
= "CN=TestKey, T=FuncTestCertKey, O=Oracle, OU=JDKSQE, C=US";
public static final String DEFAULT_PASSWD = "passwd";
public static final String RSA = "rsa";
public static final String JAVA_HOME = System.getProperty("java.home");
public static final String KEYTOOL = "keytool";
private static final int SUCCESS_EXIT_CODE = 0;
public static OutputAnalyzer executeKeytoolCommand(String[] command) {
return executeKeytoolCommand(command, SUCCESS_EXIT_CODE);
}
public static OutputAnalyzer executeKeytoolCommand(String[] command,
int exitCode) {
String[] keytoolCmd = new String[command.length + 3];
OutputAnalyzer output = null;
try {
keytoolCmd[0] = JDKToolFinder.getJDKTool(KEYTOOL);
// Ensure the keytool process is always ran under English locale
keytoolCmd[1] = "-J-Duser.language=en";
keytoolCmd[2] = "-J-Duser.country=US";
System.arraycopy(command, 0, keytoolCmd, 3, command.length);
output = ProcessTools.executeCommand(keytoolCmd);
output.shouldHaveExitValue(exitCode);
out.println("Executed keytool command sucessfully:"
+ Arrays.toString(keytoolCmd));
} catch (Throwable e) {
e.printStackTrace(System.err);
throw new RuntimeException("Keytool Command execution failed : "
+ Arrays.toString(keytoolCmd), e);
}
return output;
}
public static void createKeyStore(KeyStoreType type, String name,
String alias) {
createKeyStore(DEFAULT_DNAME, type, name, alias, RSA);
}
public static void createKeyStore(String dName, KeyStoreType type,
String name, String alias, String algorithm,
String... optionalArgs) {
createKeyStore(dName, type, name, alias, algorithm, optionalArgs,
SUCCESS_EXIT_CODE);
}
public static void createKeyStore(String dName, KeyStoreType type,
String name, String alias, String algorithm,
String[] optionalArgs, int exitCode) {
String[] command = new String[]{"-debug", "-genkeypair", "-alias",
alias, "-keystore", name, "-dname", dName, "-storepass",
DEFAULT_PASSWD, "-keypass", DEFAULT_PASSWD, "-validity", "7300",
"-keyalg", algorithm, "-storetype", type.name()};
if (optionalArgs != null && optionalArgs.length > 0) {
List<String> commandArgs = new ArrayList<>(Arrays.asList(command));
List<String> temp = Arrays.asList(optionalArgs);
commandArgs.addAll(temp);
if (!commandArgs.contains(("-keysize"))) {
commandArgs.add("-keysize");
commandArgs.add("1024");
}
command = commandArgs.toArray(new String[commandArgs.size()]);
}
executeKeytoolCommand(command, exitCode);
}
public static void exportCert(KeyStoreType type, String name,
String alias, String cert) {
String[] command = {"-debug", "-exportcert", "-keystore", name,
"-storetype", type.name(), "-storepass", DEFAULT_PASSWD, "-alias",
alias,"-file",cert,"-noprompt"};
executeKeytoolCommand(command);
}
public static KeyStore loadKeyStore(String file, KeyStoreType type,
char[] passwd)
throws IOException, KeyStoreException,
NoSuchAlgorithmException, CertificateException {
KeyStore ks = KeyStore.getInstance(type.name());
try (FileInputStream fin = new FileInputStream(file)) {
ks.load(fin, passwd);
}
return ks;
}
public static void saveKeyStore(KeyStore ks, String file, char[] passwd)
throws IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException {
try (FileOutputStream fout = new FileOutputStream(file)) {
ks.store(fout, passwd);
}
}
}

View file

@ -0,0 +1,364 @@
/*
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import static java.lang.System.out;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Base64;
import java.util.Enumeration;
/*
* @test
* @bug 8048618
* @summary Write different types p12 key store to Check the write related
* APIs.
* @run main WriteP12Test
* @enablePreview
*/
public class WriteP12Test {
private static final String IN_KEYSTORE_TYPE = "jks";
private static final String IN_KEYSTORE_PRV = "SUN";
private static final String IN_KEYSTORE_ENDUSER = "keystoreEU.jks.data";
private static final String IN_KEYSTORE_CA = "keystoreCA.jks.data";
private static final String OUT_KEYSTORE = "outKeyStore.p12";
private static final String IN_STORE_PASS = "storepass";
private static final String IN_KEY_PASS = "keypass";
private static final String CERT_PATH = System.getProperty("test.src", ".")
+ File.separator + "certs" + File.separator + "writeP12"
+ File.separator;
private static final String CA_CERT_STR = "-----BEGIN CERTIFICATE-----\n"
+ "MIIDFzCCAf8CBD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCV\n"
+ "VMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUU\n"
+ "UxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAwNTUxMlo\n"
+ "XDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEph\n"
+ "dmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ\n"
+ "1MxMiBUZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ\n"
+ "EAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG00yi9aL\n"
+ "SsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7I\n"
+ "wRTYYy9clFkeeK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4e\n"
+ "f1mUASo6+dea0UZA/FHCuV7O6z3hr5VHlyhJL2/o/8M5tGBTBISODJSnn\n"
+ "GNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1XnIkiiXR3\n"
+ "tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0\n"
+ "dQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhx\n"
+ "i18YQc2LPWBDLYTTxoFEazWmYLv1k/JT7Nta1qu1quvxXJ4uV1XHbd9NF\n"
+ "AJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhqvO03G0Q\n"
+ "imhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Yb\n"
+ "k5qe3lviMZPkkSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUr\n"
+ "sVOVWh7IBCqC/V7FqUTkmD1IFlzkkinatpl42s1MbhJId2yQkzaeBRc\n"
+ "suE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di\n"
+ "-----END CERTIFICATE-----";
private static final String LEAD_CERT = "-----BEGIN CERTIFICATE-----\n"
+ "MIICwDCCAaigAwIBAgIEPz7S1jANBgkqhkiG9w0BAQQFADBQMQswCQYDV\n"
+ "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n"
+ "R5IFNRRTEXMBUGA1UEAxMOUEtDUzEyIFRlc3QgQ0EwHhcNMDAwODA5MDc\n"
+ "wMDAwWhcNMTAwODA3MDcwMDAwWjBSMQswCQYDVQQGEwJVUzERMA8GA1UE\n"
+ "ChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaXR5IFNRRTEZMBcGA1UEA\n"
+ "xMQUEtDUzEyIFRlc3QgTGVhZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgY\n"
+ "kCgYEAzq9X2USz/WjDhT+jUyZWqB5h4A33tS11YqH5qYvqjTXjcUI6gOp\n"
+ "moXMafDG9RHRlIccvp51xLp7Ap3WMrv411lWBttqtZi5c1/DEC1cEM/Sl\n"
+ "PCk1r2zFbkJu7QKieXeMcrjZEo6LcBHMwQjIpI+up9cr3VjuyqG/olQkU\n"
+ "mXVuS0CAwEAAaMkMCIwDwYDVR0PAQH/BAUDAweAADAPBgNVHRMBAf8EBT\n"
+ "ADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBhbuim98TWmtv9vSldRE7RvQ8\n"
+ "FlS0TyZVO7kcSNtfCUE4R76J1ElN74Koc5pQnUtduLeQJs2ao/mEcCZsE\n"
+ "zVcwI3mSZrSzPhc8s7w5gOQA4TUwVLSSjKgBCaZ7R3+qJ3QeqPJ5O6sFz\n"
+ "pvBYkgSa4MWptK41jbmT8cwZQJXFCi8WxFFJ+p97F1Ppm3LgmYmtiUP4M\n"
+ "ZQwOBvpTZWXU0WrqFXpzWQx0mg4SX19fZm4nLcJAerCEUphf8ILagtpQM\n"
+ "EErT3/jg6mfCdT3Rj055QXPfF4OiRFevPF5a1fZgrCePCukRQZcd7s8K5\n"
+ "OBIaryuM0MdFtlzxi6XWeUNpVFFHURcy\n"
+ "-----END CERTIFICATE-----";
private static final String END_CERT = "-----BEGIN CERTIFICATE-----\n"
+ "MIICNjCCAZ+gAwIBAgIEPz7WtzANBgkqhkiG9w0BAQQFADBSMQswCQYDV\n"
+ "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n"
+ "R5IFNRRTEZMBcGA1UEAxMQUEtDUzEyIFRlc3QgTGVhZDAeFw0wMDA4MDk\n"
+ "wNzAwMDBaFw0xMDA4MDcwNzAwMDBaMFgxCzAJBgNVBAYTAlVTMREwDwYD\n"
+ "VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMR8wHQYDV\n"
+ "QQDExZQS0NTMTIgVGVzdCBFbmQgVXNlciAxMIGfMA0GCSqGSIb3DQEBAQ\n"
+ "UAA4GNADCBiQKBgQDIKomSYomDzH/V63eDQEG7od0DLcnnVZ81pbWhDss\n"
+ "8gHV2m8pADdRqdihBmnSQEaMW4D3uZ4sFE1LtkQls6hjd7SdOsG5Y24L8\n"
+ "15jot9a2JcB73H8H0VKirrObL5BZdt7BtASPDnYtW4Spt++YjDoJFxyF0\n"
+ "HchkavzXaVTlexakwIDAQABoxMwETAPBgNVHQ8BAf8EBQMDB4AAMA0GCS\n"
+ "qGSIb3DQEBBAUAA4GBAIFA3JXEmb9AXn3RD7t+Mn6DoyVDIy5jsn6xOKT\n"
+ "JV25I0obpDUzgw4QaAMmM0ZvusOmZ2wZNS8MtyTUgdANyakbzn5SdxbTy\n"
+ "TLEqQsFbX8UVC38fx5ZM6ExA5YSAvgmXudZpOVC0ATccoZS3JFU8CxSfW\n"
+ "+Q3IC2MLh+QTg3hUJ5b\n-----END CERTIFICATE-----";
private final Certificate testerCert;
private final Certificate testLeadCert;
private final Certificate caCert;
WriteP12Test() {
PEMDecoder pemDecoder = PEMDecoder.of();
caCert = pemDecoder.decode(CA_CERT_STR, X509Certificate.class);
testLeadCert = pemDecoder.decode(LEAD_CERT, X509Certificate.class);
testerCert = pemDecoder.decode(END_CERT, X509Certificate.class);
}
public static void main(String[] args) throws UnrecoverableKeyException,
KeyStoreException, NoSuchProviderException,
NoSuchAlgorithmException, IOException, CertificateException {
WriteP12Test jstest = new WriteP12Test();
out.println("test WriteP12CertChain");
/*
* WriteP12CertChain: This test creates a p12 keystore contains one
* entry with private key and a certificate chains contains three
* certificates in the order of user->lead->ca. This case expects to
* pass.
*/
jstest.test(new Certificate[] { jstest.testerCert, jstest.testLeadCert,
jstest.caCert }, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1",
"pass", "pass");
/*
* WriteP12CertChainBad: same as WriteP12CertChain but chains order is
* user-ca-lead, the order is wrong so expects to fail.
*/
out.println("test WriteP12CertChainBad");
try {
jstest.test(new Certificate[] { jstest.testerCert, jstest.caCert,
jstest.testLeadCert }, IN_KEYSTORE_ENDUSER,
"pkcs12testenduser1", "pass", "pass");
throw new RuntimeException(
" Certificate chain is not valid, test should not pass."
+ " Test failed.");
} catch (KeyStoreException e) {
e.printStackTrace();
out.println(" Certificate chain is not valid,exception is"
+ " expected. Test passed.");
}
/*
* WriteP12PrivateKey:This test creates a p12 contains a self-signed
* cert and private key,expects no exception
*/
out.println("test WriteP12PrivateKey");
jstest.test(null, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", "pass",
"pass");
/*
* WriteP12TwoEntry: This test creates a p12 keystore with different
* storepass and keypass, and contains two entries.
*/
out.println("test WriteP12TwoEntry");
jstest.testTwoEntry(IN_KEYSTORE_ENDUSER, IN_KEYSTORE_CA,
"pkcs12testenduser1", "pass", "pass");
/*
* WriteP12TwoPass: This test creates a p12 keystore with different
* storepass and keypass, and contains one entry with private key and a
* certificate
*/
out.println("test WriteP12TwoPass");
jstest.test(null, IN_KEYSTORE_CA, "pkcs12testCA", "storepass",
"keypass");
}
private void test(Certificate certs[], String inKeyStorePath,
String userAlias, String outStorePass, String outKeyPass)
throws KeyStoreException, NoSuchProviderException, IOException,
CertificateException, UnrecoverableKeyException,
NoSuchAlgorithmException {
// init output key store
KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE");
outputKeyStore.load(null, null);
try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE)) {
// KeyStore have encoded by Base64.getMimeEncoder().encode(),need
// decode first.
byte[] input = Files.readAllBytes(Paths.get(CERT_PATH,
inKeyStorePath));
ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64
.getMimeDecoder().decode(input));
// input key store
KeyStore inputKeyStore = KeyStore.getInstance(IN_KEYSTORE_TYPE,
IN_KEYSTORE_PRV);
inputKeyStore.load(arrayIn, IN_STORE_PASS.toCharArray());
// add key/certificate to output key store
Key key = inputKeyStore
.getKey(userAlias, IN_KEY_PASS.toCharArray());
out.println("Input Key Algorithm " + key.getAlgorithm());
out.println("====Input Certs=====");
if (certs == null) {
certs = new Certificate[] { inputKeyStore
.getCertificate(userAlias) };
}
for (Certificate cert : certs) {
out.println(((X509Certificate) cert).getSubjectDN());
}
outputKeyStore.setKeyEntry(userAlias, key,
outKeyPass.toCharArray(), certs);
Certificate retCerts[] = outputKeyStore
.getCertificateChain(userAlias);
out.println("====Output Certs=====");
for (Certificate retCert : retCerts) {
out.println(((X509Certificate) retCert).getSubjectDN());
}
out.println("====Output Key Algorithm=====");
Key outKey = outputKeyStore.getKey(userAlias,
outKeyPass.toCharArray());
out.println(outKey.getAlgorithm());
if (!key.equals(outKey)) {
throw new RuntimeException("key don't match");
}
if (!Arrays.equals(certs, retCerts)) {
throw new RuntimeException("certs don't match");
}
// save output
outputKeyStore.store(fout, outStorePass.toCharArray());
// test output
testKeyStore(outputKeyStore, outKeyPass.toCharArray());
}
}
private void testTwoEntry(String inKeyStoreOnePath,
String inKeyStoreTwoPath, String userAlias, String outStorePass,
String outKeyPass) throws KeyStoreException,
NoSuchProviderException, NoSuchAlgorithmException,
CertificateException, IOException, UnrecoverableKeyException {
// initial KeyStore
KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE");
try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE);) {
outputKeyStore.load(null, null);
KeyStore inputKeyStoreOne, inputKeyStoreTwo;
inputKeyStoreOne = KeyStore.getInstance(IN_KEYSTORE_TYPE,
IN_KEYSTORE_PRV);
// KeyStore have encoded by Base64.getMimeEncoder().encode(),need
// decode first.
byte[] inputBytes = Files.readAllBytes(Paths.get(CERT_PATH,
inKeyStoreOnePath));
ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64
.getMimeDecoder().decode(inputBytes));
// input key store
inputKeyStoreOne.load(arrayIn, IN_STORE_PASS.toCharArray());
inputBytes = Files.readAllBytes(Paths.get(CERT_PATH,
inKeyStoreTwoPath));
arrayIn = new ByteArrayInputStream(Base64.getMimeDecoder().decode(
inputBytes));
inputKeyStoreTwo = KeyStore.getInstance(IN_KEYSTORE_TYPE,
IN_KEYSTORE_PRV);
inputKeyStoreTwo.load(arrayIn, IN_STORE_PASS.toCharArray());
// add key/certificate to output key store
out.println("====First Entry=====");
Key inputKey = inputKeyStoreOne.getKey(userAlias,
IN_KEY_PASS.toCharArray());
Certificate cert = inputKeyStoreOne.getCertificate(userAlias);
Certificate certs[] = new Certificate[1];
certs[0] = cert;
out.println("====Input1 Key=====");
out.println(inputKey.getAlgorithm());
out.println("====Input1 Certs=====");
out.println("Certificate :");
out.println(((X509Certificate) cert).getSubjectDN());
outputKeyStore.setKeyEntry("USER", inputKey,
outKeyPass.toCharArray(), certs);
out.println("====Second Entry=====");
String caAlias = "pkcs12testca";
inputKey = inputKeyStoreTwo.getKey(caAlias,
IN_KEY_PASS.toCharArray());
cert = inputKeyStoreTwo.getCertificate(caAlias);
certs[0] = cert;
out.println("====Input2 Key=====");
out.println(inputKey.getAlgorithm());
out.println("====Input2 Certs=====");
out.println("Certificate :");
out.println(((X509Certificate) cert).getSubjectDN());
outputKeyStore.setKeyEntry("CA", inputKey,
outKeyPass.toCharArray(), certs);
// save output
outputKeyStore.store(fout, outStorePass.toCharArray());
// test output
testKeyStore(outputKeyStore, outKeyPass.toCharArray());
}
}
private void testKeyStore(KeyStore inputKeyStore, char[] keypass)
throws KeyStoreException, UnrecoverableKeyException,
NoSuchAlgorithmException {
out.println("========== Key Store ==========");
out.println("getProvider : " + inputKeyStore.getProvider());
out.println("getType : " + inputKeyStore.getType());
out.println("getDefaultType : " + KeyStore.getDefaultType());
int idx = 0;
Enumeration<String> e = inputKeyStore.aliases();
String alias;
while (e.hasMoreElements()) {
alias = e.nextElement();
if (!inputKeyStore.containsAlias(alias)) {
throw new RuntimeException("Alias not found");
}
out.println("Alias " + idx + " : " + alias);
out.println("getCreationDate : "
+ inputKeyStore.getCreationDate(alias));
X509Certificate cert = (X509Certificate) inputKeyStore
.getCertificate(alias);
out.println("getCertificate : " + cert.getSubjectDN());
String retAlias = inputKeyStore.getCertificateAlias(cert);
if (!retAlias.equals(alias)) {
throw new RuntimeException("Alias mismatch, actually "
+ retAlias + ", expected " + alias);
}
out.println("getCertificateAlias : " + retAlias);
Certificate[] certs = inputKeyStore.getCertificateChain(alias);
int i = 0;
for (Certificate certification : certs) {
out.println("getCertificateChain " + i
+ ((X509Certificate) certification).getSubjectDN());
i++;
}
if (inputKeyStore.isCertificateEntry(alias)) {
throw new RuntimeException(
"inputKeystore should not be certEntry because this"
+ " keystore only contain key pair entries.");
}
if (!inputKeyStore.isKeyEntry(alias)) {
throw new RuntimeException("Entry type unknown.");
}
idx++;
}
int size = inputKeyStore.size();
if (idx != size) {
throw new RuntimeException("Size not match, actually " + idx
+ ", expected " + size);
}
}
}

View file

@ -0,0 +1,76 @@
MIIQ6AIBAzCCEKIGCSqGSIb3DQEHAaCCEJMEghCPMIIQizCCBXAGCSqGSIb3DQEHAaCCBWEEggVd
MIIFWTCCBVUGCyqGSIb3DQEMCgECoIIE+jCCBPYwKAYKKoZIhvcNAQwBAzAaBBSKdWqt6IsXyQA9
6SNtYnk7vaT/CQICBAAEggTIv5XR91OsI7r831ltprYhtOfAhl3TFKj+cqnohJF1xm60K5dQN5BZ
enfVw4YPbCTR16+zTiGyHJ/MFELwOrOogPdSQBTuy1PtUZOfskD/EKFQaCVSQ1omNlgOWqVh0dhF
TMjw6KLaTfhwx2Qw3aLIjhy7rvS5SEsUbGZ/IvJ7ym+DHzFuP8oQFfISUkNxh7wOqk4BSsY1Yh9H
JbK7Y7JtWReDTbAtuACQSPO0Z7RSWKC2y29cG6x3gIiB8iKTNrPKc6m0wb48RKipzF6r35GQRMoS
rsordIc22RS/KYFfU4W9LAdV+/vJBuZazc+3MgcOXYUWDaMpAG697aim1yDjudcVnPoUdzdWQvAj
Z7dHqeplZ8h4Ur+dKH3EeWoipXBXhVI0i9hFbOU+36OZ96LUjlRfaAI3NXVMEa9+kATwDHh9cqnQ
1zkbVPCXBY6Y6+wnq5o0mpES++MCc8zELiFYZOJl6UWBE/D16QAv+6Qd/JHmRaZfNt+vNxKm1ltm
nvdyWcO4FlF9F5cC66AS3NcdZ94GNkRBW964+yaUCFHCeVGSfwxqox++akNOyfrw9lP8a24usPLj
ScueTLGCftprwUGLb9g/zRhPWBHrYELbUplER+KQeWnX84OqyAZXNnBUFhrH8CBJAPDIVCpZj7ti
Z23eQoplPpL+z/CYKqx1BTk+E82+Z3cXXRhgiguXHqJhf8mR+3ZGsNsS0r23AnHQGJVvh09wbb02
o1fAJpOkw34GGoLwqstakkO1/nKO2ln2g7UTdkzcGp9GCrhbxAmZ0jXjPy5RFG1m4yEhjAJ/lnRm
3bwCb3z1mBjtrRO9hnb4iQBzwpvctHlVzAUh77JTbUzsu7TxrranUq2+Z1MWjqsymoPjDxct0GK0
WrWV5iwVTIB73CW7IcKbAKVxsus9kRjbLaLxkfio6HGiYz2e+30CJX8sB5DPLBjfAZQiWMkq0k3T
SfAKPRSlX7okdrXpfON57naUPw6biIcbDQovH7sMDSP58VLiGI7CNUuj5rhGu9O6Jhc6n5/krhjI
W7xUkXZmZPq2yww1OSSD3LF4K7Uu6ukZMQU5NfUOVeeAkq+4RMns/nZdQd3JhP0CyuF4vLrEWq8n
6WD+Sta3ZvCxbLPs9xylnlqevmq0zUhxbY7gzObEMGH1YpZT/nSjHpAbt0bcwFIiFncCC0t9/d07
REJjWvG7J0GB9cNb4aNbE05fCx0tlipyNu2GASwT8fw0tPXrcdaHxL+1+/fDdLlsnrODN+Hvx2GC
oixNMf1NSC1M0evf/8tqPDwwUBcKdFumILwEeWHwOP7Tx3/2eRfSPP3e6iGDYv0KrzHzWV2uyoXj
bTwfRHs4W+71v91dtrKH8Q+IRKxkiSKdT0KnpDkGlnFwK88TAZso6L1agTshdtjvwNAJ/yaIN1S7
FBBKcM2/rc3SJwNTmjsHrX3C8VvenO6rAxBvn151pzMjCY9eijJwnUKHEB8V3wSP+eSM/INL1swA
BPIJba5Jg5Zhch4SpV8B5rjxAz+qkiLlGOxbsPeyfv3jzINZhkBqRtBA3gLxJjPgfPlu2s3U+HBa
iHm0/K6VlSztjs4Ez30tfgym6vbWv/rrRXNfUqWumNqC5LXyDbVy7MarS5iKMUgwIwYJKoZIhvcN
AQkUMRYeFABzAGUAcgB2AGUAcgBjAGUAcgB0MCEGCSqGSIb3DQEJFTEUBBJUaW1lIDE0MzI2OTE3
MzM4NTgwggsTBgkqhkiG9w0BBwagggsEMIILAAIBADCCCvkGCSqGSIb3DQEHATAoBgoqhkiG9w0B
DAEGMBoEFMrHJAy5G2zs/2U91Kv84axmE50HAgIEAICCCsDf0VQQ5aHERkv1me9S5cr3KQ73vg0h
gawyFpFcMRGhzwMggy460MuwHIJk9aQ9rlvGi7FNWsPdBrwpJzyU6LFHUl5w/L94hjULrHeSaJ3T
oltDs8jMK+I7Bx3B96kc5GvYzOlaq3OtRbITPs47a4qA7/TTAJxYC5pgTXiulu4lZ/scaHnBQc2N
wX6ZFSKMz38lzEllA+ndnhgLNrL7yozrVFslFu0XrDcZC8ga4tm59rn/Dzmyz+hPcK+JKv7nq5gt
MTGOGwtmaWUh/kSKPNETWVasa7UDlYexSwSadNlDSxWCHXEXb3YXOVvLDbnVB8OmWChBlw78vz/9
UmeTpaCvH3SbgulOzW1TgsV4R7oTkib/Ck2R1XBPOssDg56VSeRrsd1pVy1GKxUsD/T5tih7wK1I
IiLPrAh488GELpPadKjsv/990OSbv0q72V4kJWXn6m9RsQVGaOV2QiEjQPWSCq0FEglD8ikpg44X
HpdCf5hL87iY1z0zONG8OP0IMEEJn091wfegCJZu5XsvT9PFaBm4mjMol1Hr1ZT/w6Qzfc/AmKn2
serI/uAzOoMWGOEtzpof8M+DFD1saMCRG9Lf4A6fkub2968ZMbiSsdIu2YJefcOMWtmcW277l1Pz
EjNlLXV40bfv/0tnBlbD2dYfGS2iCi4eMsWEWbV2kBq9gie24+NsDSlGXZjd7x9F0D7xUKGlXnR/
4NzEilOURjEvxJloqd88K4xM1ZUELm/OYZwIkOmDZdqR1/8Wh82TYW5Mq4NKUbfltTOcvLE0fM5N
VGyio8qGEVzgLWOGnh7V73QMBidu3cTWKf/OYYp13ywF0CxsGRVZmskFa3uH0C2pAoWnx13Plmo8
lLtDFtxQ+u9ZBn8dZDGDD4gY2YSYj08/5MBWZQ5EWVLwn9A6xNGQMhFUuFhjmKCuulScaJ6v9aW4
QBg5SfWzfuYD1G922wx7/TtQFBVR4NIKxTOroIjSpI+lYriNDa3c1UYRa+DY8suC90Wz90sbR37T
QGOenU/QCSavPIiVijQzQbXz4eEMhddIwoCHTtkn4NgUO+pn4zMl9jCrwwMCSG1t2DZ1L6y67q4Q
UnI0mU/O8cqglykl5Rz9G2TraHMv5SMGyHgi/jKyfGfAZriopPHWsXXNs85okMoM8j3YCFsM7EJ9
l4We6J4euWK9WM7YboiSgKltJGXUgTU0l2HYN17ihF3sY3PaBiLdrNARM9blkzAhdhx0Q3NNFn3N
7g0PniTkvW07aZoemdN/yric2grhC5P3rkuaw0j/AwTDC68ReJbOmdn7Gmv+4RSIXN9DIM/JV0Dd
Xn06zLhnl9mim5hLtB1+f0E4oSz1MOOh1qoajm/lpr4o7zyHjb3v8mKrTMXvYO4PiQZ5HKWgvbB3
iMCvdn859bv5X5ckz2SVtpnTjYTemICmEPRk7hRb/DZJkMptlhG2uFIq1ZUSDwVMGrrnRkEwlyLT
f7wU5C2KoNGVgGhF9W6w/RBzYyTFVrsCTxpR9M9Jy875JnCmOBYUQLoDno+4qR00a70R2AdG7c3q
gCZQBLzKqEp+gu0YUPGZzda1i8RhSF6c0w2A7ToynDf9gTbKSsyV1iblTm1UhjG/lXtU/9rzOMth
7ZCrvd1EZGbmn2SP+CsQzoGMh9T0j+FygWx1u/yYO0kRXCjcyzOVq+p+XraDwxiI+GNcqNkrVKUW
kIJO6ajXZg0cNekZyhiR3vLdY5EOBVWahvTnWFrEPpNt6tavVHyQ+AJP5t3VLq16AkBGgICYAdnG
zKUgim96I0xNd37EKTmIlBccpNc0uVLgGEzuQiONBBcZPUwD6y4EvJnLmEaOdgRYjcaO8aeuIX/U
VEC4zQEXI99ghQ7TWuNNOwyR+kyKQQsER5GRct9fzv6qMk0Xei914IdbL7DAy2pSfyaYNNlk339H
/ji5lQPG1y8qQAw6sDtQPt0LcHg3bMX5Q/r1/LmlpML7rOUz1QwVH7QdHrHWjGvC1kjrmGtZjB7j
XwQMItY3n/J1/vBfeuSk3sgWeHBYxgmnIjhqMVEoTSTUyelfrOte9N+5fomUWqnujl6rmqHl62oO
695wUiKq6BVpXQtJEhqauQYAQ+DoGn3Klbmd5iHaqG5PU68wtEQPtSvXG6RPtteUi/H2jpnaG/Z+
6HVQejCGJrZ4h1C/afq7WnCg5ZM8dy9zE02+CtqTq1hEiXF5mF6rhpKgxJZLlWk8wq0zP47ahnI+
0VyAljgH5CW5BOwGrZdV8LHPbk+gVhqqBYIw/05HACbO4K32rEEUuvK+DSYQ0wxY8ufa1QttqQnv
YRQ3XU+M4reL3pDJwPg+3LGP7jcIEqUY+trGeWbhASAETsLUURYuIkAydPKkEvb1rFPJGfiuMAVi
PhSSTvDSrV8FZR9NNTr7zeHAbbJWArKi0hcv67noStYzBQT++SuiD5stp9Ym4DCE6/sAIR7Sa/1Y
rhViLtpHp06WzkXi5lSVBCpJjaWKznmQp580gyAjjOx3mRqkEwx440yJq0LfqTdF8jiV2IZhjiT3
MjdanLQOlldjGL64SpIKCQ0FzQcnB+sNbTtkYSRR9x4ImNYFGQpQtXimbAJAlaS5R4bOLbOygO/C
mUDjpo1NkTIyAe/YzALpbCyJqaEOPm5Yp+1C6EQfb+DUxv2MyUWNuKw0xvFWhy4TuCCsrzIfQLYi
2UxpILq8zr8ZhPUGv6KnN4j+jTo92A3DvtBbTLdRLf1n6hfAhWAOBmGu7c8N0kmfNcDJuWtvsG08
1+xqLNni149FrNDzMjLwMg2YwaHJuwdKZsMcRtEfmGi2uAsTthsq6MxMHZPBFqNaNwrcaN7+PEK1
c21PW/X6+kATvCRpKJxlChyZE5yEanvsIwpFB9IRmyEZIyYnCIcFl08Mbaw9jGdlxg32VdjIdQTY
LVQ/8NOQGuz8RJepxoBQQ4dveiWJTPeEY879EC+3U8NgA84O3YZKfNxE4uSbjeGKu4tvVp5DoByW
H7ZZWKAScltteuKFpP4ME6gGwvgF122HNzfrwztjcooIGfsxRvRSNerbAVjyZbBy3jC/3m3pOmqy
kJfzhbVqEesBRCJKaCXVHZRSoziSqlwtMgbU+tPYGMERJT727cIFFKhqLILybZbc6LKI/SV852TD
JXQ420HZX76GTSEWURDsu8glvYuGVosvBdg/63lVf8z15vJiaFbJEQDR7dHAquTAsynB2PVUErhJ
sNz4kuQRbRoD6vS07fM2avNTLouZUX3bpwugyumgl2H0lvxLWXnXelFHnIc7NzdEqx6oS1YZBgq3
7U21OG5t9hA02eZZT+LrcAWH1NUV2fFWps60WHKdCKcIN7w/vy/D8dDr1jdOppdubN35oR5ZOwob
HYjk/KepGNTDeH8el2SX9yhjj5a0aTtMTdy/DvpAN7u9Xaq0bRH1lZZyE0n4F1MysND8sWwQPTH8
uJoD4msqelGrx81lThyhwwk/8+2AWGG0sU9l0sK4xMmeMCPtdGdg9C4g5m08mHoa/etbOj+7spqf
MG4Gq1hLOygsHwFRRQe3eRi4BSoE7HvgdyP84qVnLnc4g0RDLhFdDgyBLGTYRqpCX8iZA4Nf4uRJ
pteB+CANzKjx9HqxBO/jGtOwFBg0eSXBU4d4CI6MoAS4NxUjlqhIGEKJBwJ78jPsCq2JMD0wITAJ
BgUrDgMCGgUABBTxMWXHZ4F5ADtYXqKlpD5cMihu7wQUsiXIcUR/3TChw09nR5rrIaFsN+MCAgQA

View file

@ -0,0 +1,7 @@
SHA1: 09:F1:08:B1:B3:28:22:23:22:F7:5F:6D:4A:8D:0E:0A:5E:6D:56:FB
SHA256: AD:57:47:67:20:96:49:86:53:E4:10:EF:BD:4D:D2:B0:81:C0:B0:BB:62:AE:BE:47:80:DC:00:F8:E3:E7:66:B5
SHA1: 2B:CE:0C:E1:35:B9:9D:FE:5A:6E:25:88:01:F7:E9:E5:7B:89:17:42
SHA256: 65:F3:0A:64:F2:52:B2:4E:F8:76:C5:D0:6D:53:7C:E8:00:AE:F4:95:3C:CC:CB:01:6B:22:AF:46:36:50:CF:FF
SHA1: 7D:48:4D:1C:F8:55:E8:79:6A:B0:19:E1:26:4F:AC:FD:57:6B:38:A0
SHA256: 0A:14:3F:88:8D:C2:D6:97:3E:02:0F:5F:17:E3:D9:FE:CF:93:10:2C:3C:8D:81:AC:06:2F:32:39:4D:0E:CB:6A
Alias name: servercert

View file

@ -0,0 +1,31 @@
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

View file

@ -0,0 +1,3 @@
SHA1: 48:22:E2:C2:47:9F:75:E3:52:56:9C:20:37:DF:03:7F:CD:9F:87:38
SHA256: 9B:DF:B9:EC:DB:3E:EF:BD:61:8F:C3:62:BD:3E:95:FE:E5:B6:A3:F9:94:3D:8D:C1:AE:E9:44:86:25:FA:C1:1B
Alias name: pkcs12testenduser1

View file

@ -0,0 +1,21 @@
MIIEpAIBAzCCBF4GCSqGSIb3DQEHAaCCBE8EggRLMIIERzCCBEMGCSqGSIb3DQEHBqCCBDQwggQw
AgEAMIIEKQYJKoZIhvcNAQcBMCgGCiqGSIb3DQEMAQYwGgQUgIXKrki/1oMI4cCRpYWa/iQtL0cC
AgQAgIID8L1nh0C0Gmm9/AbAYbiwBJeb5oCAHa5E6BXJO9DP+m7774lUoQFuAmHJRoqr9hRzJulD
FfdkmRO9JdCs1tRgmnik66ybBb2wqr9gsAhPHFhDWuYIQTJcYqYlBTS8hbg5stDYWCeyaqK3+Zyp
bV3nHZtCe0AO+Rd3derZ3qhluPhc2FWX05fIomTZNiJsbi5wp95ejH4tGX5OdQoWXBjDzlrxopUd
pmdmHfJvRRTEtMr45VPfuHOkAX8Fe2tPFUgkE2tUalUth90AuPXVlMm5Ne+OdKcj+V2EN2s5JxA6
28H1IL753Hov3R80/+Rzn+NIN/BCwLfHyTFa4Ur7Z2dyOJHvM5qeaz580RR8MwsEjqSpmXiyVhQW
3LNuziqs21woC7ueDW7TLiLhHp2Mt8BqFyfUYqBoS29lchRTHZbWTN2h66xycXlzbUCGIOHDXPXB
mqgxQWIltgluel+9Uf//D5yzIkXbtnW9dkMwKkybctAUs9VN8V44UBxv4+noSxepUs0iG+07c5Uu
dfvzwYtnKqKUrtTT8tA/MBNd4P1paYJR2Angx5tInyNKp8TwOaSrFUfg9stMYMh2fbWHLJFS9RDz
P7BDkrBgEO7jDu3O/XyyXzgUQRcQBv/Mw7sCFQ8BBMFzwf/dc6q277w+DJmwz2ex23iXQXQi/b6Y
iHbPwYHVwURWpVAq3P36pCTYjnUpPHMgRKo/9Iy+tL39H46SyGqBFlriM4jDEu7dbi7n1MuMxRYD
zocSkdsnlsJUBOhHLFFYIUIqx6jOgnOESKPWbG9XIHCTZJYnpasmP/VidrQMljzC7c3piePsI03D
8NcJq+BqCRrX+7Z5vPAU022hMryQqHesgnx0T0dWXaCyabzjjjOaWvacxRRCiJ4+EFZqAahMNQp/
XTNlpW1eI0oQ3YBlJl5FWuwhk6YuoNSoi8ya1wp42rFnTwXIG8enfa0wyx/ORAvfypW4wcohsCdP
oRjc9foQsdcjxv2e1yMn9TlgjTOemY81mFfaSMa+4OIhSgLnIYI96QztrY9n8WHJer1hxVdKrb+8
Mhf2vcNEToVF9ypst1C7fXSeOKdAYlNDskPAAm3prcuLMf1dzceIADr+4JOYxzdz6lLvjR+tpAHo
zWO1xh73P+p+Bo82wxnoWCopqOUCEoAYhsy+JBGZNM4AHvPAo4g0Sett3qixZhvbmw9kzKsiFAjf
wQHYPUfl0O02HvBizHK7dRDqJ94G/djGBhqfe34P0hKrCzW+n0u5nFmkFEdk50LpsTu0z3AaaaNh
E6485FDeW3R3/67pGXglNJHBWPsl2AYFimUTzxQqOfoCzBiw9St7hNvuCJBv5jA9MCEwCQYFKw4D
AhoFAAQUczIrgX5A0QTP7tpYDiY3MaSbEM8EFAprSM643ml+k9DGSQKZ7MG0UEhKAgIEAA==

View file

@ -0,0 +1,3 @@
SHA1: 2B:CE:0C:E1:35:B9:9D:FE:5A:6E:25:88:01:F7:E9:E5:7B:89:17:42
SHA256: 65:F3:0A:64:F2:52:B2:4E:F8:76:C5:D0:6D:53:7C:E8:00:AE:F4:95:3C:CC:CB:01:6B:22:AF:46:36:50:CF:FF
Alias name: pkcs12testenduser1

View file

@ -0,0 +1,46 @@
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
+FjQ0fq7d/D+Ilu6e2EBG1y/ngICBAA=

View file

@ -0,0 +1,3 @@
SHA1: 77:90:EC:65:C5:0C:FD:F2:1E:B0:3A:BD:43:21:1A:C6:FD:18:8C:AB
SHA256: 8E:C8:49:82:B8:4B:89:8E:61:2D:CD:F6:D6:34:96:04:91:6F:1B:08:F5:CD:BD:23:ED:94:22:5A:B4:7A:39:DD
Alias name: pkcs12testenduser1

View file

@ -0,0 +1,61 @@
MIINXgIBAzCCDRoGCSqGSIb3DQEHAaCCDQsEgg0HMIINAzCCA7wGCSqGSIb3DQEHAaCCA60EggOp
MIIDpTCCA6EGCyqGSIb3DQEMCgECoIICtjCCArIwHAYKKoZIhvcNAQwBAzAOBAipOP0AVsizDgIC
B9AEggKQIP/YI9/C2WYbIWxKuqXMD8WPCvqj1fhHmZJ0epCzgEdOR7GT/h2Fy4/wxrthPkj4JqkS
akQog3pjOFtj9D8QtkOw/b761qsyj17TYlQS9C6qVhcddMA+Ca2NcDhKlYofQMNTuYPXkXlpCh5R
CNFgQ+PLVZwNZjqoitjv0RLQqBudhTmJSvfDlW2w+CpbziEeRNzn0pX0/Ts7KxykDscOmUCGHKic
b6FqHoioElcmBp7ae3zdXuvI1x/1Y435qju2yODPpMXEZbdsD5iL07RZyL2vm6lfQbLc37TszDBx
ZZJ7ja5F4V/j/6/AVLkcqfZxFOnXz5Ki9rQblYJbkkTpJAyiNqi8Gx+zgPGtLWvV6KRD0zmxo6q/
OmdjKz4v9aG7MDSXenoy6tPAOvAQcQYaksvFZs1FjorJJpFzasfTUfy94JzrHUzRSPzNRDANHG/6
TgxC1FMNw+iQUY9L8j4xrWsr2JN5tAgYcWz1qZrp4cx0he9cbQeqYcjv7ZvIQbIe2zxdvxh7WByy
r8hNMe3RkMOM2yuP85JuWipq+9jt4/CrimKljN1ULPw+V9FZzY8kKcEiSPD+KXdJNkrMr77/lUJz
PGNYpFBFb4natmi31ZBH2VomTeKPpeanN/ghWojft1mGd1s1nD4NelrWATMVquH2Cq6nhKLRHi4c
KbQsMo+ftLvkDHHtpYenjGHbwEFfowkwn9slsZqmPEATV6caHNITCBbhQmvvhqPDPPViV+u1M1c7
vwf/ol7IjBlubwzBJAg6f5GW0tMNHxfg5E7O27AyREyvexk0IVakzIwUuP2anPTjPW0vyeePLtiG
TXNoUe+5UIzpshnLmSlerhVGoB+HBM1yoaaJHay7sdyQbVUxgdcwEwYJKoZIhvcNAQkVMQYEBAEA
AAAwWwYJKoZIhvcNAQkUMU4eTAB7ADcAMQA5AEIAQgA4ADkANAAtADMANQA2ADEALQA0AEMAMAA0
AC0AOQBCADIAMAAtADMAOQBCAEMARAAzADQANwAzADUAMQAwAH0wYwYJKwYBBAGCNxEBMVYeVABN
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
CxwCAgfQ

View file

@ -0,0 +1,61 @@
MIINXgIBAzCCDRoGCSqGSIb3DQEHAaCCDQsEgg0HMIINAzCCA7wGCSqGSIb3DQEHAaCCA60EggOp
MIIDpTCCA6EGCyqGSIb3DQEMCgECoIICtjCCArIwHAYKKoZIhvcNAQwBAzAOBAipOP0AVsizDgIC
B9AEggKQIP/YI9/C2WYbIWxKuqXMD8WPCvqj1fhHmZJ0epCzgEdOR7GT/h2Fy4/wxrthPkj4JqkS
akQog3pjOFtj9D8QtkOw/b761qsyj17TYlQS9C6qVhcddMA+Ca2NcDhKlYofQMNTuYPXkXlpCh5R
CNFgQ+PLVZwNZjqoitjv0RLQqBudhTmJSvfDlW2w+CpbziEeRNzn0pX0/Ts7KxykDscOmUCGHKic
b6FqHoioElcmBp7ae3zdXuvI1x/1Y435qju2yODPpMXEZbdsD5iL07RZyL2vm6lfQbLc37TszDBx
ZZJ7ja5F4V/j/6/AVLkcqfZxFOnXz5Ki9rQblYJbkkTpJAyiNqi8Gx+zgPGtLWvV6KRD0zmxo6q/
OmdjKz4v9aG7MDSXenoy6tPAOvAQcQYaksvFZs1FjorJJpFzasfTUfy94JzrHUzRSPzNRDANHG/6
TgxC1FMNw+iQUY9L8j4xrWsr2JN5tAgYcWz1qZrp4cx0he9cbQeqYcjv7ZvIQbIe2zxdvxh7WByy
r8hNMe3RkMOM2yuP85JuWipq+9jt4/CrimKljN1ULPw+V9FZzY8kKcEiSPD+KXdJNkrMr77/lUJz
PGNYpFBFb4natmi31ZBH2VomTeKPpeanN/ghWojft1mGd1s1nD4NelrWATMVquH2Cq6nhKLRHi4c
KbQsMo+ftLvkDHHtpYenjGHbwEFfowkwn9slsZqmPEATV6caHNITCBbhQmvvhqPDPPViV+u1M1c7
vwf/ol7IjBlubwzBJAg6f5GW0tMNHxfg5E7O27AyREyvexk0IVakzIwUuP2anPTjPW0vyeePLtiG
TXNoUe+5UIzpshnLmSlerhVGoB+HBM1yoaaJHay7sdyQbVUxgdcwEwYJKoZIhvcNAQkVMQYEBAEA
AAAwWwYJKoZIhvcNAQkUMU4eTAB7ADcAMQA5AEIAQgA4ADkANAAtADMANQA2ADEALQA0AEMAMAA0
AC0AOQBCADIAMAAtADMAOQBCAEMARAAzADQANwAzADUAMQAwAH0wYwYJKwYBBAGCNxEBMVYeVABN
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
CxwCAgfQ

View file

@ -0,0 +1,30 @@
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

View file

@ -0,0 +1,69 @@
MIIPUQIBAzCCDwsGCSqGSIb3DQEHAaCCDvwEgg74MIIO9DCCBoMGCSqGSIb3DQEHBqCCBnQwggZw
AgEAMIIGaQYJKoZIhvcNAQcBMCgGCiqGSIb3DQEMAQYwGgQUaHSG4jhu/7OMwM9JSl+8BZkXS30C
AgQAgIIGMJfHzGw/x2vtIsN91neZbEGRQyrmItZnrHIjaNtTaJDyxrd5Qp0aGxNrVzUZxxBlqntn
sVzTKvtH5YsRBJjKrx+kX39Avmh8UWDKi+iPIwjpqdIrk5D9DEg+zjn7OFwL5kS/wwErTFbes/t/
fobuWxJZjEqzbQNimbkdh05jCQTCHozz+VoBvkeEyssmZGrghgi5iLBH9Yrlb85YsQSfcO91Dl2/
LmtnCaMKDQ81cwofRyptbihVelIRSUxLkskOiogscBzJM68ihvNSsd8QaeS0WPbfw7Tic3nVLpUd
wxcaVud8b4OAxxyGL8rRnWzlAsZy5udKv/790DyaOmqlA3n4wAayJII8pRtKhXsHhoA5I8+quJS4
t/Uq/n35lWpczI/5mKWAXEC+LdScVyGC+vXxhcfB+EO5UgfLnus524UbwBA9MLV6jlByUZO8Vj6t
cPcnRaKfxlMcfOPGLuzLJh7/NwOGnSZTtdHqEwQkV7GPV3qgZxHX2r+LWIQ1ZNuoCBBgF+neL9MN
J/wKwXQQtfyRIPA1do8HM1SpujvTlG/ABOiTr0ZDuRW+AkMC4acxbV7G2Cllx84dRJiIQlTUgJy8
NYMJGAGH5gpJezdNQD6wimRiEGIs1yIne2Wc9dPE9y1zKjpbeeXoeepWGM2rYZMJVJSufq0rRKr/
3C5+TyBu0zLigiMrNAhqakPLV4ma3ktpgtigcLAa1eS2USpy/eJboGbRqUFobFYuQk9td4yfdmJM
0sIpeRomy3SWypnJ79NOewgOJKba4Ye65kVHNz2jAFL5R4z7ll4Iqn5h/ylIi6RqMMMWf0hBr9yD
bV5qjuwZGltv1zqTJ8cPjUWMk+UmbZXcsA9W7CnVdGPoWYCT0SW7IkUYQSs0QW7VTReA16KDSoEL
3ZRIGl7KeDqGVm6ZH8zIE0lOVFY0R/2XuIcPc2DNV3UWs0Puous+j5kQgPjF1YD1r9VT6DeMPECZ
HzBJl6a4yvKjm8hXyCnYPnxbeAZJUXOmka/ST1KVUHM499/Lii8/emHTFC/28WkiaLHOUtCegJgx
Kp/eq4RAqYbHe5oUdS9xBaxZX97T0o10udqT6BKep6K/rBKHJxXp3SMuCtBIrcswlojIMc2p9fwF
WVKSZz0zT8rhyepHI5j+IJoTauGYRD46AqSA+6EXWm0bO0oEtBuFCOVeBZJrJMseNxVLfGJOZYtZ
+9ixo9m1+WBV1kGxp1RAnTWAidd15G5sxZ9qhKK9iO63hiWFGmuOiWUb2kUpBOjtM/IRDhU/Q7y5
gvbnhVbTZR7hr+gWyIkpfOBQG42SMwTuqImGpY4yFc7H6NZSYead6Fp4GfUmLLlDG72d6Ue4N+c8
K3DTZYL47LFdXyvMNSuumRQLx+MGQ+DYzZ56uoM9R7B+34Joe8BeJa7bg0vA3Mj9CbZ3+yvYk8TL
UU60BRda1AHwiSoRrLqgeJBZh+cyQB7e7EPcTO//iTPpFVJ8yst9IGn34AndyYULaPpnljMCiUhu
X+zVATaxDMGwc++/95VHdeGRLhb+C5qeSqcPrIdV8XKCd53lgrAoZD1a9nym/mkCLQd+zjm+IE5y
pnxccn/LoFrBm8yf0A35rm+A4Gl8gPSq2GYwu7zfEjXFiAlYrCsc5trQ9YNSGOzbD2BMAn5xxrob
pQliw72xBt43e/VYCWwnLpgKqOfPfX18moDRK/kGeMPe/xtZ4rOiXbm9SEuT0pIFIaoMmilEuEI1
bP2QC/GN1DgBMlV+FRAhWJ+X/NjHjB/TKBMsESyp3ShhCOum112eqoOxk0O4Ob6LVA6Ay6YPtoVX
WhFjebHif5UtTtqd0u9jIU0J9UURkViLEzYN7/3FLIrlmntW35KhEYwCW8FhuXfFfbMHunw+zNoj
ioaJtktg4TqRAXEFrSLIFy3VrsMCnNol100/EU+fqLtJfB9tvAx5pjYzUa2mfFiaoSliBRYHFy/N
BzaXJ2DpFSd+RRbUsrLju3+vljTqtFEkhHFhMG4lgYxTAscqcoUAYfecGGhqL/wYDzh8V1WBDBGq
9UsABqQd4EoqUX01/Driawft4mozRmxtWnTmrvXSRPT4CJp7zCZeQMPrlMKS6+gXDU5MljCCCGkG
CSqGSIb3DQEHAaCCCFoEgghWMIIIUjCCBUcGCyqGSIb3DQEMCgECoIIE+jCCBPYwKAYKKoZIhvcN
AQwBAzAaBBQ4eGcrDBrmIvtj/pYR8qK0Qn77ggICBAAEggTIttxjYbbyyDe0ikO7pUOYY2lCBLGX
Z3Mx54Jg9fYmSCGv7aWubwkixV+tlfWjRfGrpaMLNfJXzcbkvso/H0Fyk1oVWLkhT9DrPWRjMYWn
aZo91EKMvuu77RPzXuEVzNc5dSj01qEURgokH7WUh7Hrsp6Ssuuud+d6a6tCAwiCjLKZQiLuZ1h/
uGalDjtM2yJVo2bZWt6puFt/H8AMLdf8HCREQ0Cddg2PG4EyQiUuzIQEk6IddPKhguWR350YCeoU
Ywx4vU6eVFYZY0DX889rXDi++b975GKoWGd74Kkt+CXrOIuXHCzmeILFouc1Uh/wwIYkgT0ClDnQ
749jKxcFG9tMkqE46POK8BLiy9V2FioKviumdiHVAMOah/sH7Ykf9QY1Qr//fHmaWRz1j966jaow
L9pdQ4v98qRSa7EUJ70AD/wK5Xajtyh6QnzW/OPq9HGIBhcy+PjP95S0MV5TG7OIXBVwgw86wp0E
ycpc2Yr0LmNQP4PJGaN0ECQm5/n886tmyv6KAMlxrzziasYymUNhY4ima12rjVN9wcNxq8Sghq4k
minW3dO4mAfU9gbvZJ1RqPFswBFm5n24zJKjzrO2qlu7tLx6Vkck3vJI3UuGWWxUBsVoHd5m1ZZP
5qrJHeEXvQuxXlyKaY7cNhk0yR7EDYC5SpUroTvVzWe1xYpoQ3ZyDKxCQ23l6jaovHJ3kQz450z0
W59wD1078JlpTwYHsx4TBilabTcZku02uz8PZrFdPl2uJgtkgY0YyrQfYDK88+BvGWl23mbpRCbb
9pO4dxFW0lqJ112EOXECbDmkCvh43NWvr0VqsJUM3xWsKKb9xpaNLSpcK32/BL+ZTQg7ec5/xx4Y
FN4yHTd6YSDzKYHQI252CMImL0HIAC7qOOCftRDEswv6xKIn6TEykCyr08RcTsnjfjzH7HIsjhxa
anv+xXosLZfCN9/RiRXfUb2ayRF2fdQsTNepp3ECiZlhMxfKO7aSwXnQzFyB+F8axEOFBLMEmJxC
7ugz5qDqUOqiR1UNQfpz8fWXGZ4e+GLr3PblVR+CyGCDibZedaeDVXGG3yx2/V7DsYUehJSDz2DB
C8KwWMHetjDlAOXbaKcZ1QhS7upnZhTCwF90JllIZtfKPS4VP9uyFecMc0Ocoq1zdB954nzX2Iyy
t4l8+WWHH1Zb4EY6eLNNy1/wUvngGXqyrUDAocZKk/G8Hy7UPXrSWo9hGRiAm86WeokJjMKHgOH9
lFg7/B1YHl2rW+E1JCAu2xAEJM9HB2+x8OFL/VBoxQLHr/flgGwCkOD62Oy/psUSL0ZQ+hM7qElW
y3+KlS01t4icC99/r4oyA9poAx0EVfSvffi3Nb3Et2ryYRG7kmjMoxvDVpmrAKopnePSE+GAjEbG
FIOli1ewzkOjcLZrdfTpONWfUKJB3Y6AOi7aV4N+wlrMrgAtlHSuDZ4csr1SnHctqpas37CkMg23
KCILn2XktsGXN5AyCmPcmZI48w+8uO4OTxOdK2qIbXrlNaL1bFlHTt9riehDyHD+5LR4zB4XL080
IA9XkbyR5OxdWlcShjPboOvGxMZeoTwmTYE23kCgh0zx0jLhb3bo3jnu6K76h3oPaRikYA5KBob3
L51vXtrFMTowEwYJKoZIhvcNAQkUMQYeBABjAGEwIwYJKoZIhvcNAQkVMRYEFAxeTobq6DehjSbi
ylxISkcqQqH6MIIDAwYLKoZIhvcNAQwKAQKgggKyMIICrjAoBgoqhkiG9w0BDAEDMBoEFAZ8kRRQ
C5cLg1CRiF+Lgzkl9aD/AgIEAASCAoA2KwrF2adzCcInax9pPRso6j4h2KcNgrdsxCWhz+DWBRCw
pOD6uitzCdyeLEMXN95Roqf/XxHZ6n/VKov0U8vgvKEU4RSeHsUQ6DqjrL7HpEhbM/lhfHj0vaWc
tQQCTslHdwl4hWajN44Yv79zMHjA75/n4JAOvtnsyQrF0+44/yA5lFYLZyY4ndbyqzAPo0ZQD6PO
bT8uyH/KbUAi5Etri47ibD1++EDltb45ctO8xA0rFIV25tL/AOG/YajgLC/7QBLTNgvMZ7F2rV9y
qYmNCTdIDzaUIWg4+0qidqVeCPbrHHkqhti4LwOIQhBXesSTuBl1xafwzDeFQpADUe5Hc4+TtJGj
gUT2gBR9dGJI6Wj5MRM/WGT/78UgbpYxG1Q7cZ6quILuzZjWQD+guHSCrhIK42dulowx1aTaela/
XYcR+cRiQtLcmr/0FHfr99d0hJ2BSQIp9IhCsAkU+W7Py39jTcgU/HepzvpsLuPOxI+JL1Rb0llq
+uKaw9jCAy8yIGgplEXg5mhSPXXSDO8k+9CL5rpJvUjQSnLrhLKo2i22p/LIEK6S2uVnD6EdRMYo
J/Vpx2ujqkPZfM/xsbAh04frXLGa2uAISDig+DH1RWlB5jNLRVbfgZA5/PjZyt6gz4lJigpXAVv1
Z13EbEKrbv+CIUJOC+spz8YMH/37YkTW382gWrZkBgmQvZ6Gu5EeeFOIxXRNPseHyg+aY5vjQVyg
V9RAg2sUDwh4u8JANq45dKEFUZfD8EqhVKyd4DuJ38AkxM5SQblQ8eygx0/bAVYzwN8ZRwxDB7Ii
VD+LPthBp147NBgBw0ssNJYQ4GB4gBc7x3UXnyau5aDO9n6KMT4wFwYJKoZIhvcNAQkUMQoeCAB1
AHMAZQByMCMGCSqGSIb3DQEJFTEWBBTuNf6QntPPWXHkQhWW+uEJ8d85XTA9MCEwCQYFKw4DAhoF
AAQUk5iGX7naSu9IN6Kw+sU5Gk319ygEFAwa1WFGcSE0mhaX1jNiYWZtqQnSAgIEAA==

View file

@ -0,0 +1,45 @@
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
1QoCAgQA

View file

@ -0,0 +1,45 @@
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
xp4CAgQA

View file

@ -0,0 +1,69 @@
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

View file

@ -0,0 +1,45 @@
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
1QoCAgQA

View file

@ -0,0 +1,38 @@
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
FgNW1MI40XfEdWafFXeJ+yQTHPyoNdk=

View file

@ -0,0 +1,61 @@
MIINXgIBAzCCDRoGCSqGSIb3DQEHAaCCDQsEgg0HMIINAzCCA7wGCSqGSIb3DQEHAaCCA60EggOp
MIIDpTCCA6EGCyqGSIb3DQEMCgECoIICtjCCArIwHAYKKoZIhvcNAQwBAzAOBAipOP0AVsizDgIC
B9AEggKQIP/YI9/C2WYbIWxKuqXMD8WPCvqj1fhHmZJ0epCzgEdOR7GT/h2Fy4/wxrthPkj4JqkS
akQog3pjOFtj9D8QtkOw/b761qsyj17TYlQS9C6qVhcddMA+Ca2NcDhKlYofQMNTuYPXkXlpCh5R
CNFgQ+PLVZwNZjqoitjv0RLQqBudhTmJSvfDlW2w+CpbziEeRNzn0pX0/Ts7KxykDscOmUCGHKic
b6FqHoioElcmBp7ae3zdXuvI1x/1Y435qju2yODPpMXEZbdsD5iL07RZyL2vm6lfQbLc37TszDBx
ZZJ7ja5F4V/j/6/AVLkcqfZxFOnXz5Ki9rQblYJbkkTpJAyiNqi8Gx+zgPGtLWvV6KRD0zmxo6q/
OmdjKz4v9aG7MDSXenoy6tPAOvAQcQYaksvFZs1FjorJJpFzasfTUfy94JzrHUzRSPzNRDANHG/6
TgxC1FMNw+iQUY9L8j4xrWsr2JN5tAgYcWz1qZrp4cx0he9cbQeqYcjv7ZvIQbIe2zxdvxh7WByy
r8hNMe3RkMOM2yuP85JuWipq+9jt4/CrimKljN1ULPw+V9FZzY8kKcEiSPD+KXdJNkrMr77/lUJz
PGNYpFBFb4natmi31ZBH2VomTeKPpeanN/ghWojft1mGd1s1nD4NelrWATMVquH2Cq6nhKLRHi4c
KbQsMo+ftLvkDHHtpYenjGHbwEFfowkwn9slsZqmPEATV6caHNITCBbhQmvvhqPDPPViV+u1M1c7
vwf/ol7IjBlubwzBJAg6f5GW0tMNHxfg5E7O27AyREyvexk0IVakzIwUuP2anPTjPW0vyeePLtiG
TXNoUe+5UIzpshnLmSlerhVGoB+HBM1yoaaJHay7sdyQbVUxgdcwEwYJKoZIhvcNAQkVMQYEBAEA
AAAwWwYJKoZIhvcNAQkUMU4eTAB7ADcAMQA5AEIAQgA4ADkANAAtADMANQA2ADEALQA0AEMAMAA0
AC0AOQBCADIAMAAtADMAOQBCAEMARAAzADQANwAzADUAMQAwAH0wYwYJKwYBBAGCNxEBMVYeVABN
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
CxwCAgfQ

View file

@ -0,0 +1,47 @@
MIIKRgIBAzCCCgIGCSqGSIb3DQEHAaCCCfMEggnvMIIJ6zCCBgwGCSqGSIb3DQEHAaCCBf0EggX5
MIIF9TCCBfEGCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvcNAQwBAzAOBAjnValj/qxAxQIC
B9AEggTYZZfhDgMBhoV+P+A4KJf/gnrbkgp4ZDWzXl8gOttjRXofhACETGpX5IHsE7UnXbRc4T70
ByZGlcGTDuT9VgiFnFN4VTs1tRIz2W4cs4EmogLX2sX4KP3U6lZiXugEJ36wPSSN8A1prsZsrTid
ff6bsi+sIO+OI6X8Y0degOU44huDhZe7Fmjed13aW6jLhr8SKRSoufDR/sjVnJK476qkYZc4/Dlr
sMmYftHdgxjfm1KdOVycWm+1ItRzniZemiYYYB+vkUBYPO/rMKCp717SWOQhs7SNQcG4KjdLs8vv
skiRPgRzfbt6vaEC4yKy27FDFqzx4unLRzGJ+ekbLzzZAu4TMS7j5g7Ngo0d7GS4+ZGHamOvDuXQ
x8/Itv1/0qzGMwLXyu1x4K1hTgFKD5NQoEk89qZMDVXi4ylGTWXE0x5azKCXP06LxP9/Pit/ufG9
CwUAIeDrZ4A6F0hyT4p7WMgaUqry54/YrjQBd632I7FacKnYojgcW+xQeRufxiYJ5x/6QIZ4dDmj
4rX7W4/0UOVlyFltmmoSq1HJRMaw95iUE+ft3q6vK/bvy6FZSd1CAbr0tut6HBmcW6BOdXFGmXGS
JnbwaK1IFU4c6KOVAwP16poGhOxaJqRaa4zMBaPcYg84rQ3aI00UHGKQvRb6UWYVGVayc13WYcGQ
Mm8GEjlmh4URRXaRL1qTKCjjYjG1mvTG+TOYUwGZUOGD+6fkGFKMkNXxLmaDyyT0cSoBeMl4whQx
obafWD8sMxCJb/E0eil/fbu114rmFfrrqP2evPEIuQoacNr+OUnfr+T6vbBpT79emxkgsKuG7eEt
4okYQTCp6aEpk7ZKppiZVOBvrN1lZfOH9s9qqtbx5Y+9uj5aGADHkhr6c4pYoIaa1BuUKgBiglE7
QdRFm98TFlC328BbUvBFXEAnshXeYHRPgevcapDBIqFz8ZBnJNMgY3KZ+mug0wg09vsFE8TkH86p
WwvgUzLlZDNt64OHh9E5Ql1MtnMlp0nunpLQyYcmCn8AJIcxSnaicjSlp+Z04hSWXAesbWie41H2
OA1CqsQdc9EePijdjX3QxDK9mBNhXY2ngWrvwkmlYatHdSFzXB4uzCsT5NKK0nKI/AmUN5vVVv01
CFCPHgyBBxF1wom2mA/QFv+7WX6c5Oj0WgOLe/3VySQ9xPoI53Cc1Jl7uOm6kXIMzMxCOiDDcScJ
i0LwyDtmVZlOqhiGCiguoptQnTT3zzp2uaDLVvyMy7bZP8T7G7ka7CSpWQNr0USldgpT8HOXJWgI
4il9iQlaajYO9ntwtYAlMTjsYy4NNoW0uYajdnjT1wO+0w1A0SKP7UrRnyaonf/G4z/VeNSh+yEn
7RkFErPhhvHQRFMG3Gkgw4ER+zo7Q7x2m5R7FOeCp4x0/wiI0e/SzyYxBqXSQfEWxQjb7IJVfd6a
gFT/heXJDvEGbLzUR9jhDptGggE2NlFyA4G+ol6XRRZKlBA0XUYJPHY+fyvcHikiJeMM/YRkrhCE
LOqfCNOafSSSLcQNzJjevq/cDpgybQZV+BrN3yPtQlZgZAy9jOZlULVQSak7K2dF355mEtPNQUIH
4U+GdMXitRVknz/dv7SF8tVzR/GYJEX51i0Qou+rzOFhmurxHyomRHnB5WTG8D/SbzGB3zATBgkq
hkiG9w0BCRUxBgQEAQAAADBbBgkqhkiG9w0BCRQxTh5MAHsAMwA4ADkARgA0AEMAMQA3AC0AMABC
ADQARgAtADQAOABFADYALQA5ADAARAA1AC0AMwAwAEMAMgA5AEYANAA4ADUAMAAwADUAfTBrBgkr
BgEEAYI3EQExXh5cAE0AaQBjAHIAbwBzAG8AZgB0ACAARQBuAGgAYQBuAGMAZQBkACAAQwByAHkA
cAB0AG8AZwByAGEAcABoAGkAYwAgAFAAcgBvAHYAaQBkAGUAcgAgAHYAMQAuADAwggPXBgkqhkiG
9w0BBwagggPIMIIDxAIBADCCA70GCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECBHBi0p8N2Vx
AgIH0ICCA5A7JaVFBqZTQbSEJhtjKPmwteV230BLhKvw4qfM9vxcBNj8kBZGDJaWYZK5BatuKMu8
xd60lqzoKgUOHrN9etjMCe2h/z/RyyeVpBuEILJUQaj+SuSTSUUTpGKokKVnSQvCAD1UgJGFt/ac
elBlaIw9pRDnDZgFhzZ3AWO09vBz+GcowUlA77W173d6fHf26khicTalsdXbimnMt48/mdtKH9ep
pjgxJwhshPhgKKt5M87nEyaaGSEFfsrPgcIj79poWwj8WE6sAg+bVw3OfX9rvbpP2vWF/e6Vc2x/
QJPChQZs8LqJAUy2lI55gZgv+hTKkkBXoHG0c4248KdyvBT5DCiFufaj/dp1Eja02Qxo+BqZLJS7
EYE1YxB7Ty9CUxWvAt6aRLQ0ZLbrK28mwgCePctczxQa+tcCMCfL/JJvcZtiu5CaHObLzF7Ymbh7
/Q6u1+5u3/Im7aBdY5AksTz2Zn4JjzSAXKTdEgcadjGsxTd/lj4dUOreXN9rUgNyQzjQHpljnhxF
6ZAAbNC8FJwFIAm+ipmV7keCWT8s6MQeoQ5qr5RDhVhGUVM2CWoKRjhbKzWbnKetfmjAUnvn0+ZO
vSKmOShMG8QgyG8trDIH734jTG6u6yoe3Afjw52DtfOo1OVi0ZDsj5GviFDZYQX5Z/86N4Tx7Tol
e/Wz5918nziNoU3+07ZySsRRESuLj6p11sUmFFPj64W/CZ1YQB/H4+R+94uYyWiovHudC/69KnBg
Rfj0XpdSg0l+HKgTez7OuJrEu9/+5QF0M1unJSGxpdojVkACf+bxu2+4czzh80sL/3Yzcenvg/nt
AQGm+sX/K2oF2E0h/22RD4U2txDxORVGcF+wfNUHkl2m+rBkgsUMhECeWGwoI/y5ZBHWWcQP2ByZ
78fa8a9L1RWGvn51yLOe/cPZ0pmYBDZ9aiP1KucGBNMTzHefZiRXscXjB28u7/YxUb7fFPY3RjjO
p2Rm17rrFrvR9/oChO9ZVJrm8p2lQfKufz/t1USs8+gZPS+kLfE3wxZefo1nFmbkTWQT6hW+z4zh
0QoBNwGJVFYxPuGvyOmQ4ksEHe7G8fc7ihkiZ+A9fJROqOjVA/ThnWIuiLKbDFlW1rQbdlihQy7Z
oKbzbA9eOMUCaXMEti5CG/97pOCiElARHDactfiy0J7ykjCGLCkw1/3j5Qdr3feN4GWqOBTfn0cK
eq8RT0pBkT0wOzAfMAcGBSsOAwIaBBRW5H12kY01oB2hnm0lkT0yUbjP4wQUF7tfAlojMdSZIdKB
/FfU1hlVl8YCAgfQ

View file

@ -0,0 +1,62 @@
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
IsNed5PjTXd1/rQmWIcCDOy9lgICBAA=

View file

@ -0,0 +1,45 @@
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
I6oCAgQA

View file

@ -0,0 +1,73 @@
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

View file

@ -0,0 +1,54 @@
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
0AQQxrOtDDKIzjpW4+rATcwNPAAA

View file

@ -0,0 +1,125 @@
MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAGgBAGA
BAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCBVoEAQQEAQEEATAEAQQEAQMEA4IFVgQBBAQBAQQBBgQB
BAQBAQQBCwQBBAQBCwQLKoZIhvcNAQwKAQIEAQQEAQEEAaAEAQQEAQMEA4IE9QQBBAQBAQQBMAQB
BAQBAwQDggTxBAEEBAEBBAEwBAEEBAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoqhkiG
9w0BDAEDBAEEBAEXBBcwFQQQ6T2lKjQK0wo/cjrjNyb0CwIBAQQBBAQBAQQBBAQBBAQBAwQDggTI
BAEEBAOCBMgEggTIiZ+WxZhkj+CjQo4+eTTGf/tSoJMtp85VFwcFUy2+Bz2+WIOf7abQ3yVRmkSc
MUeb/1vQDS+NXMimZDLoIIN9M1ql3Mq5Qtr++kURQeZAVh9q2ZJNDAmw2rvAWGJxdbqPrMA2WgQc
oGZVLiN2eIdWXxJkjLdNzjMWtpsh+6Yw52lwq8ZEIKgu7v23my8+HCemGCL87wf7qU0nQjq+I5jf
QZujYJL5iDNvosZLFLzBuOZKG7voDY2gJtbl+yiOUMOPBQYdDE8qiF+eHqu8WZ/JwlA/3EtnuIDz
i/9f9mIHMINC5vpvPXuo9TE0nF9PvxtL8mGmRcxG0vVro0sPEzu1f13OsN4qwDUVWJ6Xr154zkU8
9wMi8SAY+gbETvbZZQpxgHWsaEjG9r7fCjiLE/x+5VZCaPeNK8zB+cb0Z2wPGPlojV6Ggcqt/7dI
pZtRMyeSNpSCTncgZlBwh6JLKRCLFSEjZhGzKIsCjT9TpU+IzoD9Niue1cWo2ciZIuTMaSwnqYhO
KzJ/Wivqx9tjhEVI9cCuLf/JPpmFvsmrdMurjD6s4WQPMc7prK8aMJy5W3vcN32wuEQyR6KcqhDn
QxsX7KPavuIi3dTe8I4pNaMJlZ3Ubif4qvt5qJe6I3rxuie2Q1ux7clXk99W5ZvU06tCYTv/3GP4
M3TjupaWAtmgWZRLsjbTW2NBnxVP40o0AthzYCElyrqhlQPTRU/p1y3RPXyVyssZXwCtvQJe4cxb
V38+kjVSrYL+WGjVkuCQAs4KSdmsH97ShclgAAsrqhDi4+DNhaVIuoFMhkwp4DngxiWMNHWYMjAC
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
AoiyQ6u3imI281gAAA==

View file

@ -0,0 +1,73 @@
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

View file

@ -0,0 +1,54 @@
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
HwQQ6Vxq63yfCeamza5PZKytWQAA

View file

@ -0,0 +1,125 @@
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
LK2fdlxrCGzUHTgAAA==

View file

@ -0,0 +1,41 @@
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

View file

@ -0,0 +1,38 @@
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

View file

@ -0,0 +1,79 @@
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
VL+NWQOgtME=

View file

@ -0,0 +1,65 @@
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
fAQEFPL7KYm4NrHpQSKpto5+pPs7NgLWAgIEAA==

View file

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID7DCCAtSgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJJTjEL
MAkGA1UECAwCS0ExDDAKBgNVBAcMA2JscjEPMA0GA1UECgwGT3JhY2xlMQ0wCwYD
VQQLDARKYXZhMQ0wCwYDVQQDDARMZWFkMB4XDTE1MDUyODAzNDMwN1oXDTI1MDUy
NTAzNDMwN1owSzELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQ8wDQYDVQQKDAZP
cmFjbGUxDTALBgNVBAsMBEphdmExDzANBgNVBAMMBk1lbWJlcjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAMr07JoRV0kR5mNKgLFKLYeUQ2eFEyV8alkC
3OL2Ew9tP9CT+60kqlbyLfxa8+8XU/SClch6yf7R4majR85PgfJuZKRvyUdWgw5y
K0wbxWkRVqRAgSo0Zp8hkhV9BDe1R7s4r4XBI/rSVTQmDsMVZdigDtIDYKMS0BtW
DnW4ueWbZHdNHyxlTEJc6trsvU2KH5pY69VgGZzonNuMa9p17aQpOnVbWNhS6Mcs
mHonU5d19Xh543T8ovbA8cj0osdYgcOQ42FEBqON4Lih8SyhqZQyi4UvkiHek3Pu
i5Q0dwwVT1lnorUwH3bXp4boMaUmh7bvKMe/BQ5T18wkXlgYuVECAwEAAaOBzjCB
yzAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUWDsl+9vHtuuQRhb+Zyd//f6qSXEwcQYDVR0j
BGowaKFbpFkwVzELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQwwCgYDVQQHDANi
bHIxDzANBgNVBAoMBk9yYWNsZTENMAsGA1UECwwESmF2YTENMAsGA1UEAwwETGVh
ZIIJAIQbGsfQ2qikMA0GCSqGSIb3DQEBCwUAA4IBAQABEg/vV+ckqMwwA6QLdk6i
Q+oaYcjz2C7wcZmvmrdYGHUrtlf4aWQd4G/TDBtqKZ6MfA2AaciDe7lAI2agdKCM
MFG6XeqtjElCa77b8KrE3Ha+N07pmYnU42vZrqMpayjj/Eey9bOuSaTgLVTA00BI
5wiTbLokTrYW3lhMityeFyvGw7bEvfGbXLs/7hyZ6wEXindgaGT9adL9jz2LT2Tt
YorRvxRSRMbBWCc6o+ICfawU226ZOetGVfdTSYgL3a9AQ+zAMhgdJq+ac077G1vA
HzKZgygYAHIr1G0DxwEPOAHBQFtbTbAQURpjzKWFYeGiZuCEBwwsKgDIT0kGF76E
-----END CERTIFICATE-----

View file

@ -0,0 +1,31 @@
MIIGwAIBAzCCBnoGCSqGSIb3DQEHAaCCBmsEggZnMIIGYzCCAzAGCSqGSIb3DQEHAaCCAyEEggMd
MIIDGTCCAxUGCyqGSIb3DQEMCgECoIICqjCCAqYwKAYKKoZIhvcNAQwBAzAaBBSZNW+Sd+0mytcN
A/vZXbBxiRZHxgICBAAEggJ4YAYE4bHqC0rxj3w6eUmXqp/tebM75dLfm/YyOQqKTE5bPJNWAT2E
njhtDTNDigxhLjy4tH1sligytYgABTOcBotniRGM9yZ/52JR7bv6NxGCbv+SU2v10Srug+onIhFM
639E7bG1yRfNW7IATgKLX1KxIBWFX973MBnsDVK5gZEhy17hzLUdaJRk3AyiCIB17R3d0SthtIW+
WR/1rYUDOUe4weJYPsVW+WwtYtdOllcDLopS+B/QgXPrv9FOLUfEHtNO9crLMnGU8Kr9uqMyHu99
ZdIgH1wuuK3Na7noc4KI4Q3JoTsRRfWpl6nEt5FERpRY8Q1spNwzo9mZ9NwtVyMkjGfSnZP8RE7M
2csqZESd88PGVcnrMzNb/y+5X1qgj+bx56v+6m91QcIcv3RMK645Wiow9WjtmZL5sGl0SNUcwzP1
zYGjZrWnTICjMmuNDIDznX2yrtHLxoM8AzhUwIvirTROv+RaqO+gopDxTBy9kymPiHS6PLllC3hL
GYqZ1CFCIkn7nf9DP4tKJmfvOhrURCFnbXSlIbu7d5j8TNI+6CLuD9H1c8vlp6kdvaJejLzAVFt8
eY8A/zIDUKcyKXCFPS4F25X6vJ6ZdQOKBVzg8ueAUety6o44eJ7NxusLoMyHneLCTQ7jRobSihss
eXa182Yk1Q+H7Dx+zbPr6FsNp8wNf90CM6zZAbgBqBzM5eGb2Y/Ich1eG2oLAFurrpqgxXlb6nJS
nJ7e7NgAqf3S4VbKt3uCvVtrZfUUvCdx4BUfeNSNOGmAtgCRlPn93Gc2+IL7eJYNqDScNjGf/hj+
rHCL7jNPRvoovzBdUSzJ1Y92r0iUWu4xWDAzBgkqhkiG9w0BCRQxJh4kAHAAawBjAHMAMQAyAHQA
ZQBzAHQAZQBuAGQAdQBzAGUAcgAxMCEGCSqGSIb3DQEJFTEUBBJUaW1lIDE0MzI3MDQxMTIzNzQw
ggMrBgkqhkiG9w0BBwagggMcMIIDGAIBADCCAxEGCSqGSIb3DQEHATAoBgoqhkiG9w0BDAEGMBoE
FNSn/NMdKj9fmg+dMmEFE2rlvLY8AgIEAICCAtiFvAUXr/bKf77WWVx2Y9OnqlUNkXkeE7XEI5XB
qKid6iUlv4eRWY3PyK5gLIDELGJHOIpHKAkjSef6kBU04E/jcQmg+kA+3GScXFZXTw+jjgGmaX9x
zbAzXAvEURwh/T0HRtxsxXLf+7D3gdiIAQcVyh50xD58HOOox7mo1NFQ9Vi63f82wyJgQH1tYSid
ExsC2ZJ2H7mncZrD/RtKgShwEmn8CTappx9iILVGkyRTbliWKxfr5EaEY0yXpDN8aj5N4pgGWg8O
Qh9axIRFuTxhZ4jIDMEI6VUT0ugBn1rfBbaqWfmM3IfQZsQQsidARCISyajzjEDaiB0wRRCSuoyU
FJdkCttHj8M85VvsRDN9YQa2ilBDfSjaJT8SQsvmMP8fpohnalGZsADBSTCZp1s6m5vgPErSCmY3
w347fK3UtnDhtpxy6KvtiosJq2YLszC16O2KaiwvDoOteJSTv3aJfMXuZWF0QCBwN2pPhyPCnQZq
sUe7YlnaihKqzAj+jyaWRI48HJY3y94zeEESXuY4Y1fgrWfsEuO7oHcqTvy0O10otPOnG5etIvNL
uFBmYYL3Ag9HNKYHwl1d/lqrh7a3dHi8IuREQ1vY74sFbhefzDsZs4Foz0m60oJY2BeNl1BPtFKW
yVrwIMKAlLovx5+sH/HvVtchabl0RPlNtYJNEUDVnp40OLE4B7fDQaNOY3hQJErCsE+ffhHMqy0k
bLVM73XKBhS4GypIBx+GSZauuOXmxBKJCz/00ZUXfeRDqjSUe901eip9fILUmFObBlohbE02xt15
8b0m+tHgj3aNvF5RkTnendRGh3D+O8hBWz9+AHSpIsXxemuWJ+VQgIeMOERwD+62zkEqLgOsn1pB
3ZmN3pUl8mIWNDrdC7nGLU6YJt4PNVFRYtJIhuo8fN3I/Fk0CMCwZhZMsP8UcEH9GJOBK5/MtCds
ZBMUE/UJsjlGCzcq/7OVTDA9MCEwCQYFKw4DAhoFAAQUPQnz3GvfsIzh1/29KwCg+E8LeVAEFMmb
qHeo0noP26ViWalg3FeT8Lk+AgIEAA==

View file

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICRTCCAa6gAwIBAgIEFjfyzjANBgkqhkiG9w0BAQQFADBWMQswCQYDVQQGEwJV
UzEPMA0GA1UEChMGT3JhY2xlMRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxHzAdBgNV
BAMTFlBLQ1MxMiBUZXN0IEVuZCBVc2VyIDEwHhcNMTUwNTI3MDUyMTUyWhcNMzUw
MjExMDUyMTUyWjBWMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGT3JhY2xlMRUwEwYD
VQQLEwxTZWN1cml0eSBTUUUxHzAdBgNVBAMTFlBLQ1MxMiBUZXN0IEVuZCBVc2Vy
IDEwgZ4wDQYJKoZIhvcNAQEBBQADgYwAMIGIAoGAUPl3dSLSQd+ocj4oDJI6qdt+
iIamUd6aDHllX/vNfguuX5G1/NO/aas5XofV9Zfy+XCdqGI/rUE294vod1BkBOiP
UmsgHl30nWCwEq5FuFWLwLWgm2DkNMGVJnvvCVLDzuYhvkymNbOoppHywIMVAryP
Xi2082vRKvW677VqcT0CAwEAAaMhMB8wHQYDVR0OBBYEFLpLVS5KZoGIDGmden5r
AK3/D9+5MA0GCSqGSIb3DQEBBAUAA4GBAEomR40Sj+BvNYiL8Lfr2vMadCF23R3X
fjPd3TCGuMJtI78N9lSTnrZCnrxn4ep7FuVl59jqEX7mBQcVtUNPqw/xrFI/sv4z
Nwxa18TG78i85OXapvVsX1fWx0GeeK2XTKetHLMEc8zcW8IHcukSX+5Z6Y/pg+lB
mqEx9bvLCJTW
-----END CERTIFICATE-----

View file

@ -0,0 +1,2 @@
# do not set keystore.type property, so default value will be used
#keystore.type=

View file

@ -0,0 +1,31 @@
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

View file

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICRTCCAa6gAwIBAgIEL8ZaXTANBgkqhkiG9w0BAQQFADBWMQswCQYDVQQGEwJV
UzEPMA0GA1UEChMGT3JhY2xlMRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxHzAdBgNV
BAMTFlBLQ1MxMiBUZXN0IEVuZCBVc2VyIDEwHhcNMTUwNTI3MDUzNTI1WhcNMzUw
MjExMDUzNTI1WjBWMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGT3JhY2xlMRUwEwYD
VQQLEwxTZWN1cml0eSBTUUUxHzAdBgNVBAMTFlBLQ1MxMiBUZXN0IEVuZCBVc2Vy
IDEwgZ4wDQYJKoZIhvcNAQEBBQADgYwAMIGIAoGARub+B5xAEtoE2Sv9+oRnKYIC
AZZ5dpTdMUWiExsXBcK6KQ61X5GftMz4a5io7PoxJxsDkPyTPNaHov2dzOBblbn2
Gd0YgRdI3jcmm6ELDN7CqzsO7FK48L8maLeIj/0hYPBZPxKohjChi2GUNKn97OMf
Y0LTeDqpO6+oc2E25XECAwEAAaMhMB8wHQYDVR0OBBYEFLC2ChLxDu/yacB3s0ON
NNDusz2SMA0GCSqGSIb3DQEBBAUAA4GBADhG2wSf4KHMspsKv8bkjWrDA6wTjwnx
pQES8E2dMmmp/LybH0CerpcShGGw35uh8wnCaWA1hBgMAs1mfghTt9X8tZCG5MmA
VmkR7VPu1lNbdB1sswXAy3/423ncWbPJKIvbXBLJrzvC3Ri6d/AiH/0Tud0H15IN
YQ+ThBRF5iQC
-----END CERTIFICATE-----

View file

@ -0,0 +1,31 @@
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

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICRTCCAa6gAwIBAgIECrE+nTANBgkqhkiG9w0BAQQFADBWMQswCQYDVQQGEwJV
UzEPMA0GA1UEChMGT3JhY2xlMRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxHzAdBgNV
BAMTFlBLQ1MxMiBUZXN0IEVuZCBVc2VyIDEwHhcNMTUwNTI3MDUzMDEyWhcNMzUw
MjExMDUzMDEyWjBWMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGT3JhY2xlMRUwEwYD
VQQLEwxTZWN1cml0eSBTUUUxHzAdBgNVBAMTFlBLQ1MxMiBUZXN0IEVuZCBVc2Vy
IDEwgZ4wDQYJKoZIhvcNAQEBBQADgYwAMIGIAoGAUJKwuZJOuG+EZ9d8L4BDYOzv
2sFCyCTrDbw6lH/vaG/kkhJgZdYMV1pwqxmsspUrSYwATx3usPElv+OOjEJlwuLo
wj+/6Ob9LirwUAHb9LbcF5r9dRxLBcFUaTnDlqzgOuS1gn9dnD9z4CugId9t9IjF
tLiump5zXNcZw/+/JKMCAwEAAaMhMB8wHQYDVR0OBBYEFOKLf8ckktSBUTDRoYxV
b56vtgd8MA0GCSqGSIb3DQEBBAUAA4GBACgrbEqfqtgKx0iLiQEgKb4K+O4Gg8Td
wuSjtXn9WQR5Fux7XNoM8f3xRw95CROg1/JEYhsH7fzeG/Aq6BbFooyHZsQ7yGXJ
ujJ3O7hl0MuFZRChf9QP7YQjYb4toj1wdE0EvA9lNWomr2Ox9b3+QFTdxPcBElv6
+ImhOPtF6/lt
-----END CERTIFICATE-----

View file

@ -0,0 +1,76 @@
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

View file

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIBAzANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJJTjEL
MAkGA1UECAwCS0ExDzANBgNVBAoMBk9yYWNsZTENMAsGA1UECwwESmF2YTEQMA4G
A1UEAwwHQ2xpZW50MTAeFw0xNTA1MjYyMjE3MThaFw0yNTA1MjMyMjE3MThaMEwx
CzAJBgNVBAYTAklOMQswCQYDVQQIDAJLQTEPMA0GA1UECgwGT3JhY2xlMQ0wCwYD
VQQLDARKYXZhMRAwDgYDVQQDDAdDbGllbnQyMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA2HADVMaKPd7xAYK0BTsCcQzglk8H2qp0Sg5nDYgb7KqB/1cb
RyMB3g3FG4Isv6L0Lp2GLAeHVn35YljHNrcBUU5fG/+DNJPNiM+srevblMeksOcA
frPnxmog+GMgiO97O2/3Xtgl0ailsOHidPH9hBXr+WikNu7ITPXkJiYi0d1n8p2N
e/p4W4cBitxIUlZm2OTSW4d3EDW86saf657kSpTlb2zBT/r9fjWluHlTg+jGnGIz
UdpYP7sSnye8oym5PxT2IMPU6vRgF9Gzwg+6bPaZnrYNURifGJIuQH+/wDaqA+Ix
g2Q2Ij8SiDhkNrCoeLf77Aot9d5ZPtledJPSRQIDAQABo3sweTAJBgNVHRMEAjAA
MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd
BgNVHQ4EFgQUhxNmvHpNjpjnl/vMVkEnyF5Msk0wHwYDVR0jBBgwFoAUHyFP2xAx
0GeDCQPTzfxG7M8di7QwDQYJKoZIhvcNAQELBQADggEBAD4rXzKq8PdSK7rzuwfu
q+RzeYZnNM7OsoBGhMfHQKnnI3LH5bgyttuCoV665X2mgy6+LZcrXqom/ZrLXQ6x
JVtGxNHr7rqbnC/9tB2/s9HHN3YiRs966shWHGkhCubsUGre7Z25Pq55K6Pyl+nU
hb+K8aQ54z4oDt+raAdbuILq91fUjw5j1qex3d62fHvf4IO3spcKY4HhnwBPifg2
YZCiZRZOoVysi2FTdsvW2NfQCYgtUftbkfNrKglkRuIa9rQEduhDy1cwn4fc9S1f
6WTvuJNoIp3o1nQppFjfO7fzfIDCrlaEkkXU7O54KQ5HTKu62tZp9xKW71oolOnZ
bZQ=
-----END CERTIFICATE-----

View file

@ -0,0 +1,303 @@
/*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8044445 8194307 8207318
* @summary test new methods from JEP-229: Create PKCS12 Keystores by Default
*/
import java.io.*;
import java.security.*;
import java.security.KeyStore.*;
import java.security.cert.*;
import javax.crypto.*;
import javax.security.auth.callback.*;
public class ProbeKeystores {
private static final char[] PASSWORD = "changeit".toCharArray();
private static final char[] BAD_PASSWORD = "badpasword".toCharArray();
private static final LoadStoreParameter LOAD_STORE_PARAM =
new MyLoadStoreParameter(new PasswordProtection(PASSWORD));
private static final LoadStoreParameter BAD_LOAD_STORE_PARAM =
new MyLoadStoreParameter(new PasswordProtection(BAD_PASSWORD));
private static final String DIR = System.getProperty("test.src", ".");
private static final String CERT_FILE = "trusted.pem";
private static class MyLoadStoreParameter implements LoadStoreParameter {
private ProtectionParameter protection;
MyLoadStoreParameter(ProtectionParameter protection) {
this.protection = protection;
}
public ProtectionParameter getProtectionParameter() {
return protection;
}
}
public static final void main(String[] args) throws Exception {
// Testing empty keystores
init("empty.jks", "JKS");
init("empty.jceks", "JCEKS");
init("empty.p12", "PKCS12");
load("empty.jks", "JKS");
load("empty.jceks", "JCEKS");
load("empty.p12", "PKCS12");
load("empty.jks", "PKCS12"); // test compatibility mode
load("empty.p12", "JKS"); // test compatibility mode
load("empty.jks", "PKCS12", true); // test without compatibility mode
load("empty.jks", "JKS", false); // test without compatibility mode
load("empty.p12", "JKS", true); // test without compatibility mode
load("empty.p12", "PKCS12", false); // test without compatibility mode
probe("empty.jks", "JKS");
probe("empty.jceks", "JCEKS");
probe("empty.p12", "PKCS12");
build("empty.jks", "JKS", true);
build("empty.jks", "JKS", false);
build("empty.jceks", "JCEKS", true);
build("empty.jceks", "JCEKS", false);
build("empty.p12", "PKCS12", true);
build("empty.p12", "PKCS12", false);
// Testing keystores containing an X.509 certificate
X509Certificate cert = loadCertificate(CERT_FILE);
init("onecert.jks", "JKS", cert);
init("onecert.jceks", "JCEKS", cert);
init("onecert.p12", "PKCS12", cert);
load("onecert.jks", "JKS");
load("onecert.jceks", "JCEKS");
load("onecert.p12", "PKCS12");
load("onecert.jks", "PKCS12"); // test compatibility mode
load("onecert.p12", "JKS"); // test compatibility mode
load("onecert.jks", "PKCS12", true); // test without compatibility mode
load("onecert.jks", "JKS", false); // test without compatibility mode
load("onecert.p12", "JKS", true); // test without compatibility mode
load("onecert.p12", "PKCS12", false); // test without compatibility mode
probe("onecert.jks", "JKS");
probe("onecert.jceks", "JCEKS");
probe("onecert.p12", "PKCS12");
build("onecert.jks", "JKS", true);
build("onecert.jks", "JKS", false);
build("onecert.jceks", "JCEKS", true);
build("onecert.jceks", "JCEKS", false);
build("onecert.p12", "PKCS12", true);
build("onecert.p12", "PKCS12", false);
// Testing keystores containing a secret key
SecretKey key = generateSecretKey("AES", 128);
init("onekey.jceks", "JCEKS", key);
init("onekey.p12", "PKCS12", key);
load("onekey.jceks", "JCEKS");
load("onekey.p12", "PKCS12");
load("onekey.p12", "JKS"); // test compatibility mode
load("onekey.p12", "JKS", true); // test without compatibility mode
load("onekey.p12", "PKCS12", false); // test without compatibility mode
probe("onekey.jceks", "JCEKS");
probe("onekey.p12", "PKCS12");
build("onekey.jceks", "JCEKS", true);
build("onekey.jceks", "JCEKS", false);
build("onekey.p12", "PKCS12", true);
build("onekey.p12", "PKCS12", false);
System.out.println("OK.");
}
// Instantiate an empty keystore using the supplied keystore type
private static void init(String file, String type) throws Exception {
KeyStore ks = KeyStore.getInstance(type);
ks.load(null, null);
try (OutputStream stream = new FileOutputStream(file)) {
ks.store(stream, PASSWORD);
}
System.out.println("Created a " + type + " keystore named '" + file + "'");
}
// Instantiate a keystore using the supplied keystore type & create an entry
private static void init(String file, String type, X509Certificate cert)
throws Exception {
KeyStore ks = KeyStore.getInstance(type);
ks.load(null, null);
ks.setEntry("mycert", new KeyStore.TrustedCertificateEntry(cert), null);
try (OutputStream stream = new FileOutputStream(file)) {
ks.store(stream, PASSWORD);
}
System.out.println("Created a " + type + " keystore named '" + file + "'");
}
// Instantiate a keystore using the supplied keystore type & create an entry
private static void init(String file, String type, SecretKey key)
throws Exception {
KeyStore ks = KeyStore.getInstance(type);
ks.load(null, null);
ks.setEntry("mykey", new KeyStore.SecretKeyEntry(key),
new PasswordProtection(PASSWORD));
try (OutputStream stream = new FileOutputStream(file)) {
ks.store(stream, PASSWORD);
}
System.out.println("Created a " + type + " keystore named '" + file + "'");
}
// Instantiate a keystore by probing the supplied file for the keystore type
private static void probe(String file, String type) throws Exception {
// First try with the correct password
KeyStore ks = KeyStore.getInstance(new File(file), PASSWORD);
if (!type.equalsIgnoreCase(ks.getType())) {
throw new Exception("ERROR: expected a " + type + " keystore, " +
"got a " + ks.getType() + " keystore instead");
} else {
System.out.println("Probed a " + type + " keystore named '" + file
+ "' with " + ks.size() + " entries");
}
// Next try with an incorrect password
try {
ks = KeyStore.getInstance(new File(file), BAD_PASSWORD);
throw new Exception("ERROR: expected an exception but got success");
} catch (IOException e) {
System.out.println("Failed to load a " + type + " keystore named '" + file + "' (as expected)");
}
// Now try with the correct password within a LoadStoreParameter
ks = KeyStore.getInstance(new File(file), LOAD_STORE_PARAM);
if (!type.equalsIgnoreCase(ks.getType())) {
throw new Exception("ERROR: expected a " + type + " keystore, " +
"got a " + ks.getType() + " keystore instead");
} else {
System.out.println("Probed a " + type + " keystore named '" + file
+ "' with " + ks.size() + " entries");
}
// Next try with an incorrect password within a LoadStoreParameter
try {
ks = KeyStore.getInstance(new File(file), BAD_LOAD_STORE_PARAM);
throw new Exception("ERROR: expected an exception but got success");
} catch (IOException e) {
System.out.println("Failed to load a " + type + " keystore named '" + file + "' (as expected)");
}
}
// Instantiate a keystore by probing the supplied file for the keystore type
private static void build(String file, String type, boolean usePassword)
throws Exception {
Builder builder;
if (usePassword) {
builder = Builder.newInstance(new File(file),
new PasswordProtection(PASSWORD));
} else {
builder = Builder.newInstance(new File(file),
new CallbackHandlerProtection(new DummyHandler()));
}
KeyStore ks = builder.getKeyStore();
if (!type.equalsIgnoreCase(ks.getType())) {
throw new Exception("ERROR: expected a " + type + " keystore, " +
"got a " + ks.getType() + " keystore instead");
} else {
System.out.println("Built a " + type + " keystore named '" + file + "'");
}
}
// Load the keystore entries
private static void load(String file, String type) throws Exception {
KeyStore ks = KeyStore.getInstance(type);
try (InputStream stream = new FileInputStream(file)) {
ks.load(stream, PASSWORD);
}
if (!type.equalsIgnoreCase(ks.getType())) {
throw new Exception("ERROR: expected a " + type + " keystore, " +
"got a " + ks.getType() + " keystore instead");
} else {
System.out.println("Loaded a " + type + " keystore named '" + file + "'");
}
}
// Load the keystore entries (with compatibility mode disabled)
private static void load(String file, String type, boolean expectFailure)
throws Exception {
Security.setProperty("keystore.type.compat", "false");
try {
load(file, type);
if (expectFailure) {
throw new Exception("ERROR: expected load to fail but it didn't");
}
} catch (IOException e) {
if (expectFailure) {
System.out.println("Failed to load a " + type + " keystore named '" + file + "' (as expected)");
} else {
throw e;
}
} finally {
Security.setProperty("keystore.type.compat", "true");
}
}
// Read an X.509 certificate from the supplied file
private static X509Certificate loadCertificate(String certFile)
throws Exception {
X509Certificate cert = null;
try (FileInputStream certStream =
new FileInputStream(DIR + "/" + certFile)) {
CertificateFactory factory =
CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(certStream);
}
}
// Generate a secret key using the supplied algorithm name and key size
private static SecretKey generateSecretKey(String algorithm, int size)
throws NoSuchAlgorithmException {
KeyGenerator generator = KeyGenerator.getInstance(algorithm);
generator.init(size);
return generator.generateKey();
}
private static class DummyHandler implements CallbackHandler {
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
System.out.println("** Callbackhandler invoked");
for (int i = 0; i < callbacks.length; i++) {
Callback cb = callbacks[i];
if (cb instanceof PasswordCallback) {
PasswordCallback pcb = (PasswordCallback)cb;
pcb.setPassword(PASSWORD);
break;
}
}
}
}
}

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8244336
* @summary Test JCE layer algorithm restriction
* @library /test/lib
* @run main/othervm TestDisabledAlgorithms KEYSTORE.JKs true
* @run main/othervm TestDisabledAlgorithms keySTORE.what false
* @run main/othervm TestDisabledAlgorithms kEYstoRe.jceKS false
* @run main/othervm -Djdk.crypto.disabledAlgorithms="keystore.jkS" TestDisabledAlgorithms keySTORE.jceKs true
* @run main/othervm -Djdk.crypto.disabledAlgorithms="KEYstORE.what" TestDisabledAlgorithms KeYStore.JKs false
* @run main/othervm -Djdk.crypto.disabledAlgorithms="keystOre.jceKS" TestDisabledAlgorithms KEysTORE.JKS false
*/
import java.io.File;
import java.util.List;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Provider;
import java.security.Security;
import jdk.test.lib.Utils;
public class TestDisabledAlgorithms {
private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms";
// reuse existing JKS test keystore
private final static String DIR = System.getProperty("test.src", ".");
private static final char[] PASSWD = "passphrase".toCharArray();
private static final String JKS_FN = "keystore.jks";
private static void test(List<String> algos, Provider p,
boolean shouldThrow) throws Exception {
for (String a : algos) {
System.out.println("Testing " + (p != null ? p.getName() : "") +
": " + a + ", shouldThrow=" + shouldThrow);
if (shouldThrow) {
if (p == null) {
Utils.runAndCheckException(() -> KeyStore.getInstance(a),
KeyStoreException.class);
Utils.runAndCheckException(
() -> KeyStore.getInstance(new File(DIR, JKS_FN),
PASSWD),
KeyStoreException.class);
Utils.runAndCheckException(
() -> KeyStore.getInstance(new File(DIR, JKS_FN),
() -> {
return new KeyStore.PasswordProtection(PASSWD);
}),
KeyStoreException.class);
} else {
// with a provider argument
Utils.runAndCheckException(() -> KeyStore.getInstance(a, p),
KeyStoreException.class);
Utils.runAndCheckException(() -> KeyStore.getInstance(a,
p.getName()), KeyStoreException.class);
}
} else {
KeyStore k;
if (p == null) {
k = KeyStore.getInstance(a);
System.out.println("Got KeyStore w/ algo " + k.getType());
k = KeyStore.getInstance(new File(DIR, JKS_FN), PASSWD);
System.out.println("Got KeyStore w/ algo " + k.getType());
k = KeyStore.getInstance(new File(DIR, JKS_FN),
() -> {
return new KeyStore.PasswordProtection(PASSWD);
});
System.out.println("Got KeyStore w/ algo " + k.getType());
} else {
// with a provider argument
k = KeyStore.getInstance(a, p);
k = KeyStore.getInstance(a, p.getName());
System.out.println("Got KeyStore w/ algo " + k.getType());
}
}
}
}
public static void main(String[] args) throws Exception {
String propValue = args[0];
System.out.println("Setting Security Prop " + PROP_NAME + " = " +
propValue);
Security.setProperty(PROP_NAME, propValue);
boolean shouldThrow = Boolean.valueOf(args[1]);
List<String> algos = List.of("JKS", "jkS");
// test w/o provider
test(algos, null, shouldThrow);
// test w/ provider
Provider[] providers = Security.getProviders("KeyStore.JKS");
for (Provider p : providers) {
test(algos, p, shouldThrow);
}
}
}

View file

@ -0,0 +1,323 @@
/*
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PEMDecoder;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.time.Instant;
/*
* @test
* @bug 8048621 8133090 8167371 8236671 8374808
* @enablePreview
* @summary Test basic operations with keystores (jks, jceks, pkcs12)
* @author Yu-Ching Valerie PENG
*/
public class TestKeyStoreBasic {
private static final String PRIVATE_KEY_PKCS8_BASE64 = """
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpyz97liuWPDYcLH9TX8BiT78o
lCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgKmLhuczF3M9VIcWr+
JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz7leikne7KmclHvTfvFd0WDI7Gb9v
o4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXRv5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfF
e1DDsMg/KpKGiILYZ+g2qtVMZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e
+sO6H24w2F19AgMBAAECggEBAId/12187dO6wUPCjumuJA1QrrBnbKdKONyai36uoc1Od4s5QFj7
+hEIeS7rbGNYQuBvnkgusAbzkW0FIpxpHce3EJez/emux6pEOKoP77BwMt9gy+txyu0+BHi91FQg
AGvrnQDO5EYVY4Cz/WjOsJzKu8zVLg+DS0Toa2qRFwmUe9mVAXPNOCZ3Oae/Q6tCDsaINNw0fmjj
jn6uohPbS+n6xENG3FkQXB36getXy310xTGED2J27cmAQH6gLR6Kl2iROzNPbbpBqbuemI9kbcld
EwBS1jRfZWeaPstYA1niVrE9UgUBzemnoh4TDkG076sYthHMr5QFGjPswnwtJ4ECgYEA0sURQ5+v
baH4tdaemI3qpnknXTlzSpuZZmAoyvY0Id0mlduwKwmZ3Y5989wHfnnhFfyNO4IkTKjI2Wp97qP5
4eqUNpA7FtNU7KUzMcFDTtwtNZuRYMrKlqo2lLbA+gVrAYpYZFL4b7tcwtX4DnYorDsmude6W8sG
4Mx2VdFJC9UCgYEAzjsdXCYH5doWUHb0dvn9ID7IikffEMRM720MRjrnnnVbpzx6ACntkPDNZg7p
TRE/mx7iBz81ZaUWE+V0wd0JvCHEdpAz3mksyvDFhU4Bgs6xzf2pSul5muhsx3hHcvvPezz5Bnxs
faJlzkxfwotyGmvWN15GA/pyfsZjsbbTpwkCgYAO6NnbysQCIV8SnegCKqfatt9N/O5m7LLhRxQb
p2bwrlC4cZ34rWkw/w9x3LK7A6wkfgUPnJkswxPSLXJTG05l6M4rPfCwIKr1Qopojp9QSMr569NQ
4YeLOOc7heIIzbFQHpU6I5Rncv2Q2sn9W+ZsqJKIuvX34FjQNiZ406EzMQKBgHSxOGS61D84DuZK
2Ps1awhC3kB4eHzJRms3vflDPWoJJ+pSKwpKrzUTPHXiPBqyhtYkPGszVeiE6CAr9sv3YZnFVaBs
6hyQUJsob+uE/w/gGvXe8VsFDx0bJOodYfhrCbTHBHWqE81nBcocpxayxsayfAzqWB3KKd0YLrMR
K2PZAoGAcZa8915R2m0KZ6HVJUt/JDR85jCbN71kcVDFY2XSFkOJvOdFoHNfRckfLzjq9Y2MSSTV
+QDWbDo2doUQCejJUTaN8nP79tfyir24X5uVPvQaeVoGTKYb+LfUqK0F60lStmjuddIGSZH55y3v
+9XjmxbVERtd1lqgQg3VlmKlEXY=
-----END PRIVATE KEY-----
""";
/*
* Certificate:
* Data:
* Version: 3 (0x2)
* Serial Number: 7 (0x7)
* Signature Algorithm: sha512WithRSAEncryption
* Issuer: CN=Root
* Validity
* Not Before: Sep 1 18:03:59 2015 GMT
* Not After : Jan 17 18:03:59 2043 GMT
* Subject: CN=EE
*/
private static final String CERTIFICATE = ""
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDHTCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAPMQ0wCwYDVQQDDARSb290\n"
+ "MB4XDTE1MDkwMTE4MDM1OVoXDTQzMDExNzE4MDM1OVowDTELMAkGA1UEAwwCRUUw\n"
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyz97liuWPDYcLH9TX8Bi\n"
+ "T78olCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgK\n"
+ "mLhuczF3M9VIcWr+JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz\n"
+ "7leikne7KmclHvTfvFd0WDI7Gb9vo4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXR\n"
+ "v5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfFe1DDsMg/KpKGiILYZ+g2qtVM\n"
+ "ZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e+sO6H24w2F19\n"
+ "AgMBAAGjgYUwgYIwNAYDVR0fBC0wKzApoCegJYYjbGRhcDovL2xkYXAuaG9zdC5m\n"
+ "b3IuY3JsZHAvbWFpbi5jcmwwSgYIKwYBBQUHAQEEPjA8MDoGCCsGAQUFBzAChi5s\n"
+ "ZGFwOi8vbGRhcC5ob3N0LmZvci5haWEvZGM9Um9vdD9jQUNlcnRpZmljYXRlMA0G\n"
+ "CSqGSIb3DQEBDQUAA4IBAQBWDfZHpuUx0yn5d3+BuztFqoks1MkGdk+USlH0TB1/\n"
+ "gWWBd+4S4PCKlpSur0gj2rMW4fP5HQfNlHci8JV8/bG4KuKRAXW56dg1818Hl3pc\n"
+ "iIrUSRn8uUjH3p9qb+Rb/u3mmVQRyJjN2t/zceNsO8/+Dd808OB9aEwGs8lMT0nn\n"
+ "ZYaaAqYz1GIY/Ecyx1vfEZEQ1ljo6i/r70C3igbypBUShxSiGsleiVTLOGNA+MN1\n"
+ "/a/Qh0bkaQyTGqK3bwvzzMeQVqWu2EWTBD/PmND5ExkpRICdv8LBVXfLnpoBr4lL\n"
+ "hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY\n"
+ "-----END CERTIFICATE-----\n";
private static final char[] PASSWD2 = new char[] {
'b', 'o', 'r', 'e', 'd'
};
private static final char[] PASSWDK = "cannot be null"
.toCharArray();
private static final String[] KS_Type = {
"jks", "jceks", "pkcs12", "PKCS11KeyStore"
};
private static final String[] PROVIDERS = {
"SUN", "SunJCE", "SunJSSE"
};
private static final String ALIAS_HEAD = "test";
private static final String CRYPTO_ALG = "PBEWithHmacSHA256AndAES_128";
public static void main(String args[]) throws Exception {
TestKeyStoreBasic jstest = new TestKeyStoreBasic();
jstest.run();
}
public void run() throws Exception {
for (String provider : PROVIDERS) {
runTest(provider);
System.out.println("Test with provider " + provider + " passed");
}
}
public void runTest(String provider) throws Exception {
PEMDecoder pemDecoder = PEMDecoder.of();
PrivateKey privateKey = pemDecoder.decode(PRIVATE_KEY_PKCS8_BASE64, PrivateKey.class);
Certificate cert = pemDecoder.decode(CERTIFICATE, X509Certificate.class);
int numEntries = 5;
String type = null;
for (int i = 0; i < PROVIDERS.length; i++) {
if (provider.compareTo(PROVIDERS[i]) == 0) {
type = KS_Type[i];
break;
}
}
System.out.printf("Test %s provider and %s keystore%n", provider, type);
KeyStore ks = KeyStore.getInstance(type, provider);
KeyStore ks2 = KeyStore.getInstance(type, ks.getProvider().getName());
// create an empty key store
ks.load(null, null);
// unit test - test with null password
try {
ks.setKeyEntry(ALIAS_HEAD, privateKey, null,
new Certificate[] { cert });
} catch (KeyStoreException e) {
if (!e.getMessage().contains("password can\'t be null")) {
throw new RuntimeException("Unexpected message:" + e.getMessage());
}
// expected
}
// store the secret keys
for (int j = 0; j < numEntries; j++) {
ks.setKeyEntry(ALIAS_HEAD + j, privateKey, PASSWDK,
new Certificate[] { cert });
}
// initialize the 2nd key store object with the 1st one
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ks.store(baos, PASSWDK);
byte[] bArr = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bArr);
ks2.load(bais, null);
// check 2nd key store type
checkType(ks2, type);
// check the existing aliases for the 2nd key store
checkAlias(ks2, numEntries);
// compare the creation date of the 2 key stores for all aliases
compareCreationDate(ks, ks2, numEntries);
compareCreationInstant(ks, ks2, numEntries);
// remove the last entry from the 2nd key store
numEntries--;
ks2.deleteEntry(ALIAS_HEAD + numEntries);
// re-initialize the 1st key store with the 2nd key store
baos.reset();
ks2.store(baos, PASSWD2);
bais = new ByteArrayInputStream(baos.toByteArray());
try {
// expect an exception since the password is incorrect
ks.load(bais, PASSWDK);
throw new RuntimeException(
"ERROR: passed the loading with incorrect password");
} catch (IOException ex) {
System.out.println("Expected exception: " + ex);
if (!causedBy(ex, UnrecoverableKeyException.class)) {
ex.printStackTrace(System.out);
throw new RuntimeException("Unexpected cause");
}
System.out.println("Expected cause: "
+ UnrecoverableKeyException.class.getName());
bais.reset();
ks.load(bais, PASSWD2);
bais.reset();
ks.load(bais, null);
}
// check key store type
checkType(ks, type);
// check the existing aliases
checkAlias(ks, numEntries);
// compare the creation date of the 2 key stores for all aliases
compareCreationDate(ks, ks2, numEntries);
compareCreationInstant(ks, ks2, numEntries);
// check setEntry/getEntry with a password protection algorithm
if ("PKCS12".equalsIgnoreCase(ks.getType())) {
System.out.println(
"Skipping the setEntry/getEntry check for PKCS12 keystore...");
return;
}
String alias = ALIAS_HEAD + ALIAS_HEAD;
KeyStore.PasswordProtection pw =
new KeyStore.PasswordProtection(PASSWD2, CRYPTO_ALG, null);
KeyStore.PrivateKeyEntry entry =
new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{ cert });
checkSetEntry(ks, alias, pw, entry);
ks.setEntry(alias, entry, new KeyStore.PasswordProtection(PASSWD2));
checkGetEntry(ks, alias, pw);
}
// check setEntry with a password protection algorithm
private void checkSetEntry(KeyStore ks, String alias,
KeyStore.PasswordProtection pw, KeyStore.Entry entry) throws Exception {
try {
ks.setEntry(alias, entry, pw);
throw new Exception(
"ERROR: expected KeyStore.setEntry to throw an exception");
} catch (KeyStoreException e) {
// ignore the expected exception
}
}
// check getEntry with a password protection algorithm
private void checkGetEntry(KeyStore ks, String alias,
KeyStore.PasswordProtection pw) throws Exception {
try {
ks.getEntry(alias, pw);
throw new Exception(
"ERROR: expected KeyStore.getEntry to throw an exception");
} catch (KeyStoreException e) {
// ignore the expected exception
}
}
// check key store type
private void checkType(KeyStore obj, String type) {
if (!obj.getType().equals(type)) {
throw new RuntimeException("ERROR: wrong key store type");
}
}
// check the existing aliases
private void checkAlias(KeyStore obj, int range) throws KeyStoreException {
for (int k = 0; k < range; k++) {
if (!obj.containsAlias(ALIAS_HEAD + k)) {
throw new RuntimeException("ERROR: alias (" + k
+ ") should exist");
}
}
}
// compare the creation dates - true if all the same
private void compareCreationDate(KeyStore o1, KeyStore o2, int range)
throws KeyStoreException {
String alias;
for (int k = 0; k < range; k++) {
alias = ALIAS_HEAD + k;
if (!o1.getCreationDate(alias).equals(o2.getCreationDate(alias))) {
throw new RuntimeException("ERROR: entry creation time (" + k
+ ") differs");
}
}
}
// compare the creation instants - true if all the same
private void compareCreationInstant(KeyStore o1, KeyStore o2, int range)
throws KeyStoreException {
String alias;
for (int k = 0; k < range; k++) {
alias = ALIAS_HEAD + k;
final Instant instant1 = o1.getCreationInstant(alias);
final Instant instant2 = o2.getCreationInstant(alias);
if (!(instant1.equals(instant2))) {
throw new RuntimeException("ERROR: entry creation time (" + k
+ ") differs Instants {"
+ instant1 + " - "
+ instant2 + "}");
}
}
}
// checks if an exception was caused by specified exception class
private static boolean causedBy(Exception e, Class klass) {
Throwable cause = e;
while ((cause = cause.getCause()) != null) {
if (cause.getClass().equals(klass)) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,124 @@
/*
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import static java.lang.System.out;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/*
* @test
* @bug 8048621
* @summary Test the basic operations of KeyStore entry, provided by SunJCE
* (jceks)
* @author Yu-Ching Valerie PENG
*/
public class TestKeyStoreEntry {
private static final char[] PASSWDK = new char[] {
't', 'e', 'r', 'c', 'e', 's'
};
private static final char[] PASSWDF = new String("guardian Angel")
.toCharArray();
private static final String[] KS_ALGOS = {
"DES", "DESede", "Blowfish", "AES"
};
private static final int NUM_ALGOS = KS_ALGOS.length;
private final SecretKey[] sks = new SecretKey[NUM_ALGOS];
TestKeyStoreEntry() throws Exception {
// generate secret keys which are to be stored in the jce
// key store object
KeyGenerator[] kgs = new KeyGenerator[NUM_ALGOS];
for (int i = 0; i < NUM_ALGOS; i++) {
kgs[i] = KeyGenerator.getInstance(KS_ALGOS[i], "SunJCE");
sks[i] = kgs[i].generateKey();
}
}
public static void main(String args[]) throws Exception {
TestKeyStoreEntry jstest = new TestKeyStoreEntry();
jstest.run();
}
public void run() throws Exception {
try (FileOutputStream fos = new FileOutputStream("jceks");
FileInputStream fis = new FileInputStream("jceks");) {
KeyStore ks = KeyStore.getInstance("jceks");
// create an empty key store
ks.load(null, null);
// store the secret keys
String aliasHead = new String("secretKey");
for (int j = 0; j < NUM_ALGOS; j++) {
ks.setKeyEntry(aliasHead + j, sks[j], PASSWDK, null);
}
// write the key store out to a file
ks.store(fos, PASSWDF);
// wipe clean the existing key store
for (int k = 0; k < NUM_ALGOS; k++) {
ks.deleteEntry(aliasHead + k);
}
if (ks.size() != 0) {
throw new RuntimeException("ERROR: re-initialization failed");
}
// reload the key store with the file
ks.load(fis, PASSWDF);
// check the integrity/validaty of the key store
Key temp = null;
String alias = null;
if (ks.size() != NUM_ALGOS) {
throw new RuntimeException("ERROR: wrong number of key"
+ " entries");
}
for (int m = 0; m < ks.size(); m++) {
alias = aliasHead + m;
temp = ks.getKey(alias, PASSWDK);
// compare the keys
if (!temp.equals(sks[m])) {
throw new RuntimeException("ERROR: key comparison (" + m
+ ") failed");
}
// check the type of key
if (ks.isCertificateEntry(alias) || !ks.isKeyEntry(alias)) {
throw new RuntimeException("ERROR: type identification ("
+ m + ") failed");
}
}
}
}
}

Binary file not shown.

View file

@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIF5DCCBMygAwIBAgIQGVCD3zqdD1ZMZZ/zLAPnQzANBgkqhkiG9w0BAQUFADCBvDELMAkGA1UE
BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
ZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29t
L3JwYSAoYykxMDE2MDQGA1UEAxMtVmVyaVNpZ24gQ2xhc3MgMyBJbnRlcm5hdGlvbmFsIFNlcnZl
ciBDQSAtIEczMB4XDTEyMDcxMDAwMDAwMFoXDTEzMDczMTIzNTk1OVowgbgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQHFA5SZWR3b29kIFNob3JlczEbMBkGA1UEChQS
T3JhY2xlIENvcnBvcmF0aW9uMRIwEAYDVQQLFAlHbG9iYWwgSVQxMzAxBgNVBAsUKlRlcm1zIG9m
IHVzZSBhdCB3d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNTEVMBMGA1UEAxQMKi5vcmFjbGUuY29t
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz/dOCGrWzPj62q0ZkF59Oj9Fli4wHAuX
U4/S0yBXF8j6K7TKWFTQkGZt3+08KUhmLm1CE1DbbyRJT292YNXYXunNaKdABob8kaBO/NESUOEJ
0SZh7fd0xCSJAAPiwOMrM5jLeb/dEpU6nP74Afrhu5ffvKdcvTRGguj9H2oVsisTK8Z1HsiiwcJG
JXcrjvdCZoPU4FHvK03XZPAqPHKNSaJOrux6kRIWYjQMlmL+qDOb0nNHa6gBdi+VqqJHJHeAM677
dcUd0jn2m2OWtUnrM3MJZQof7/z27RTdX5J8np0ChkUgm63biDgRZO7uZP0DARQ0I6lZMlrarT8/
sct3twIDAQABo4IB4jCCAd4wFwYDVR0RBBAwDoIMKi5vcmFjbGUuY29tMAkGA1UdEwQCMAAwCwYD
VR0PBAQDAgWgMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHFwMwKjAoBggrBgEFBQcCARYcaHR0cHM6
Ly93d3cudmVyaXNpZ24uY29tL3JwYTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwbgYI
KwYBBQUHAQwEYjBgoV6gXDBaMFgwVhYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUS2u5KJYGDLvQ
UjibKaxLB4shBRgwJhYkaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nbzEuZ2lmMHIGCCsG
AQUFBwEBBGYwZDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AudmVyaXNpZ24uY29tMDwGCCsGAQUF
BzAChjBodHRwOi8vc3ZyaW50bC1nMy1haWEudmVyaXNpZ24uY29tL1NWUkludGxHMy5jZXIwQQYD
VR0fBDowODA2oDSgMoYwaHR0cDovL3N2cmludGwtZzMtY3JsLnZlcmlzaWduLmNvbS9TVlJJbnRs
RzMuY3JsMB8GA1UdIwQYMBaAFNebfNgioBX33a1fzimbWMO8RgC1MA0GCSqGSIb3DQEBBQUAA4IB
AQAITRBlEo+qXLwCL53Db2BGnhDgnSomjne8aCmU7Yt4Kp91tzJdhNuaC/wwDuzD2dPJqzemae3s
wKiOXrmDQZDj9NNTdkrXHnCvDR4TpOynWe3zBa0bwKnV2cIRKcv482yV53u0kALyFZbagYPwOOz3
YJA/2SqdcDn9Ztc/ABQ1SkyXyA5j4LJdf2g7BtYrFxjy0RG6We2iM781WSB/9MCNKyHgiwd3KpLf
urdSKLzy1elNAyt1P3UHwBIIvZ6sJIr/eeELc54Lxt6PtQCXx8qwxYTYXWPXbLgKBHdebgrmAbPK
TfD69wysvjk6vwSHjmvaqB4R4WRcgkuT+1gxx+ve
-----END CERTIFICATE-----