package org.bouncycastle.test.est;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.security.spec.ECGenParameterSpec;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.net.ssl.X509TrustManager;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.est.jcajce.JcaJceUtils;
import org.bouncycastle.util.test.SimpleTest;
import org.junit.Test;
public class TestKeyUsage
extends SimpleTest
{
private static int[] keyUsage = new int[]{
KeyUsage.digitalSignature,
KeyUsage.nonRepudiation,
KeyUsage.keyEncipherment,
KeyUsage.dataEncipherment,
KeyUsage.keyAgreement,
KeyUsage.keyCertSign,
KeyUsage.cRLSign,
KeyUsage.encipherOnly,
KeyUsage.decipherOnly
};
public static String[] keyUsageNames = new String[]{
"digitalSignature",
"nonRepudiation",
"keyEncipherment",
"dataEncipherment",
"keyAgreement",
"keyCertSign",
"cRLSign",
"encipherOnly",
"decipherOnly"
};
private static KeyPurposeId[] keyPurposeIds = new KeyPurposeId[]{
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_msSGC,
KeyPurposeId.id_kp_nsSGC,
KeyPurposeId.id_kp_clientAuth,
};
private static String[] KeyPurposeIDName = new String[]{
"id_kp_serverAuth",
"id_kp_msSGC",
"id_kp_nsSGC",
"id_kp_clientAuth"
};
public String getName()
{
return "TestKeyUsage";
}
public void performTest()
throws Exception
{
ESTTestUtils.runJUnit(TestKeyUsage.class);
}
public static void matrix()
throws Exception
{
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
//
// Permutate key usage indexes
//
ArrayList<List> keyUsages = new ArrayList<List>();
keyUsages.add(new ArrayList());
for (int a = 0; a < keyUsage.length; a++)
{
ArrayList<Integer> u = new ArrayList<Integer>();
keyUsages.add(u);
u.add(a);
}
for (int a = 0; a < keyUsage.length; a++)
{
ArrayList<Integer> u = new ArrayList<Integer>();
for (int b = 0; b < a; b++)
{
u.add(b);
}
if (u.size() > 1)
{
keyUsages.add(u);
}
}
//
// Permutate keyPurposes indexes
//
ArrayList<List<Integer>> keyPurposes = new ArrayList<List<Integer>>();
keyPurposes.add(new ArrayList<Integer>());
for (int a = 0; a < keyPurposeIds.length; a++)
{
ArrayList<Integer> u = new ArrayList<Integer>();
keyPurposes.add(u);
u.add(a);
}
for (int a = 0; a < keyPurposeIds.length; a++)
{
ArrayList<Integer> u = new ArrayList<Integer>();
for (int b = 0; b < a; b++)
{
u.add(b);
}
if (u.size() > 1)
{
keyPurposes.add(u);
}
}
FileWriter sw = new FileWriter("~/matrix.html");
PrintWriter pw = new PrintWriter(sw);
pw.println("<html><head><style>" +
"table.hovertable {\n" +
"\tfont-family: verdana,arial,sans-serif;\n" +
"\tfont-size:11px;\n" +
"\tcolor:#333333;\n" +
"\tborder-width: 1px;\n" +
"\tborder-color: #999999;\n" +
"\tborder-collapse: collapse;\n" +
"}\n" +
"table.hovertable th {\n" +
"\tbackground-color:#c3dde0;\n" +
"\tborder-width: 1px;\n" +
"\tpadding: 8px;\n" +
"\tborder-style: solid;\n" +
"\tborder-color: #a9c6c9;\n" +
"}\n" +
"table.hovertable tr {\n" +
"\tbackground-color:#d4e3e5;\n" +
"}\n" +
"table.hovertable td {\n" +
"\tborder-width: 1px;\n" +
"\tpadding: 8px;\n" +
"\tborder-style: solid;\n" +
"\tborder-color: #a9c6c9;\n" +
"}\n" +
"</style></head><body><div><table class=\"hovertable\">");
pw.println("<tr><th></th>");
for (List<Integer> x : keyUsages)
{
if (x.isEmpty())
{
pw.println("<th>null</th>");
}
else
{
pw.print("<th>");
for (Integer k : x)
{
pw.print(keyUsageNames[k]);
pw.println(" ");
}
pw.println("</th>");
}
}
pw.println("<tr>");
KeyUsage usage = null;
ASN1EncodableVector purposes = null;
for (List<Integer> y : keyPurposes)
{
pw.println("<tr>");
pw.print("<td>");
if (y.isEmpty())
{
pw.print("null");
purposes = null;
}
else
{
purposes = new ASN1EncodableVector();
for (Integer i : y)
{
if (keyPurposeIds[i] != null)
{
purposes.add(keyPurposeIds[i]);
pw.print(" " + KeyPurposeIDName[i]);
}
}
pw.print("</td>");
}
for (List<Integer> x : keyUsages)
{
//
// Assemble usage.
//
if (x.isEmpty())
{
usage = null;
}
else
{
int k = 0;
for (Integer i : x)
{
k |= keyUsage[i];
}
usage = new KeyUsage(k);
}
X509Certificate cert = makeCertificate(originalKeyPair, purposes, usage);
try
{
JcaJceUtils.validateServerCertUsage(cert);
pw.print("<td>Pass</td>");
}
catch (Exception ex)
{
assert ex instanceof CertificateException;
pw.print("<td>Fail</td>");
}
}
pw.println("</tr>");
}
pw.println("</table>");
pw.println("</div></body></html>");
pw.flush();
pw.close();
}
@Test
public void testWith_0()
throws Exception
{
//
// With no key usage and no extended key usage.
//
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
X509Certificate cert = makeCertificate(originalKeyPair, null, null);
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_1()
throws Exception
{
// With digitalSignature, and no extended key usage
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
X509Certificate cert = makeCertificate(originalKeyPair, null, new KeyUsage(KeyUsage.digitalSignature));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_2()
throws Exception
{
// With keyEncipherment and no extended key usage
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
X509Certificate cert = makeCertificate(originalKeyPair, null, new KeyUsage(KeyUsage.keyEncipherment));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_3()
throws Exception
{
// With digitalSignature and keyEncipherment and no extended key usage.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
X509Certificate cert = makeCertificate(originalKeyPair, null, new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_4()
throws Exception
{
// With digitalSignature, keyEncipherment amd keyAgreement no extended key usage.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
X509Certificate cert = makeCertificate(originalKeyPair, null, new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test(expected = CertificateException.class)
public void testCertUsage_5()
throws Exception
{
// With keyAgreement no extended key usage -- must fail.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
X509Certificate cert = makeCertificate(originalKeyPair, null, new KeyUsage(KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_6()
throws Exception
{
// Valid key usage with serverAuth extended key usage
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
ASN1EncodableVector purpose = new ASN1EncodableVector();
purpose.add(KeyPurposeId.id_kp_serverAuth);
X509Certificate cert = makeCertificate(
originalKeyPair,
purpose,
new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_7()
throws Exception
{
// Valid key usage with msSGC extended key usage.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
ASN1EncodableVector purpose = new ASN1EncodableVector();
purpose.add(KeyPurposeId.id_kp_msSGC);
X509Certificate cert = makeCertificate(
originalKeyPair,
purpose,
new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_8()
throws Exception
{
// Valid key usage with nsSGC extended key usage.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
ASN1EncodableVector purpose = new ASN1EncodableVector();
purpose.add(KeyPurposeId.id_kp_nsSGC);
X509Certificate cert = makeCertificate(
originalKeyPair,
purpose,
new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_9()
throws Exception
{
// Valid key usage with nsSGC extended key usage.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
ASN1EncodableVector purpose = new ASN1EncodableVector();
purpose.add(KeyPurposeId.id_kp_serverAuth);
purpose.add(KeyPurposeId.id_kp_msSGC);
purpose.add(KeyPurposeId.id_kp_nsSGC);
X509Certificate cert = makeCertificate(
originalKeyPair,
purpose,
new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test
public void testCertUsage_10()
throws Exception
{
// Valid key usage with nsSGC extended key usage.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
ASN1EncodableVector purpose = new ASN1EncodableVector();
purpose.add(KeyPurposeId.id_kp_serverAuth);
purpose.add(KeyPurposeId.id_kp_msSGC);
purpose.add(KeyPurposeId.id_kp_nsSGC);
purpose.add(KeyPurposeId.id_kp_clientAuth);
X509Certificate cert = makeCertificate(
originalKeyPair,
purpose,
new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
@Test(expected = CertificateException.class)
public void testCertUsage_11()
throws Exception
{
// Valid key usage with nsSGC extended key usage.
ESTTestUtils.ensureProvider();
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
kpg.initialize(ecGenSpec, new SecureRandom());
KeyPair originalKeyPair = kpg.generateKeyPair();
ASN1EncodableVector purpose = new ASN1EncodableVector();
purpose.add(KeyPurposeId.id_kp_clientAuth);
X509Certificate cert = makeCertificate(
originalKeyPair,
purpose,
new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyAgreement));
// Should not reject.
JcaJceUtils.validateServerCertUsage(cert);
}
// @Test
// public void testKeyEncipherment()
// throws Exception
// {
// X509Certificate cert = ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
// ESTServerUtils.makeRelativeToServerHome("/keyusage/KeyUsage-keyEnciph.pem")
// ));
//
// JcaJceUtils.validateServerCertUsage(cert);
//
// }
//
// @Test
// public void testCertPath()
// throws Exception
// {
//
// ESTTestUtils.ensureProvider();
//
// Set<TrustAnchor> ts = ESTTestUtils.toTrustAnchor(ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
// ESTServerUtils.makeRelativeToServerHome("/keyusage/bc_cacert.crt")
// )));
// X509TrustManager[] tm = JcaJceUtils.getCertPathTrustManager(ts, null);
//
// tm[0].checkServerTrusted(new X509Certificate[]{ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
// ESTServerUtils.makeRelativeToServerHome("/keyusage/KeyUsage-keyEnciph.pem")
// ))}, "");
//
// }
private static X509Certificate makeCertificate(KeyPair originalKeyPair, ASN1EncodableVector purposes, KeyUsage keyUsage)
throws Exception
{
X500NameBuilder builder = new X500NameBuilder();
builder.addRDN(BCStyle.C, "AU");
builder.addRDN(BCStyle.CN, "Bunyip Bluegum");
builder.addRDN(BCStyle.O, "Pudding Protectors");
builder.addRDN(BCStyle.L, "Victoria");
X500Name name = builder.build();
X509Certificate clientTLSCert = ESTTestUtils.createASignedCert("SHA256WITHECDSA",
name,
SubjectPublicKeyInfo.getInstance(originalKeyPair.getPublic().getEncoded()),
name,
originalKeyPair.getPrivate(),
1, purposes, keyUsage
);
return clientTLSCert;
}
}