From 9784a0aa6e277261a2eeebe9d9718d57b4b297ad Mon Sep 17 00:00:00 2001 From: Niels Thykier Date: Tue, 19 Nov 2024 10:49:15 +0100 Subject: [PATCH] SD-1775: Issues with parsing the provided public key The real issue was the header used `RSA `, when it should not have. However, I also changed the code to use Bouncycastle's PEM parser and writer to delegate some of the code to a library. --- ebl/pom.xml | 10 ++++++ .../ebl/crypto/PayloadSignerFactory.java | 32 +++++++++---------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/ebl/pom.xml b/ebl/pom.xml index 29386246..2040a0c1 100644 --- a/ebl/pom.xml +++ b/ebl/pom.xml @@ -33,5 +33,15 @@ canonical-json 3.0 + + org.bouncycastle + bcprov-jdk18on + 1.79 + + + org.bouncycastle + bcpkix-jdk18on + 1.79 + diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/PayloadSignerFactory.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/PayloadSignerFactory.java index deb7068d..6b03b8ee 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/PayloadSignerFactory.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/PayloadSignerFactory.java @@ -7,8 +7,14 @@ import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jose.crypto.RSASSAVerifier; import lombok.SneakyThrows; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.bouncycastle.util.io.pem.PemWriter; +import org.dcsa.conformance.core.UserFacingException; import org.dcsa.conformance.standards.ebl.crypto.impl.RSAPayloadSigner; +import java.io.StringReader; +import java.io.StringWriter; import java.security.KeyFactory; import java.security.KeyPair; import java.security.PublicKey; @@ -178,22 +184,15 @@ public static SignatureVerifier verifierFromPublicKey(PublicKey publicKey) { @SneakyThrows public static SignatureVerifier verifierFromPemEncodedPublicKey(String publicKeyPem) { - if (publicKeyPem.contains("-----BEGIN RSA PUBLIC KEY-----")) { - String privKeyPEM = publicKeyPem.replace("-----BEGIN RSA PUBLIC KEY-----", "") - .replace("-----END RSA PUBLIC KEY-----", "") - .replaceAll("\\s++", ""); - - byte [] encoded = Base64.getDecoder().decode(privKeyPEM); - + try (var reader = new PemReader(new StringReader(publicKeyPem))) { + var encoded = reader.readPemObject().getContent(); var keySpec = new X509EncodedKeySpec(encoded); KeyFactory kf = KeyFactory.getInstance("RSA"); var rsaPublicKey = (RSAPublicKey)kf.generatePublic(keySpec); return new SingleKeySignatureVerifier(new RSASSAVerifier(rsaPublicKey)); + } catch (Exception e) { + throw new UserFacingException("Could not parse provided string as an X509 PEM encoded RSA public key"); } - if (publicKeyPem.isEmpty()) { - throw new AssertionError("Missing key at the time where it was needed."); - } - throw new UnsupportedOperationException("Unsupported key format"); } private record SingleKeySignatureVerifier(JWSVerifier jwsVerifier) implements SignatureVerifier { @@ -219,13 +218,12 @@ public String getPublicKeyInPemFormat() { } } + @SneakyThrows public static String pemEncodeKey(RSAPublicKey key) { - var base64 = Base64.getEncoder().encodeToString(key.getEncoded()); - var result = new StringBuilder("-----BEGIN RSA PUBLIC KEY-----\n"); - for (int i = 0; i < base64.length() ; i += 64) { - var limit = i + Math.min(64, base64.length() - i); - result.append(base64, i, limit); + var w = new StringWriter(); + try (var pemWriter = new PemWriter(w)) { + pemWriter.writeObject(new PemObject("PUBLIC KEY", key.getEncoded())); } - return result.append("-----END RSA PUBLIC KEY-----").toString(); + return w.getBuffer().toString(); } }