diff --git a/gradle.properties b/gradle.properties index 90db68b..9ffda0b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group = org.xbib name = net -version = 3.0.1 +version = 3.0.2 org.gradle.warning.mode = ALL diff --git a/net-security/src/main/java/org/xbib/net/security/PrivateKeyReader.java b/net-security/src/main/java/org/xbib/net/security/PrivateKeyReader.java index 0bec8ec..d0b0d96 100644 --- a/net-security/src/main/java/org/xbib/net/security/PrivateKeyReader.java +++ b/net-security/src/main/java/org/xbib/net/security/PrivateKeyReader.java @@ -1,8 +1,13 @@ package org.xbib.net.security; +import java.security.KeyPair; +import java.security.PublicKey; +import java.security.spec.KeySpec; import org.xbib.net.security.eddsa.EdDSAPrivateKey; +import org.xbib.net.security.eddsa.EdDSAPublicKey; import org.xbib.net.security.eddsa.spec.EdDSANamedCurveTable; import org.xbib.net.security.eddsa.spec.EdDSAPrivateKeySpec; +import org.xbib.net.security.eddsa.spec.EdDSAPublicKeySpec; import org.xbib.net.security.util.Asn1Object; import org.xbib.net.security.util.DerParser; import org.xbib.net.security.util.DerUtils; @@ -73,35 +78,87 @@ public class PrivateKeyReader { public PrivateKeyReader() { } - public PrivateKey readPrivateKey(InputStream inputStream, String password) + public KeySpec parse(InputStream inputStream, String password) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, NoSuchPaddingException, InvalidKeyException { Objects.requireNonNull(inputStream); byte[] key = inputStream.readAllBytes(); if (indexOf(key, BEGIN_PRIVATE_KEY,0, key.length) >= 0) { byte[] keyBytes = extract(key, BEGIN_PRIVATE_KEY, END_PRIVATE_KEY); - EncodedKeySpec keySpec = generateKeySpec(keyBytes, password != null ? password.toCharArray() : null); - return KeyFactory.getInstance("RSA").generatePrivate(keySpec); + return generateKeySpec(keyBytes, password != null ? password.toCharArray() : null); } if (indexOf(key, BEGIN_RSA_PRIVATE_KEY,0, key.length) >= 0) { byte[] keyBytes = extract(key, BEGIN_RSA_PRIVATE_KEY, END_RSA_PRIVATE_KEY); - RSAPrivateCrtKeySpec keySpec = getRSAKeySpec(keyBytes); - return KeyFactory.getInstance("RSA").generatePrivate(keySpec); + return getRSAKeySpec(keyBytes); } if (indexOf(key, BEGIN_DSA_PRIVATE_KEY,0, key.length) >= 0) { byte[] keyBytes = extract(key, BEGIN_DSA_PRIVATE_KEY, END_DSA_PRIVATE_KEY); - DSAPrivateKeySpec keySpec = getDSAKeySpec(keyBytes); - return KeyFactory.getInstance("DSA").generatePrivate(keySpec); + return getDSAKeySpec(keyBytes); } if (indexOf(key, BEGIN_EC_PRIVATE_KEY,0, key.length) >= 0) { byte[] keyBytes = extract(key, BEGIN_EC_PRIVATE_KEY, END_EC_PRIVATE_KEY); - ECPrivateKeySpec keySpec = getECKeySpec(keyBytes); - return KeyFactory.getInstance("EC").generatePrivate(keySpec); + return getECKeySpec(keyBytes); } if (indexOf(key, BEGIN_OPENSSH_PRIVATE_KEY,0, key.length) >= 0) { byte[] keyBytes = extract(key, BEGIN_OPENSSH_PRIVATE_KEY, END_OPENSSH_PRIVATE_KEY); byte[] sk = Arrays.copyOfRange(keyBytes, 0, 32); - return new EdDSAPrivateKey(new EdDSAPrivateKeySpec(sk, EdDSANamedCurveTable.getByName("Ed25519"))); + return new EdDSAPrivateKeySpec(sk, EdDSANamedCurveTable.getByName("Ed25519")); + } + throw new IOException("invalid PEM input stream"); + } + + public PrivateKey readPrivateKey(InputStream inputStream, String password) + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, + InvalidAlgorithmParameterException, NoSuchPaddingException, InvalidKeyException { + KeySpec keySpec = parse(inputStream, password); + if (keySpec instanceof EncodedKeySpec) { + return KeyFactory.getInstance("RSA").generatePrivate(keySpec); + } + if (keySpec instanceof RSAPrivateCrtKeySpec) { + return KeyFactory.getInstance("RSA").generatePrivate(keySpec); + } + if (keySpec instanceof DSAPrivateKeySpec) { + return KeyFactory.getInstance("DSA").generatePrivate(keySpec); + } + if (keySpec instanceof ECPrivateKeySpec) { + return KeyFactory.getInstance("EC").generatePrivate(keySpec); + } + if (keySpec instanceof EdDSAPrivateKeySpec) { + return new EdDSAPrivateKey((EdDSAPrivateKeySpec) keySpec); + } + throw new IOException("invalid PEM"); + } + + public KeyPair generateFrom(InputStream inputStream, String password) + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, + InvalidAlgorithmParameterException, NoSuchPaddingException, InvalidKeyException { + KeySpec keySpec = parse(inputStream, password); + PrivateKey privateKey = null; + PublicKey publicKey = null; + if (keySpec instanceof EncodedKeySpec) { + privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); + publicKey = KeyFactory.getInstance("RSA").generatePublic(keySpec); + } + if (keySpec instanceof RSAPrivateCrtKeySpec) { + privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); + publicKey = KeyFactory.getInstance("RSA").generatePublic(keySpec); + } + if (keySpec instanceof DSAPrivateKeySpec) { + privateKey = KeyFactory.getInstance("DSA").generatePrivate(keySpec); + publicKey = KeyFactory.getInstance("DSA").generatePublic(keySpec); + } + if (keySpec instanceof ECPrivateKeySpec) { + privateKey = KeyFactory.getInstance("EC").generatePrivate(keySpec); + publicKey = KeyFactory.getInstance("EC").generatePublic(keySpec); + } + if (keySpec instanceof EdDSAPrivateKeySpec) { + EdDSAPrivateKeySpec privateKeySpec = (EdDSAPrivateKeySpec) keySpec; + privateKey = new EdDSAPrivateKey(privateKeySpec); + EdDSAPublicKeySpec publicKeySpec = new EdDSAPublicKeySpec(privateKeySpec.getA(), privateKeySpec.getParams()); + publicKey = new EdDSAPublicKey(publicKeySpec); + } + if (publicKey != null && privateKey != null) { + return new KeyPair(publicKey, privateKey); } throw new IOException("invalid PEM"); } diff --git a/net-security/src/test/java/org/xbib/net/security/PrivateKeyReaderTest.java b/net-security/src/test/java/org/xbib/net/security/PrivateKeyReaderTest.java index 63949ab..3f76b95 100644 --- a/net-security/src/test/java/org/xbib/net/security/PrivateKeyReaderTest.java +++ b/net-security/src/test/java/org/xbib/net/security/PrivateKeyReaderTest.java @@ -8,6 +8,7 @@ import java.nio.charset.StandardCharsets; import java.security.PrivateKey; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class PrivateKeyReaderTest { diff --git a/net-security/src/test/java/org/xbib/net/security/ed25519/Ed25519KeyTest.java b/net-security/src/test/java/org/xbib/net/security/ed25519/Ed25519KeyTest.java new file mode 100644 index 0000000..09620e9 --- /dev/null +++ b/net-security/src/test/java/org/xbib/net/security/ed25519/Ed25519KeyTest.java @@ -0,0 +1,20 @@ +package org.xbib.net.security.ed25519; + +import java.nio.charset.StandardCharsets; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import org.junit.jupiter.api.Test; + +public class Ed25519KeyTest { + + @Test + public void generate() throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519"); + KeyPair kp = kpg.generateKeyPair(); + Signature sig = Signature.getInstance("Ed25519"); + sig.initSign(kp.getPrivate()); + sig.update("Hello Jörg".getBytes(StandardCharsets.UTF_8)); + byte[] s = sig.sign(); + } +}