use of co.nstant.in.cbor.CborBuilder in project identity-credential by google.
the class MultiDocumentPresentationTest method checkPresentation.
static void checkPresentation(PresentationSession session, String credentialName, PublicKey expectedAuthKey, PrivateKey readerEphemeralPrivateKey, byte[] sessionTranscript) throws Exception {
Map<String, Collection<String>> dsEntriesToRequest = new LinkedHashMap<>();
dsEntriesToRequest.put("org.iso.18013-5.2019", Arrays.asList("First name", "Last name", "Home address", "Birth date", "Cryptanalyst", "Portrait image", "Height"));
// First check DeviceSigned
CredentialDataResult rd = session.getCredentialData(credentialName, new CredentialDataRequest.Builder().setDeviceSignedEntriesToRequest(dsEntriesToRequest).setRequestMessage(Util.createItemsRequest(dsEntriesToRequest, null)).build());
// Check we didn't get any IssuerSigned entries
assertEquals(0, rd.getIssuerSignedEntries().getNamespaces().size());
byte[] resultCbor = rd.getDeviceNameSpaces();
String pretty = Util.cborPrettyPrint(Util.canonicalizeCbor(resultCbor));
assertEquals("{\n" + " 'org.iso.18013-5.2019' : {\n" + " 'Height' : 180,\n" + " 'Last name' : 'Turing',\n" + " 'Birth date' : '19120623',\n" + " 'First name' : 'Alan',\n" + " 'Cryptanalyst' : true,\n" + " 'Home address' : 'Maida Vale, London, England',\n" + " 'Portrait image' : [0x01, 0x02]\n" + " }\n" + "}", pretty);
byte[] deviceAuthentication = Util.cborEncode(new CborBuilder().addArray().add("DeviceAuthentication").add(Util.cborDecode(sessionTranscript)).add("org.iso.18013-5.2019.mdl").add(Util.cborBuildTaggedByteString(resultCbor)).end().build().get(0));
byte[] mac = rd.getDeviceMac();
byte[] signature = rd.getDeviceSignature();
assertTrue(mac != null || signature != null);
if (expectedAuthKey != null) {
byte[] deviceAuthenticationBytes = Util.cborEncode(Util.cborBuildTaggedByteString(deviceAuthentication));
if (mac != null) {
// Calculate the MAC by deriving the key using ECDH and HKDF.
SecretKey eMacKey = Util.calcEMacKeyForReader(expectedAuthKey, readerEphemeralPrivateKey, sessionTranscript);
byte[] expectedMac = Util.cborEncode(Util.coseMac0(eMacKey, // payload
new byte[0], // detached content
deviceAuthenticationBytes));
// Then compare it with what the TA produced.
assertArrayEquals(expectedMac, mac);
} else {
assertTrue(Util.coseSign1CheckSignature(Util.cborDecode(signature), deviceAuthenticationBytes, expectedAuthKey));
}
}
// Then check IssuerSigned
Map<String, Collection<String>> isEntriesToRequest = new LinkedHashMap<>();
isEntriesToRequest.put("org.iso.18013-5.2019", Arrays.asList("First name", "Last name", "Home address", "Birth date", "Cryptanalyst", "Portrait image", "Height"));
rd = session.getCredentialData(credentialName, new CredentialDataRequest.Builder().setIssuerSignedEntriesToRequest(isEntriesToRequest).setRequestMessage(Util.createItemsRequest(dsEntriesToRequest, null)).build());
// Check we didn't get any DeviceSigned entries
assertEquals(0, rd.getDeviceSignedEntries().getNamespaces().size());
assertEquals(1, rd.getIssuerSignedEntries().getNamespaces().size());
Collection<String> entryNames = rd.getIssuerSignedEntries().getEntryNames("org.iso.18013-5.2019");
assertEquals(7, entryNames.size());
assertEquals("Alan", rd.getIssuerSignedEntries().getEntryString("org.iso.18013-5.2019", "First name"));
assertEquals("Turing", rd.getIssuerSignedEntries().getEntryString("org.iso.18013-5.2019", "Last name"));
assertEquals("19120623", rd.getIssuerSignedEntries().getEntryString("org.iso.18013-5.2019", "Birth date"));
assertEquals(180, rd.getIssuerSignedEntries().getEntryInteger("org.iso.18013-5.2019", "Height"));
assertTrue(rd.getIssuerSignedEntries().getEntryBoolean("org.iso.18013-5.2019", "Cryptanalyst"));
assertEquals("Maida Vale, London, England", rd.getIssuerSignedEntries().getEntryString("org.iso.18013-5.2019", "Home address"));
assertArrayEquals(new byte[] { 0x01, 0x02 }, rd.getIssuerSignedEntries().getEntryBytestring("org.iso.18013-5.2019", "Portrait image"));
rd.getIssuerSignedEntries();
}
use of co.nstant.in.cbor.CborBuilder in project identity-credential by google.
the class CredentialData method generateAuthenticationKeyCert.
@NonNull
static X509Certificate generateAuthenticationKeyCert(String authKeyAlias, String credentialKeyAlias, byte[] proofOfProvisioningSha256) {
KeyStore ks = null;
try {
ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
X509Certificate selfSignedCert = (X509Certificate) ks.getCertificate(authKeyAlias);
PublicKey publicKey = selfSignedCert.getPublicKey();
PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) ks.getEntry(credentialKeyAlias, null)).getPrivateKey();
X500Name issuer = new X500Name("CN=Android Identity Credential Key");
X500Name subject = new X500Name("CN=Android Identity Credential Authentication Key");
Date now = new Date();
final long kMilliSecsInOneYear = 365L * 24 * 60 * 60 * 1000;
Date expirationDate = new Date(now.getTime() + kMilliSecsInOneYear);
BigInteger serial = new BigInteger("1");
JcaX509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(issuer, serial, now, expirationDate, subject, publicKey);
if (proofOfProvisioningSha256 != null) {
byte[] encodedProofOfBinding = Util.cborEncode(new CborBuilder().addArray().add("ProofOfBinding").add(proofOfProvisioningSha256).end().build().get(0));
builder.addExtension(new ASN1ObjectIdentifier("1.3.6.1.4.1.11129.2.1.26"), false, encodedProofOfBinding);
}
ContentSigner signer = new JcaContentSignerBuilder("SHA256withECDSA").build(privateKey);
byte[] encodedCert = builder.build(signer).getEncoded();
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert);
X509Certificate result = (X509Certificate) cf.generateCertificate(bais);
return result;
} catch (IOException | KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException | CertificateException | OperatorCreationException e) {
throw new IllegalStateException("Error signing public key with private key", e);
}
}
use of co.nstant.in.cbor.CborBuilder in project identity-credential by google.
the class CredentialData method saveToDisk.
private void saveToDisk() {
CborBuilder builder = new CborBuilder();
MapBuilder<CborBuilder> map = builder.addMap();
saveToDiskBasic(map);
saveToDiskAuthDatas(map);
saveToDiskACPs(map);
saveToDiskNamespaceDatas(map);
saveToDiskAuthKeys(map);
byte[] cleartextDataToSaveBytes = saveToDiskEncode(builder);
byte[] dataToSaveBytes = saveToDiskEncrypt(cleartextDataToSaveBytes);
String filename = getFilenameForCredentialData(mCredentialName);
AtomicFile file = new AtomicFile(mContext.getFileStreamPath(filename));
FileOutputStream outputStream = null;
try {
outputStream = file.startWrite();
outputStream.write(dataToSaveBytes);
outputStream.close();
file.finishWrite(outputStream);
} catch (IOException e) {
if (outputStream != null) {
file.failWrite(outputStream);
}
throw new RuntimeException("Error writing data", e);
}
}
use of co.nstant.in.cbor.CborBuilder in project identity-credential by google.
the class CredentialData method accessControlProfileToCbor.
static DataItem accessControlProfileToCbor(AccessControlProfile accessControlProfile) {
CborBuilder cborBuilder = new CborBuilder();
MapBuilder<CborBuilder> mapBuilder = cborBuilder.addMap();
mapBuilder.put("id", accessControlProfile.getAccessControlProfileId().getId());
X509Certificate readerCertificate = accessControlProfile.getReaderCertificate();
if (readerCertificate != null) {
try {
mapBuilder.put("readerCertificate", readerCertificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new IllegalStateException("Error encoding reader mCertificate", e);
}
}
if (accessControlProfile.isUserAuthenticationRequired()) {
// TODO: what value to put here?
mapBuilder.put("capabilityType", 1);
long timeout = accessControlProfile.getUserAuthenticationTimeout();
if (timeout != 0) {
mapBuilder.put("timeout", timeout);
}
}
return cborBuilder.build().get(0);
}
use of co.nstant.in.cbor.CborBuilder in project identity-credential by google.
the class DeviceRequestGenerator method addDocumentRequest.
/**
* Adds a request for a document and which data elements to request.
*
* @param docType the document type.
* @param itemsToRequest the items to request as a map of namespaces into data
* element
* names into the intent-to-retain for each data element.
* @param requestInfo <code>null</code> or additional information provided.
* This is
* a map from keys and the values must be valid
* <a href="http://cbor.io/">CBOR</a>.
* @param readerKeySignature <code>null</code> if not signing the request, otherwise a
* {@link Signature} to be used for signing the request.
* @param readerKeyCertificateChain <code>null</code> if <code>readerKeySignature</code> is
* <code>null</code>, otherwise a chain of X.509
* certificates for <code>readerKey</code>.
* @return the <code>DeviceRequestGenerator</code>.
*/
@NonNull
public DeviceRequestGenerator addDocumentRequest(@NonNull String docType, @NonNull Map<String, Map<String, Boolean>> itemsToRequest, @Nullable Map<String, byte[]> requestInfo, @Nullable Signature readerKeySignature, @Nullable Collection<X509Certificate> readerKeyCertificateChain) {
CborBuilder nameSpacesBuilder = new CborBuilder();
MapBuilder<CborBuilder> nsBuilder = nameSpacesBuilder.addMap();
for (String namespaceName : itemsToRequest.keySet()) {
Map<String, Boolean> innerMap = itemsToRequest.get(namespaceName);
MapBuilder<MapBuilder<CborBuilder>> elemBuilder = nsBuilder.putMap(namespaceName);
for (String elemName : innerMap.keySet()) {
boolean intentToRetain = innerMap.get(elemName).booleanValue();
elemBuilder.put(elemName, intentToRetain);
}
elemBuilder.end();
}
nsBuilder.end();
CborBuilder itemsRequestBuilder = new CborBuilder();
MapBuilder<CborBuilder> irMapBuilder = itemsRequestBuilder.addMap();
irMapBuilder.put("docType", docType);
irMapBuilder.put(new UnicodeString("nameSpaces"), nameSpacesBuilder.build().get(0));
if (requestInfo != null) {
MapBuilder<MapBuilder<CborBuilder>> riBuilder = irMapBuilder.putMap("requestInfo");
for (String key : requestInfo.keySet()) {
byte[] value = requestInfo.get(key);
DataItem valueDataItem = Util.cborDecode(value);
riBuilder.put(new UnicodeString(key), valueDataItem);
}
riBuilder.end();
}
irMapBuilder.end();
byte[] encodedItemsRequest = Util.cborEncode(itemsRequestBuilder.build().get(0));
DataItem itemsRequestBytesDataItem = Util.cborBuildTaggedByteString(encodedItemsRequest);
DataItem readerAuth = null;
if (readerKeySignature != null) {
if (readerKeyCertificateChain == null) {
throw new IllegalArgumentException("readerKey is provided but no cert chain");
}
if (mEncodedSessionTranscript == null) {
throw new IllegalStateException("sessionTranscript has not been set");
}
byte[] encodedReaderAuthentication = Util.cborEncode(new CborBuilder().addArray().add("ReaderAuthentication").add(Util.cborDecode(mEncodedSessionTranscript)).add(itemsRequestBytesDataItem).end().build().get(0));
byte[] readerAuthenticationBytes = Util.cborEncode(Util.cborBuildTaggedByteString(encodedReaderAuthentication));
readerAuth = Util.coseSign1Sign(readerKeySignature, null, readerAuthenticationBytes, readerKeyCertificateChain);
}
CborBuilder docRequestBuilder = new CborBuilder();
MapBuilder<CborBuilder> mapBuilder = docRequestBuilder.addMap();
mapBuilder.put(new UnicodeString("itemsRequest"), itemsRequestBytesDataItem);
if (readerAuth != null) {
mapBuilder.put(new UnicodeString("readerAuth"), readerAuth);
}
DataItem docRequest = docRequestBuilder.build().get(0);
mDocRequestsBuilder.add(docRequest);
return this;
}
Aggregations