Search in sources :

Example 1 with KeyStoreException

use of com.radixdlt.crypto.exception.KeyStoreException in project radixdlt by radixdlt.

the class RadixKeyStore method readKeyPair.

/**
 * Reads a key pair with the specified name from the key store.
 *
 * @param name The name of the key in the key store. If no key with the given name is present, it
 *     will be created if specified, otherwise a {@link KeyStoreException} will be raised.
 * @param create Set to {@code true} to create a new random key if the specified key does not
 *     exist in the store.
 * @return The {@link ECKeyPair} read from the key store
 * @throws KeyStoreException If an error occurs while reading the key
 * @throws PrivateKeyException If an error occurs while validating the private key
 * @throws PublicKeyException If an error occurs while computing the public key
 */
public ECKeyPair readKeyPair(String name, boolean create) throws KeyStoreException, PrivateKeyException, PublicKeyException {
    try {
        var entry = this.keyStore.getEntry(name, emptyPassword);
        if (entry == null) {
            if (create) {
                var newKeyPair = ECKeyPair.generateNew();
                writeKeyPair(name, newKeyPair);
                return newKeyPair;
            } else {
                throw new KeyStoreException("No such entry: " + name);
            }
        } else {
            return processEntry(name, entry);
        }
    } catch (GeneralSecurityException | IOException e) {
        throw new KeyStoreException("Key store error while reading key", e);
    }
}
Also used : GeneralSecurityException(java.security.GeneralSecurityException) KeyStoreException(com.radixdlt.crypto.exception.KeyStoreException) IOException(java.io.IOException)

Example 2 with KeyStoreException

use of com.radixdlt.crypto.exception.KeyStoreException in project radixdlt by radixdlt.

the class RadixKeyStore method selfSignedCert.

/**
 * Creates a self-signed certificate from the specified key-pair.
 *
 * <p>The validity period for the certificate extends from the current local clock time for the
 * specified validity period in years.
 *
 * @param keyPair The key-pair to create the self-signed certificate for.
 * @param validityYears Years The validity period in years.
 * @param subjectDN The key's distinguished subject name.
 * @return A self-signed certificate
 * @throws KeyStoreException If an error occurs while building the certificate
 * @throws IOException If an I/O error occurs while building the certificate
 */
@VisibleForTesting
static Certificate selfSignedCert(KeyPair keyPair, int validityYears, String subjectDN) throws KeyStoreException, IOException {
    X500Name dnName = new X500Name(subjectDN);
    LocalDateTime startDate = LocalDateTime.now();
    LocalDateTime endDate = startDate.plusYears(validityYears);
    BigInteger certSerialNumber = BigInteger.valueOf(toDate(startDate).getTime());
    var certBuilder = new JcaX509v3CertificateBuilder(dnName, certSerialNumber, toDate(startDate), toDate(endDate), dnName, keyPair.getPublic());
    BasicConstraints basicConstraints = new BasicConstraints(true);
    certBuilder.addExtension(OID_BASIC_CONSTRAINTS, true, basicConstraints);
    try {
        ContentSigner contentSigner = new JcaContentSignerBuilder(CERT_SIGNATURE_ALG).build(keyPair.getPrivate());
        return new JcaX509CertificateConverter().getCertificate(certBuilder.build(contentSigner));
    } catch (OperatorCreationException | CertificateException ex) {
        throw new KeyStoreException("Error creating certificate", ex);
    }
}
Also used : LocalDateTime(java.time.LocalDateTime) JcaContentSignerBuilder(org.bouncycastle.operator.jcajce.JcaContentSignerBuilder) ContentSigner(org.bouncycastle.operator.ContentSigner) CertificateException(java.security.cert.CertificateException) X500Name(org.bouncycastle.asn1.x500.X500Name) KeyStoreException(com.radixdlt.crypto.exception.KeyStoreException) JcaX509CertificateConverter(org.bouncycastle.cert.jcajce.JcaX509CertificateConverter) JcaX509v3CertificateBuilder(org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder) BigInteger(java.math.BigInteger) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) BasicConstraints(org.bouncycastle.asn1.x509.BasicConstraints) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 3 with KeyStoreException

use of com.radixdlt.crypto.exception.KeyStoreException in project radixdlt by radixdlt.

the class RadixKeyStore method writeKeyPair.

/**
 * Writes the specified key pair identified by the specified name to the key store.
 *
 * <p><b>Implementation note:</b><br>
 * Note that this method will create a new file and set it's permissions to just {@link
 * PosixFilePermission#OWNER_READ} and {@link PosixFilePermission#OWNER_WRITE} on Posix
 * filesystems.
 *
 * @param name The name the key will have in the key store. If a key already exists with this
 *     name, it will be overwritten.
 * @param ecKeyPair The {@link ECKeyPair} to write to the store.
 * @throws KeyStoreException If an error occurs writing the key
 * @throws IOException If an error occurs persisting the key store
 */
