Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pkix der encoded key parsing #429

Merged
merged 1 commit into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions sigstore-java/src/main/java/dev/sigstore/encryption/Keys.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ public static PublicKey parsePublicKey(byte[] keyBytes)
return keyFactory.generatePublic(publicKeySpec);
}

/**
* Takes a PKIX DER formatted public key in bytes and constructs a {@code PublicKey} with it.
*
* <p>This method is known to work with keys algorithms: RSA, EdDSA, EC.
*
* @param contents the public key bytes
* @param algorithm the key algorithm
* @return a PublicKey object
* @throws NoSuchAlgorithmException if we don't support the scheme provided
* @throws InvalidKeySpecException if the public key material is invalid
*/
public static PublicKey parsePkixPublicKey(byte[] contents, String algorithm)
throws NoSuchAlgorithmException, InvalidKeySpecException {
X509EncodedKeySpec spec = new X509EncodedKeySpec(contents);
KeyFactory factory = KeyFactory.getInstance(algorithm);
return factory.generatePublic(spec);
}

/**
* Valid values for scheme are:
*
Expand All @@ -127,16 +145,12 @@ public static PublicKey parsePublicKey(byte[] keyBytes)
*/
public static PublicKey constructTufPublicKey(byte[] contents, String scheme)
throws NoSuchAlgorithmException, InvalidKeySpecException {
PublicKey publicKey = null;
switch (scheme) {
case "rsassa-pss-sha256":
throw new RuntimeException("rsassa-pss-sha256 not currently supported");
case "ed25519":
{
final KeyFactory kf = KeyFactory.getInstance("Ed25519");
final X509EncodedKeySpec keySpec = new X509EncodedKeySpec(contents);
publicKey = kf.generatePublic(keySpec);
break;
return kf.generatePublic(keySpec);
}
case "ecdsa-sha2-nistp256":
{
Expand All @@ -157,11 +171,11 @@ public static PublicKey constructTufPublicKey(byte[] contents, String scheme)
new ECNamedCurveSpec("P-256", spec.getCurve(), spec.getG(), spec.getN());
ECPoint point = decodePoint(params.getCurve(), contents);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
publicKey = kf.generatePublic(pubKeySpec);
break;
return kf.generatePublic(pubKeySpec);
}
default:
throw new RuntimeException(scheme + " not currently supported");
}
return publicKey;
}

// https://stackoverflow.com/questions/42911637/get-publickey-from-key-bytes-not-knowing-the-key-algorithm
Expand Down
66 changes: 45 additions & 21 deletions sigstore-java/src/test/java/dev/sigstore/encryption/KeysTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -155,33 +156,56 @@ void parseTufPublicKey_ed25519_lteJava14()

@Test
void parseTufPublicKey_ed25519Bad() {

try {
PublicKey key =
Keys.constructTufPublicKey(
Hex.decode(
"302b300506032b65700321008b2e369230c3b97f4627fd6a59eb054a83ec15ed929ab3d983a40ffd322a223d"),
"ed25519");
fail();
} catch (Exception e) {
}
Assertions.assertThrows(
InvalidKeySpecException.class,
() ->
Keys.constructTufPublicKey(
Hex.decode(
"302b300506032b65700321008b2e369230c3b97f4627fd6a59eb054a83ec15ed929ab3d983a40ffd322a223d"),
"ed25519"));
}

@Test
void parseTufPublicKey_rsa()
throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
void parseTufPublicKey_rsa() throws NoSuchAlgorithmException, InvalidKeySpecException {
// {@code step crypto keypair ed25519.pub /dev/null --kty OKP --curve Ed25519}
// copy just the key part out of ed25519.pub removing PEM header and footer
// {@code echo $(copied content) | base64 -d | hexdump -v -e '/1 "%02x" '}
try {
PublicKey key =
Keys.constructTufPublicKey(
Hex.decode(
"302a300506032b65700321008b2e369230c3b97f4627fd6a59eb054a83ec15ed929ab3d983a40ffd322a223d"),
"rsassa-pss-sha256");
fail();
} catch (RuntimeException e) {
}
Assertions.assertThrows(
RuntimeException.class,
() ->
Keys.constructTufPublicKey(
Hex.decode(
"302a300506032b65700321008b2e369230c3b97f4627fd6a59eb054a83ec15ed929ab3d983a40ffd322a223d"),
"rsassa-pss-sha256"));
}

@Test
void parsePkixPublicKey_rsa() throws NoSuchAlgorithmException, InvalidKeySpecException {
var base64Key =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAghWkDAnX9F5QZZ9NxIWg9vcjULtD/kkbQwlcSm22e06FrgOdiFy1fKN/Ng32qEk1ZIKyi0HFzZxzPIcvg7eaFTRb7+AQiG6eMDmUzPGr67Jp0Di2ncH9+uOZmv4PVKovvQLq7qnEwbDk0HttxUscLQ2e36Lfv/2lpGW7apVmHVMoC5kwZ3KTiAk/DUtDhD4VQjU2rBy6OneO6pm6vdNzG4Jktjc0uUKFCRRUzydGEh05PgC9vSQu/EOiU+7aQPV1ZDUGpjg9tOM0SgaTOU3YSUfGiXZNHoiS2HwLyQPaxiHR2NPVH75bwnUFBHhdMxT1rhU+yLhXaweDQW6GQ0ti8wIDAQAB";
Assertions.assertNotNull(Keys.parsePkixPublicKey(Base64.decode(base64Key), "RSA"));
}

@Test
void parsePkixPublicKey_rsaKeyButWrongAlgorithm() {
var base64Key =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAghWkDAnX9F5QZZ9NxIWg9vcjULtD/kkbQwlcSm22e06FrgOdiFy1fKN/Ng32qEk1ZIKyi0HFzZxzPIcvg7eaFTRb7+AQiG6eMDmUzPGr67Jp0Di2ncH9+uOZmv4PVKovvQLq7qnEwbDk0HttxUscLQ2e36Lfv/2lpGW7apVmHVMoC5kwZ3KTiAk/DUtDhD4VQjU2rBy6OneO6pm6vdNzG4Jktjc0uUKFCRRUzydGEh05PgC9vSQu/EOiU+7aQPV1ZDUGpjg9tOM0SgaTOU3YSUfGiXZNHoiS2HwLyQPaxiHR2NPVH75bwnUFBHhdMxT1rhU+yLhXaweDQW6GQ0ti8wIDAQAB";
Assertions.assertThrows(
InvalidKeySpecException.class,
() -> Keys.parsePkixPublicKey(Base64.decode(base64Key), "EC"));
}

@Test
void parsePkixPublicKey_eddsa() throws NoSuchAlgorithmException, InvalidKeySpecException {
var base64Key = "MCowBQYDK2VwAyEAixzZOnx34hveTZ69J5iBCkmerK5Oh7EzJqTh3YY55jI=";
Assertions.assertNotNull(Keys.parsePkixPublicKey(Base64.decode(base64Key), "EdDSA"));
}

@Test
void parsePkixPublicKey_ecdsa() throws NoSuchAlgorithmException, InvalidKeySpecException {
var base64Key =
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVqBnvab9XEVlTLW4iGKBIdrL6Sxf0x5vclZyXtR6hl79/o+RSgyr1ZQKLLCUC20imDWUgFMmfLu4UUiKNcI2uQ==";
Assertions.assertNotNull(Keys.parsePkixPublicKey(Base64.decode(base64Key), "EC"));
}

@Test
Expand Down