Skip to content

Commit

Permalink
Add function COSEAlgorithmIdentifier.fromPublicKey(ByteArray)
Browse files Browse the repository at this point in the history
  • Loading branch information
emlun committed May 31, 2022
1 parent 05e2452 commit a747531
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 13 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
New features:

* Added method `FidoMetadataDownloader.refreshBlob()`.
* Added function `COSEAlgorithmIdentifier.fromPublicKey(ByteArray)`.


== Version 2.0.0 ==
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ public void validate() {
}

final COSEAlgorithmIdentifier alg =
WebAuthnCodecs.getCoseKeyAlg(cose)
COSEAlgorithmIdentifier.fromPublicKey(cose)
.orElseThrow(
() ->
new IllegalArgumentException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

final class WebAuthnCodecs {

Expand Down Expand Up @@ -140,12 +139,6 @@ private static PublicKey importCoseEd25519PublicKey(CBORObject cose)
return kFact.generatePublic(new X509EncodedKeySpec(x509Key.getBytes()));
}

static Optional<COSEAlgorithmIdentifier> getCoseKeyAlg(ByteArray key) {
CBORObject cose = CBORObject.DecodeFromBytes(key.getBytes());
final int alg = cose.get(CBORObject.FromObject(3)).AsInt32();
return COSEAlgorithmIdentifier.fromId(alg);
}

static String getJavaAlgorithmName(COSEAlgorithmIdentifier alg) {
switch (alg) {
case EdDSA:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.upokecenter.cbor.CBORException;
import com.upokecenter.cbor.CBORObject;
import java.util.Optional;
import java.util.stream.Stream;
import lombok.Getter;
import lombok.NonNull;

/**
* A number identifying a cryptographic algorithm. The algorithm identifiers SHOULD be values
Expand Down Expand Up @@ -65,6 +68,36 @@ public static Optional<COSEAlgorithmIdentifier> fromId(long id) {
return Stream.of(values()).filter(v -> v.id == id).findAny();
}

/**
* Read the {@link COSEAlgorithmIdentifier} from a public key in COSE_Key format.
*
* @param publicKeyCose a public key in COSE_Key format.
* @return The <code>alg</code> of the <code>publicKeyCose</code> parsed as a {@link
* COSEAlgorithmIdentifier}, if possible. Returns empty if the {@link COSEAlgorithmIdentifier}
* enum has no constant matching the <code>alg</code> value.
* @throws IllegalArgumentException if <code>publicKeyCose</code> is not a well-formed COSE_Key.
*/
public static Optional<COSEAlgorithmIdentifier> fromPublicKey(@NonNull ByteArray publicKeyCose) {
final CBORObject ALG = CBORObject.FromObject(3);
final int alg;
try {
CBORObject cose = CBORObject.DecodeFromBytes(publicKeyCose.getBytes());
if (!cose.ContainsKey(ALG)) {
throw new IllegalArgumentException(
"Public key does not contain an \"alg\"(3) value: " + publicKeyCose);
}
CBORObject algCbor = cose.get(ALG);
if (!(algCbor.isNumber() && algCbor.AsNumber().IsInteger())) {
throw new IllegalArgumentException(
"Public key has non-integer \"alg\"(3) value: " + publicKeyCose);
}
alg = algCbor.AsInt32();
} catch (CBORException e) {
throw new IllegalArgumentException("Failed to parse public key", e);
}
return fromId(alg);
}

@JsonCreator
private static COSEAlgorithmIdentifier fromJson(long id) {
return fromId(id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,8 @@ case class RegistrationTestData(
})

protected def validate(): Unit = {
val alg = WebAuthnCodecs
.getCoseKeyAlg(
val alg = COSEAlgorithmIdentifier
.fromPublicKey(
response.getResponse.getParsedAuthenticatorData.getAttestedCredentialData.get.getCredentialPublicKey
)
.get
Expand Down Expand Up @@ -785,7 +785,7 @@ case class RegistrationTestData(
val pubkey = WebAuthnCodecs.importCosePublicKey(pubKeyCoseBytes)
val prikey = WebAuthnTestCodecs.importPrivateKey(
privateKey,
WebAuthnCodecs.getCoseKeyAlg(pubKeyCoseBytes).get,
COSEAlgorithmIdentifier.fromPublicKey(pubKeyCoseBytes).get,
)
new KeyPair(pubkey, prikey)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1781,8 +1781,8 @@ class RelyingPartyRegistrationSpec
it("Succeeds for an RS1 test case.") {
val testData =
RegistrationTestData.Packed.SelfAttestationRs1
val alg = WebAuthnCodecs
.getCoseKeyAlg(
val alg = COSEAlgorithmIdentifier
.fromPublicKey(
testData.response.getResponse.getParsedAuthenticatorData.getAttestedCredentialData.get.getCredentialPublicKey
)
.get
Expand Down

0 comments on commit a747531

Please sign in to comment.