test: tested loading ECDSA key pair from text
This commit is contained in:
@@ -0,0 +1,64 @@
|
|||||||
|
# KeyLoader
|
||||||
|
|
||||||
|
KeyLoader provides utility methods to load keys from pem-formatted key texts.
|
||||||
|
|
||||||
|
## ECDSA-based algorithm
|
||||||
|
|
||||||
|
### Generate key pair
|
||||||
|
|
||||||
|
#### Generate private key
|
||||||
|
|
||||||
|
Generate a private key by `genpkey` command provided by OpenSSL:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ec_private_key.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
The output of this command is a file called `ec_private_key.pem` and its content looks like the
|
||||||
|
following:
|
||||||
|
|
||||||
|
```text
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7
|
||||||
|
+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn
|
||||||
|
Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Generate public key by private key
|
||||||
|
|
||||||
|
Export public key from private key with `ec` command provided by OpenSSL:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
openssl ec -in ec_private_key.pem -pubout -out ec_public_key.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
The output of this command is a file called `ec_public_key.pem` and its content looks like the
|
||||||
|
following:
|
||||||
|
|
||||||
|
```text
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZAOxkWNouIIPKsdF1YgF1D/XD8Pa
|
||||||
|
ZyYNcH60ONRWjMqlQXozWMb2i7WphKxf8kopp42nzCflWQod+JQY+hM/EQ==
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Convert private key to EC formats which could be acceptable by Java
|
||||||
|
|
||||||
|
Java's `PKCS8EncodedKeySpec` requires the private key to be in PKCS#8 format, while OpenSSL by
|
||||||
|
default generates private keys in traditional PEM format. To convert the private key, run the
|
||||||
|
following command:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
openssl pkcs8 -topk8 -inform PEM -outform PEM -in ec_private_key.pem -out ec_private_key_pkcs8.pem -nocrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
The converted private key will look like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7
|
||||||
|
+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn
|
||||||
|
Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
```
|
||||||
@@ -55,12 +55,13 @@ public class EcKeyLoader implements KeyLoader {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise a key loader for EC-based algorithms.
|
* Initialise a key loader for EC-based algorithms.
|
||||||
*
|
|
||||||
* @throws NoSuchAlgorithmException if no {@code Provider} supports a {@code KeyFactorySpi}
|
|
||||||
* implementation for the specified algorithm
|
|
||||||
*/
|
*/
|
||||||
public EcKeyLoader() throws NoSuchAlgorithmException {
|
public EcKeyLoader() {
|
||||||
|
try {
|
||||||
this.keyFactory = KeyFactory.getInstance("EC");
|
this.keyFactory = KeyFactory.getInstance("EC");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new KeyLoadingException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,8 +77,8 @@ public class EcKeyLoader implements KeyLoader {
|
|||||||
try {
|
try {
|
||||||
// remove all unnecessary parts of the pem key text
|
// remove all unnecessary parts of the pem key text
|
||||||
pemKeyText = pemKeyText
|
pemKeyText = pemKeyText
|
||||||
.replaceAll("-----BEGIN EC PRIVATE KEY-----", "")
|
.replaceAll("-----BEGIN (EC )?PRIVATE KEY-----", "")
|
||||||
.replaceAll("-----END EC PRIVATE KEY-----", "")
|
.replaceAll("-----END (EC )?PRIVATE KEY-----", "")
|
||||||
.replaceAll("\n", "");
|
.replaceAll("\n", "");
|
||||||
var decodedKeyString = Base64.getDecoder().decode(pemKeyText);
|
var decodedKeyString = Base64.getDecoder().decode(pemKeyText);
|
||||||
var keySpec = new PKCS8EncodedKeySpec(decodedKeyString);
|
var keySpec = new PKCS8EncodedKeySpec(decodedKeyString);
|
||||||
@@ -106,8 +107,8 @@ public class EcKeyLoader implements KeyLoader {
|
|||||||
try {
|
try {
|
||||||
// remove all unnecessary parts of the pem key text
|
// remove all unnecessary parts of the pem key text
|
||||||
pemKeyText = pemKeyText
|
pemKeyText = pemKeyText
|
||||||
.replaceAll("-----BEGIN EC PUBLIC KEY-----", "")
|
.replaceAll("-----BEGIN (EC )?PUBLIC KEY-----", "")
|
||||||
.replaceAll("-----END EC PUBLIC KEY-----", "")
|
.replaceAll("-----END (EC )?PUBLIC KEY-----", "")
|
||||||
.replaceAll("\n", "");
|
.replaceAll("\n", "");
|
||||||
var keyBytes = Base64.getDecoder().decode(pemKeyText);
|
var keyBytes = Base64.getDecoder().decode(pemKeyText);
|
||||||
var spec = new X509EncodedKeySpec(keyBytes);
|
var spec = new X509EncodedKeySpec(keyBytes);
|
||||||
@@ -115,7 +116,7 @@ public class EcKeyLoader implements KeyLoader {
|
|||||||
if (key instanceof ECPublicKey publicKey) {
|
if (key instanceof ECPublicKey publicKey) {
|
||||||
return publicKey;
|
return publicKey;
|
||||||
} else {
|
} else {
|
||||||
throw new KeyLoadingException("Unable to load private key from pem-formatted key text.");
|
throw new KeyLoadingException("Unable to load public key from pem-formatted key text.");
|
||||||
}
|
}
|
||||||
} catch (InvalidKeySpecException e) {
|
} catch (InvalidKeySpecException e) {
|
||||||
throw new KeyLoadingException("Key spec is invalid.", e);
|
throw new KeyLoadingException("Key spec is invalid.", e);
|
||||||
|
|||||||
@@ -17,13 +17,27 @@
|
|||||||
|
|
||||||
package com.onixbyte.security;
|
package com.onixbyte.security;
|
||||||
|
|
||||||
|
import com.onixbyte.security.impl.EcKeyLoader;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class KeyPairLoaderTest {
|
public class KeyPairLoaderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
var keyLoader = new EcKeyLoader();
|
||||||
|
var privateKey = keyLoader.loadPrivateKey("""
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7
|
||||||
|
+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn
|
||||||
|
Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
""");
|
||||||
|
var publicKey = keyLoader.loadPublicKey("""
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZAOxkWNouIIPKsdF1YgF1D/XD8Pa
|
||||||
|
ZyYNcH60ONRWjMqlQXozWMb2i7WphKxf8kopp42nzCflWQod+JQY+hM/EQ==
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7
|
||||||
|
+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn
|
||||||
|
Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7
|
||||||
|
+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn
|
||||||
|
Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZAOxkWNouIIPKsdF1YgF1D/XD8Pa
|
||||||
|
ZyYNcH60ONRWjMqlQXozWMb2i7WphKxf8kopp42nzCflWQod+JQY+hM/EQ==
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
+1
@@ -43,6 +43,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.interfaces.ECPrivateKey;
|
import java.security.interfaces.ECPrivateKey;
|
||||||
import java.security.interfaces.ECPublicKey;
|
import java.security.interfaces.ECPublicKey;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|||||||
Reference in New Issue
Block a user