Skip to content

Could decoding be more ergonomic? #127

@jhannes

Description

@jhannes

I'm trying to use cbor-java to implement webauth. In this case, I need to get a COSE from a subset of a binary field in a CBOR object. The code for doing this with cbor-java could be more ergonomic:

Map attestationDataItem = (Map) CborDecoder.decode(Base64.getDecoder().decode(base64AttestationObject)).get(0);
byte[] authData = ((ByteString) attestationDataItem.get(new UnicodeString("authData"))).getBytes();
int idLength = authData[53] << 8 | authData[54];
byte[] publicKeyBytes = new byte[authData.length - 55 - idLength];

Map cosePublicKey = (Map) CborDecoder.decode(publicKeyBytes).get(0);

Number keyType = (Number) cosePublicKey.get(new UnsignedInteger(1));
KeyFactory keyFactory = KeyFactory.getInstance("EC"); // since keyType == 2

Number algorithm = (Number) cosePublicKey.get(new UnsignedInteger(3));

Number curveType = (Number) cosePublicKey.get(new UnsignedInteger(-1));
AlgorithmParameters params = AlgorithmParameters.getInstance("EC");
params.init(new ECGenParameterSpec("secp256k1")); // since curveType == -1

// since keyType == 2
byte[] x = ((ByteString) cosePublicKey.get(new UnsignedInteger(-2))).getBytes();
byte[] y = ((ByteString) cosePublicKey.get(new UnsignedInteger(-3))).getBytes();

ECPublicKeySpec keySpec = new ECPublicKeySpec(
        new ECPoint(new BigInteger(x), new BigInteger(y)),
        params.getParameterSpec(ECParameterSpec.class)
);

(please disregard the KeyFactory, AlgorithmParameters and ECGenParameterSpec stuff - this is java.security stuff)

In an ideal world, I would be able to write something like:

Map attestationDataItem = CborDecoder.decodeMap(Base64.getDecoder().decode(base64AttestationObject)).get(0);
byte[] authData = attestationDataItem.getBytes("authData");
int idLength = authData[53] << 8 | authData[54];
byte[] publicKeyBytes = new byte[authData.length - 55 - idLength];

Map cosePublicKey = CborDecoder.decodeMap(publicKeyBytes).get(0);

int keyType = cosePublicKey.getInt(1);
KeyFactory keyFactory = KeyFactory.getInstance("EC"); // since keyType == 2

int algorithm = cosePublicKey.getInt(3);

int curveType = cosePublicKey.getInt(-1);
AlgorithmParameters params = AlgorithmParameters.getInstance("EC");
params.init(new ECGenParameterSpec("secp256k1")); // since curveType == -1

// since keyType == 2
byte[] x = cosePublicKey.getBytes(-2);
byte[] y = cosePublicKey.getBytes(-3);

Would you consider a pull request to this effect?

(If you want to be really ambitious, doing COSE => java.security would be cool)

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions