1 package com.atlassian.asap.core.keys;
2
3
4 import com.atlassian.asap.api.exception.CannotRetrieveKeyException;
5 import com.atlassian.asap.core.SecurityProvider;
6 import org.apache.commons.io.IOUtils;
7 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
8 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
9 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
10 import org.bouncycastle.openssl.PEMParser;
11 import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
12
13 import java.io.IOException;
14 import java.io.Reader;
15 import java.io.StringReader;
16 import java.nio.charset.StandardCharsets;
17 import java.security.KeyFactory;
18 import java.security.NoSuchAlgorithmException;
19 import java.security.PrivateKey;
20 import java.security.Provider;
21 import java.security.PublicKey;
22 import java.security.spec.InvalidKeySpecException;
23 import java.security.spec.PKCS8EncodedKeySpec;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class DataUriKeyReader implements KeyReader {
45 public static final String DATA_URI_PKCS8_HEADER = "data:application/pkcs8;";
46 public static final String DATA_URI_PEM_HEADER = "data:application/x-pem-file;";
47
48 private final Provider provider;
49
50 public DataUriKeyReader() {
51 this(SecurityProvider.getProvider());
52 }
53
54 public DataUriKeyReader(Provider provider) {
55 this.provider = provider;
56 }
57
58 @Override
59 public PrivateKey readPrivateKey(Reader reader) throws CannotRetrieveKeyException {
60 try {
61 String dataUri = IOUtils.toString(reader);
62 if (dataUri.startsWith(DATA_URI_PKCS8_HEADER)) {
63 byte[] keyData = DataUriUtil.getKeyData(dataUri);
64 AlgorithmIdentifier algorithmIdentifier = PrivateKeyInfo.getInstance(keyData).getPrivateKeyAlgorithm();
65 KeyFactory keyFactory = KeyFactory.getInstance(algorithmIdentifier.getAlgorithm().getId(), provider);
66 return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyData));
67 } else {
68 throw new CannotRetrieveKeyException("Data uri could not be parsed due to unexpected prefix");
69 }
70 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
71 throw new CannotRetrieveKeyException("Error reading private key, unknown key type", e);
72 } catch (IOException | IllegalArgumentException e) {
73 throw new CannotRetrieveKeyException("Error reading private key", e);
74 }
75 }
76
77 @Override
78 public PublicKey readPublicKey(Reader reader) throws CannotRetrieveKeyException {
79 try {
80 String dataUri = IOUtils.toString(reader);
81 if (dataUri.startsWith(DATA_URI_PEM_HEADER)) {
82 byte[] keyData = DataUriUtil.getKeyData(dataUri);
83 PEMParser pemParser = new PEMParser(new StringReader(new String(keyData, StandardCharsets.US_ASCII)));
84 SubjectPublicKeyInfo pub = SubjectPublicKeyInfo.getInstance(pemParser.readObject());
85 JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(provider);
86 return converter.getPublicKey(pub);
87 } else {
88 throw new CannotRetrieveKeyException("Data uri could not be parsed due to unexpected prefix");
89 }
90 } catch (IOException | IllegalArgumentException e) {
91 throw new CannotRetrieveKeyException("Error reading Public key", e);
92 }
93 }
94 }