public void writeKeyPair(String name, ECKeyPair ecKeyPair) throws KeyStoreException, IOException {
    byte[] encodedPrivKey = null;
    try {
        encodedPrivKey = encodePrivKey(ecKeyPair.getPrivateKey());
        var pki = PrivateKeyInfo.getInstance(encodedPrivKey);
        // Note that while PrivateKey objects are in theory destroyable,
        // the BCEC implementation has not yet been updated to accommodate.
        var privateKey = BouncyCastleProvider.getPrivateKey(pki);
        var encodedPubKey = encodePubKey(ecKeyPair.getPublicKey().getBytes());
        var spki = SubjectPublicKeyInfo.getInstance(encodedPubKey);
        var publicKey = BouncyCastleProvider.getPublicKey(spki);
        var keyPair = new KeyPair(publicKey, privateKey);
        Certificate[] chain = { selfSignedCert(keyPair, 1000, DEFAULT_SUBJECT_DN) };
        KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry(privateKey, chain);
        this.keyStore.setEntry(name, pke, emptyPassword);
        writeKeyStore(this.file, this.keyStore, this.storePassword);
    } catch (GeneralSecurityException ex) {
        throw new KeyStoreException("Error while writing key", ex);
    } finally {
        if (encodedPrivKey != null) {
            Arrays.fill(encodedPrivKey, (byte) 0);
        }
    }
}
Also used : KeyPair(java.security.KeyPair) GeneralSecurityException(java.security.GeneralSecurityException) KeyStoreException(com.radixdlt.crypto.exception.KeyStoreException) KeyStore(java.security.KeyStore) Certificate(java.security.cert.Certificate)

Example 4 with KeyStoreException

use of com.radixdlt.crypto.exception.KeyStoreException in project radixdlt by radixdlt.

the class RadixKeyStore method processEntry.

private ECKeyPair processEntry(String name, Entry entry) throws KeyStoreException, PrivateKeyException, IOException, PublicKeyException {
    // Still do the check here anyway.
    if (entry instanceof KeyStore.PrivateKeyEntry) {
        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) entry;
        // Note that while PrivateKey objects are in theory destroyable,
        // the BCEC implementation has not yet been updated to accommodate.
        PrivateKey pk = pkEntry.getPrivateKey();
        byte[] encoded = pk.getEncoded();
        try {
            return ECKeyPair.fromPrivateKey(decodePrivKey(encoded));
        } finally {
            Arrays.fill(encoded, (byte) 0);
        }
    } else {
        throw new KeyStoreException(String.format("Entry %s is not a private key: %s", name, entry.getClass()));
    }
}
Also used : ECPrivateKey(org.bouncycastle.asn1.sec.ECPrivateKey) PrivateKey(java.security.PrivateKey) KeyStoreException(com.radixdlt.crypto.exception.KeyStoreException) KeyStore(java.security.KeyStore)

Example 5 with KeyStoreException

use of com.radixdlt.crypto.exception.KeyStoreException in project radixdlt by radixdlt.

the class RadixKeyStore method decodePrivKey.

/**
 * Decodes the specified ASN.1 encoded <a
 * href="https://tools.ietf.org/html/rfc5208#section-5">Private Key Info</a> structure into a raw
 * 256-bit secp256k1 private key.
 *
 * @param encoded The encoded private key
 * @return The raw {@link ECKeyPair#BYTES} length private key.
 * @throws IOException If an error occurred decoding the ASN.1 key.
 * @throws KeyStoreException If the decoded key is not for the secp256k1 curve.
 */
private static byte[] decodePrivKey(byte[] encoded) throws IOException, KeyStoreException {
    PrivateKeyInfo pki = PrivateKeyInfo.getInstance(encoded);
    ECPrivateKey ecpk = ECPrivateKey.getInstance(pki.parsePrivateKey());
    ASN1Primitive params = ecpk.getParameters();
    if (!OID_SECP256K1_CURVE.equals(params)) {
        throw new KeyStoreException("Unknown curve: " + params.toString());
    }
    return ECKeyUtils.adjustArray(ecpk.getKey().toByteArray(), ECKeyPair.BYTES);
}
Also used : ECPrivateKey(org.bouncycastle.asn1.sec.ECPrivateKey) KeyStoreException(com.radixdlt.crypto.exception.KeyStoreException) ASN1Primitive(org.bouncycastle.asn1.ASN1Primitive) PrivateKeyInfo(org.bouncycastle.asn1.pkcs.PrivateKeyInfo)

Aggregations

KeyStoreException (com.radixdlt.crypto.exception.KeyStoreException)7 GeneralSecurityException (java.security.GeneralSecurityException)4 KeyStore (java.security.KeyStore)3 IOException (java.io.IOException)2 KeyPair (java.security.KeyPair)2 PrivateKey (java.security.PrivateKey)2 Certificate (java.security.cert.Certificate)2 ECPrivateKey (org.bouncycastle.asn1.sec.ECPrivateKey)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 TestSetupUtils (com.radixdlt.TestSetupUtils)1 PrivateKeyException (com.radixdlt.crypto.exception.PrivateKeyException)1 PublicKeyException (com.radixdlt.crypto.exception.PublicKeyException)1 File (java.io.File)1 FileNotFoundException (java.io.FileNotFoundException)1 BigInteger (java.math.BigInteger)1 Files (java.nio.file.Files)1 KeyPairGenerator (java.security.KeyPairGenerator)1 SecureRandom (java.security.SecureRandom)1 CertificateException (java.security.cert.CertificateException)1 ECGenParameterSpec (java.security.spec.ECGenParameterSpec)1