|
35 | 35 | import java.util.stream.Collectors;
|
36 | 36 |
|
37 | 37 | import org.springframework.core.convert.converter.Converter;
|
| 38 | +import org.springframework.lang.NonNull; |
38 | 39 | import org.springframework.util.Assert;
|
39 | 40 |
|
40 | 41 | /**
|
@@ -110,41 +111,18 @@ public static Converter<InputStream, RSAPrivateKey> pkcs8() {
|
110 | 111 | * return a {@link RSAPublicKey}.
|
111 | 112 | */
|
112 | 113 | public static Converter<InputStream, RSAPublicKey> x509() {
|
113 |
| - KeyFactory keyFactory = rsaFactory(); |
114 |
| - CertificateFactory certificateFactory = x509CertificateFactory(); |
| 114 | + X509PemDecoder pemDecoder = new X509PemDecoder(rsaFactory()); |
| 115 | + X509CertificateDecoder certDecoder = new X509CertificateDecoder(x509CertificateFactory()); |
115 | 116 | return (source) -> {
|
116 | 117 | List<String> lines = readAllLines(source);
|
117 |
| - Assert.isTrue( |
118 |
| - !lines.isEmpty() |
119 |
| - && (lines.get(0).startsWith(X509_PEM_HEADER) || lines.get(0).startsWith(X509_CERT_HEADER)), |
| 118 | + Assert.notEmpty(lines, "Input stream is empty"); |
| 119 | + String encodingHint = lines.get(0); |
| 120 | + Converter<List<String>, RSAPublicKey> decoder = encodingHint.startsWith(X509_PEM_HEADER) ? pemDecoder |
| 121 | + : encodingHint.startsWith(X509_CERT_HEADER) ? certDecoder : null; |
| 122 | + Assert.notNull(decoder, |
120 | 123 | "Key is not in PEM-encoded X.509 format or a valid X.509 certificate, please check that the header begins with "
|
121 | 124 | + X509_PEM_HEADER + " or " + X509_CERT_HEADER);
|
122 |
| - StringBuilder base64Encoded = new StringBuilder(); |
123 |
| - for (String line : lines) { |
124 |
| - if (RsaKeyConverters.isNotX509PemWrapper(line) && isNotX509CertificateWrapper(line)) { |
125 |
| - base64Encoded.append(line); |
126 |
| - } |
127 |
| - } |
128 |
| - byte[] x509 = Base64.getDecoder().decode(base64Encoded.toString()); |
129 |
| - if (lines.get(0).startsWith(X509_PEM_HEADER)) { |
130 |
| - try { |
131 |
| - return (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(x509)); |
132 |
| - } |
133 |
| - catch (Exception ex) { |
134 |
| - throw new IllegalArgumentException(ex); |
135 |
| - } |
136 |
| - } |
137 |
| - if (lines.get(0).startsWith(X509_CERT_HEADER)) { |
138 |
| - try (InputStream x509CertStream = new ByteArrayInputStream(x509)) { |
139 |
| - X509Certificate certificate = (X509Certificate) certificateFactory |
140 |
| - .generateCertificate(x509CertStream); |
141 |
| - return (RSAPublicKey) certificate.getPublicKey(); |
142 |
| - } |
143 |
| - catch (CertificateException | IOException ex) { |
144 |
| - throw new IllegalArgumentException(ex); |
145 |
| - } |
146 |
| - } |
147 |
| - return null; |
| 125 | + return decoder.convert(lines); |
148 | 126 | };
|
149 | 127 | }
|
150 | 128 |
|
@@ -175,12 +153,70 @@ private static boolean isNotPkcs8Wrapper(String line) {
|
175 | 153 | return !PKCS8_PEM_HEADER.equals(line) && !PKCS8_PEM_FOOTER.equals(line);
|
176 | 154 | }
|
177 | 155 |
|
178 |
| - private static boolean isNotX509PemWrapper(String line) { |
179 |
| - return !X509_PEM_HEADER.equals(line) && !X509_PEM_FOOTER.equals(line); |
| 156 | + private static class X509PemDecoder implements Converter<List<String>, RSAPublicKey> { |
| 157 | + |
| 158 | + private final KeyFactory keyFactory; |
| 159 | + |
| 160 | + X509PemDecoder(KeyFactory keyFactory) { |
| 161 | + this.keyFactory = keyFactory; |
| 162 | + } |
| 163 | + |
| 164 | + @Override |
| 165 | + @NonNull |
| 166 | + public RSAPublicKey convert(List<String> lines) { |
| 167 | + StringBuilder base64Encoded = new StringBuilder(); |
| 168 | + for (String line : lines) { |
| 169 | + if (isNotX509PemWrapper(line)) { |
| 170 | + base64Encoded.append(line); |
| 171 | + } |
| 172 | + } |
| 173 | + byte[] x509 = Base64.getDecoder().decode(base64Encoded.toString()); |
| 174 | + try { |
| 175 | + return (RSAPublicKey) this.keyFactory.generatePublic(new X509EncodedKeySpec(x509)); |
| 176 | + } |
| 177 | + catch (Exception ex) { |
| 178 | + throw new IllegalArgumentException(ex); |
| 179 | + } |
| 180 | + } |
| 181 | + |
| 182 | + private boolean isNotX509PemWrapper(String line) { |
| 183 | + return !X509_PEM_HEADER.equals(line) && !X509_PEM_FOOTER.equals(line); |
| 184 | + } |
| 185 | + |
180 | 186 | }
|
181 | 187 |
|
182 |
| - private static boolean isNotX509CertificateWrapper(String line) { |
183 |
| - return !X509_CERT_HEADER.equals(line) && !X509_CERT_FOOTER.equals(line); |
| 188 | + private static class X509CertificateDecoder implements Converter<List<String>, RSAPublicKey> { |
| 189 | + |
| 190 | + private final CertificateFactory certificateFactory; |
| 191 | + |
| 192 | + X509CertificateDecoder(CertificateFactory certificateFactory) { |
| 193 | + this.certificateFactory = certificateFactory; |
| 194 | + } |
| 195 | + |
| 196 | + @Override |
| 197 | + @NonNull |
| 198 | + public RSAPublicKey convert(List<String> lines) { |
| 199 | + StringBuilder base64Encoded = new StringBuilder(); |
| 200 | + for (String line : lines) { |
| 201 | + if (isNotX509CertificateWrapper(line)) { |
| 202 | + base64Encoded.append(line); |
| 203 | + } |
| 204 | + } |
| 205 | + byte[] x509 = Base64.getDecoder().decode(base64Encoded.toString()); |
| 206 | + try (InputStream x509CertStream = new ByteArrayInputStream(x509)) { |
| 207 | + X509Certificate certificate = (X509Certificate) this.certificateFactory |
| 208 | + .generateCertificate(x509CertStream); |
| 209 | + return (RSAPublicKey) certificate.getPublicKey(); |
| 210 | + } |
| 211 | + catch (CertificateException | IOException ex) { |
| 212 | + throw new IllegalArgumentException(ex); |
| 213 | + } |
| 214 | + } |
| 215 | + |
| 216 | + private boolean isNotX509CertificateWrapper(String line) { |
| 217 | + return !X509_CERT_HEADER.equals(line) && !X509_CERT_FOOTER.equals(line); |
| 218 | + } |
| 219 | + |
184 | 220 | }
|
185 | 221 |
|
186 | 222 | }
|
0 commit comments