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);
}
}
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);
}
}
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);
}
}
}
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()));
}
}
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);
}
Aggregations