blob: 43af5200ee8c1fcd0787486b67c8e1ee90c1fbb0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package se.leap.bitmaskclient.base.utils;
import static android.util.Base64.encodeToString;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.spongycastle.util.encoders.Base64;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import de.blinkt.openvpn.core.NativeUtils;
public class PrivateKeyHelper {
public static final String TAG = PrivateKeyHelper.class.getSimpleName();
public static final String RSA = "RSA";
public static final String ED_25519 = "Ed25519";
public static final String ECDSA = "ECDSA";
public static final String RSA_KEY_BEGIN = "-----BEGIN RSA PRIVATE KEY-----\n";
public static final String RSA_KEY_END = "-----END RSA PRIVATE KEY-----";
public static final String EC_KEY_BEGIN = "-----BEGIN PRIVATE KEY-----\n";
public static final String EC_KEY_END = "-----END PRIVATE KEY-----";
public interface PrivateKeyHelperInterface {
@Nullable PrivateKey parsePrivateKeyFromString(String privateKeyString);
}
public static class DefaultPrivateKeyHelper implements PrivateKeyHelperInterface {
public PrivateKey parsePrivateKeyFromString(String privateKeyString) {
if (privateKeyString == null || privateKeyString.isBlank()) {
return null;
}
if (privateKeyString.contains(RSA_KEY_BEGIN)) {
return parseRsaKeyFromString(privateKeyString);
} else if (privateKeyString.contains(EC_KEY_BEGIN)) {
return parseECPrivateKey(privateKeyString);
} else {
return null;
}
}
private RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) {
RSAPrivateKey key;
try {
KeyFactory kf;
kf = KeyFactory.getInstance(RSA, "BC");
rsaKeyString = rsaKeyString.replaceFirst(RSA_KEY_BEGIN, "").replaceFirst(RSA_KEY_END, "");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString));
key = (RSAPrivateKey) kf.generatePrivate(keySpec);
} catch (InvalidKeySpecException | NoSuchAlgorithmException | NullPointerException |
NoSuchProviderException e) {
e.printStackTrace();
return null;
}
return key;
}
private PrivateKey parseECPrivateKey(String ecKeyString) {
String base64 = ecKeyString.replace(EC_KEY_BEGIN, "").replace(EC_KEY_END, "");
byte[] keyBytes = Base64.decode(base64);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
String errMsg;
try {
KeyFactory keyFactory = KeyFactory.getInstance(ED_25519, "BC");
return keyFactory.generatePrivate(keySpec);
} catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchProviderException e) {
errMsg = e.toString();
}
try {
KeyFactory keyFactory = KeyFactory.getInstance(ECDSA, "BC");
return keyFactory.generatePrivate(keySpec);
} catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchProviderException e) {
errMsg += "\n" + e.toString();
Log.e(TAG, errMsg);
}
return null;
}
}
public static String getPEMFormattedPrivateKey(PrivateKey key) throws NullPointerException {
if (key == null) {
throw new NullPointerException("Private key was null.");
}
String keyString = encodeToString(key.getEncoded(), android.util.Base64.DEFAULT);
if (key instanceof RSAPrivateKey) {
return (RSA_KEY_BEGIN + keyString + RSA_KEY_END);
} else {
return EC_KEY_BEGIN + keyString + EC_KEY_END;
}
}
private static PrivateKeyHelperInterface instance = new DefaultPrivateKeyHelper();
@VisibleForTesting
public PrivateKeyHelper(PrivateKeyHelperInterface helperInterface) {
if (!NativeUtils.isUnitTest()) {
throw new IllegalStateException("PrivateKeyHelper injected with PrivateKeyHelperInterface outside of an unit test");
}
instance = helperInterface;
}
public static @Nullable PrivateKey parsePrivateKeyFromString(String rsaKeyString) {
return instance.parsePrivateKeyFromString(rsaKeyString);
}
}
|