blob: 3b3ddbe1c050f47674e8025df395dfe6dbbf59ea [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.accumulo.test.util;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class CertUtilsTest {
private static final String KEYSTORE_TYPE = "JKS";
private static final String PASSWORD = "CertUtilsTestPassword";
private static final char[] PASSWORD_CHARS = PASSWORD.toCharArray();
private static final String RDN_STRING = "o=Apache Accumulo,cn=CertUtilsTest";
@Rule
public TemporaryFolder folder =
new TemporaryFolder(new File(System.getProperty("user.dir") + "/target"));
private CertUtils getUtils() {
return new CertUtils(KEYSTORE_TYPE, RDN_STRING, "RSA", 4096, "SHA512WITHRSA");
}
@Test
public void createSelfSigned() throws Exception {
CertUtils certUtils = getUtils();
File keyStoreFile = new File(folder.getRoot(), "selfsigned.jks");
certUtils.createSelfSignedCert(keyStoreFile, "test", PASSWORD);
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(keyStoreFile)) {
keyStore.load(fis, PASSWORD_CHARS);
}
Certificate cert = CertUtils.findCert(keyStore);
cert.verify(cert.getPublicKey()); // throws exception if it can't be verified
}
@Test
public void createPublicSelfSigned() throws Exception {
CertUtils certUtils = getUtils();
File rootKeyStoreFile = new File(folder.getRoot(), "root.jks");
certUtils.createSelfSignedCert(rootKeyStoreFile, "test", PASSWORD);
File publicKeyStoreFile = new File(folder.getRoot(), "public.jks");
certUtils.createPublicCert(publicKeyStoreFile, "test", rootKeyStoreFile.getAbsolutePath(),
PASSWORD, "");
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(publicKeyStoreFile)) {
keyStore.load(fis, new char[0]);
}
try {
CertUtils.findPrivateKey(keyStore, PASSWORD_CHARS);
fail("expected not to find private key in keystore");
} catch (KeyStoreException e) {
assertTrue(e.getMessage().contains("private key"));
}
Certificate cert = CertUtils.findCert(keyStore);
cert.verify(cert.getPublicKey()); // throws exception if it can't be verified
}
@Test
public void createSigned() throws Exception {
CertUtils certUtils = getUtils();
File rootKeyStoreFile = new File(folder.getRoot(), "root.jks");
certUtils.createSelfSignedCert(rootKeyStoreFile, "test", PASSWORD);
File signedKeyStoreFile = new File(folder.getRoot(), "signed.jks");
certUtils.createSignedCert(signedKeyStoreFile, "test", PASSWORD,
rootKeyStoreFile.getAbsolutePath(), PASSWORD);
KeyStore rootKeyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(rootKeyStoreFile)) {
rootKeyStore.load(fis, PASSWORD_CHARS);
}
Certificate rootCert = CertUtils.findCert(rootKeyStore);
KeyStore signedKeyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(signedKeyStoreFile)) {
signedKeyStore.load(fis, PASSWORD_CHARS);
}
Certificate signedCert = CertUtils.findCert(signedKeyStore);
try {
signedCert.verify(signedCert.getPublicKey());
fail("signed cert should not be able to verify itself");
} catch (SignatureException e) {
// expected
}
signedCert.verify(rootCert.getPublicKey()); // throws exception if it can't be verified
}
@Test
public void publicOnlyVerfication() throws Exception {
// this approximates the real life scenario. the client will only have the public key of each
// cert (the root made by us as below, but the signed cert extracted by the SSL transport)
CertUtils certUtils = getUtils();
File rootKeyStoreFile = new File(folder.getRoot(), "root.jks");
certUtils.createSelfSignedCert(rootKeyStoreFile, "test", PASSWORD);
File publicRootKeyStoreFile = new File(folder.getRoot(), "publicroot.jks");
certUtils.createPublicCert(publicRootKeyStoreFile, "test", rootKeyStoreFile.getAbsolutePath(),
PASSWORD, "");
File signedKeyStoreFile = new File(folder.getRoot(), "signed.jks");
certUtils.createSignedCert(signedKeyStoreFile, "test", PASSWORD,
rootKeyStoreFile.getAbsolutePath(), PASSWORD);
File publicSignedKeyStoreFile = new File(folder.getRoot(), "publicsigned.jks");
certUtils.createPublicCert(publicSignedKeyStoreFile, "test",
signedKeyStoreFile.getAbsolutePath(), PASSWORD, "");
KeyStore rootKeyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(publicRootKeyStoreFile)) {
rootKeyStore.load(fis, new char[0]);
}
KeyStore signedKeyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(publicSignedKeyStoreFile)) {
signedKeyStore.load(fis, new char[0]);
}
Certificate rootCert = CertUtils.findCert(rootKeyStore);
Certificate signedCert = CertUtils.findCert(signedKeyStore);
try {
signedCert.verify(signedCert.getPublicKey());
fail("signed cert should not be able to verify itself");
} catch (SignatureException e) {
// expected
}
signedCert.verify(rootCert.getPublicKey()); // throws exception if it can't be verified
}
@Test
public void signingChain() throws Exception {
// no reason the keypair we generate for the tservers need to be able to sign anything,
// but this is a way to make sure the private and public keys created actually correspond.
CertUtils certUtils = getUtils();
File rootKeyStoreFile = new File(folder.getRoot(), "root.jks");
certUtils.createSelfSignedCert(rootKeyStoreFile, "test", PASSWORD);
File signedCaKeyStoreFile = new File(folder.getRoot(), "signedca.jks");
certUtils.createSignedCert(signedCaKeyStoreFile, "test", PASSWORD,
rootKeyStoreFile.getAbsolutePath(), PASSWORD);
File signedLeafKeyStoreFile = new File(folder.getRoot(), "signedleaf.jks");
certUtils.createSignedCert(signedLeafKeyStoreFile, "test", PASSWORD,
signedCaKeyStoreFile.getAbsolutePath(), PASSWORD);
KeyStore caKeyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(signedCaKeyStoreFile)) {
caKeyStore.load(fis, PASSWORD_CHARS);
}
Certificate caCert = CertUtils.findCert(caKeyStore);
KeyStore leafKeyStore = KeyStore.getInstance(KEYSTORE_TYPE);
try (FileInputStream fis = new FileInputStream(signedLeafKeyStoreFile)) {
leafKeyStore.load(fis, PASSWORD_CHARS);
}
Certificate leafCert = CertUtils.findCert(leafKeyStore);
leafCert.verify(caCert.getPublicKey()); // throws exception if it can't be verified
}
}