55import java .io .FileInputStream ;
66import java .io .IOException ;
77import java .math .BigInteger ;
8+ import java .nio .charset .StandardCharsets ;
89import java .nio .file .Files ;
910import java .security .KeyFactory ;
1011import java .security .KeyStore ;
2526import java .util .Base64 ;
2627import java .util .List ;
2728import java .util .concurrent .atomic .AtomicInteger ;
29+ import java .util .regex .Matcher ;
30+ import java .util .regex .Pattern ;
2831
2932import static java .util .Objects .requireNonNull ;
3033
@@ -33,6 +36,9 @@ class KeyStoreBuilder {
3336 private static final String TYPE_CERTIFICATE = "X.509" ;
3437 private static final String ALGORITHM_PRIVATE_KEY = "RSA" ;
3538
39+ private static final Pattern PATTERN_PKCS1_PEM = Pattern .compile ("-----BEGIN RSA PRIVATE KEY-----(.*)-----END RSA PRIVATE KEY-----" );
40+ private static final Pattern PATTERN_PKCS8_PEM = Pattern .compile ("-----BEGIN PRIVATE KEY-----(.*)-----END PRIVATE KEY-----" );
41+
3642 private ProtectionParameter keyStoreProtection ;
3743 private File caCertFile ;
3844 private File privateKeyCertFile ;
@@ -65,17 +71,6 @@ KeyStoreBuilder withPrivateKeyCertFile(File privateKeyCertFile) {
6571 return this ;
6672 }
6773
68- /**
69- * Provide the private key file to use. It must be in {@code *.DER} format. If you have a *.PME private key, you can create it using
70- * {@code openssl}.
71- * <p>
72- * The required command looks like following:<br>
73- * <code>$ openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER</code>
74- * </p>
75- *
76- * @param privateKeyFile private key file in {@code *.DER} format (must not be {@code null}
77- * @return the {@link KeyStore} builder itself
78- */
7974 KeyStoreBuilder withPrivateKeyFile (File privateKeyFile ) {
8075 requireNonNull (privateKeyFile , "'privateKeyFile' must not be null." );
8176 if (!privateKeyFile .exists ()) {
@@ -132,6 +127,21 @@ private List<Certificate> createCertificatesFor(File certFile) {
132127 private PrivateKey createPrivateKeyFor (File privateKeyFile ) {
133128 try {
134129 byte [] bytes = Files .readAllBytes (privateKeyFile .toPath ());
130+ if (privateKeyFile .getName ().endsWith ("pem" )) {
131+ String content = new String (bytes , StandardCharsets .UTF_8 ).replaceAll ("\\ n" , "" );
132+
133+ Matcher pkcs1Matcher = PATTERN_PKCS1_PEM .matcher (content );
134+ if (pkcs1Matcher .find ()) {
135+ return createPrivateKeyFromPemPkcs1 (pkcs1Matcher .group (1 ));
136+ }
137+
138+ Matcher pkcs8Matcher = PATTERN_PKCS8_PEM .matcher (content );
139+ if (pkcs8Matcher .find ()) {
140+ return createPrivateKeyFromPemPkcs8 (pkcs8Matcher .group (1 ));
141+ }
142+
143+ throw new TaskwarriorKeyStoreException ("Could not detect key algorithm for '%s'." , privateKeyFile );
144+ }
135145 return createPrivateKeyFromPkcs8Der (bytes );
136146 } catch (IOException e ) {
137147 throw new TaskwarriorKeyStoreException (e , "Could not read private key of '%s' via input stream." , privateKeyFile );
0 commit comments