Search in sources :

Example 1 with CborBuilder

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();
}
Also used : SecretKey(javax.crypto.SecretKey) CborBuilder(co.nstant.in.cbor.CborBuilder) Collection(java.util.Collection) LinkedHashMap(java.util.LinkedHashMap) CborBuilder(co.nstant.in.cbor.CborBuilder)

Example 2 with CborBuilder

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);
    }
}
Also used : PrivateKey(java.security.PrivateKey) JcaContentSignerBuilder(org.bouncycastle.operator.jcajce.JcaContentSignerBuilder) CertificateException(java.security.cert.CertificateException) X500Name(org.bouncycastle.asn1.x500.X500Name) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) CertificateFactory(java.security.cert.CertificateFactory) JcaX509v3CertificateBuilder(org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder) UnrecoverableEntryException(java.security.UnrecoverableEntryException) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) PublicKey(java.security.PublicKey) ContentSigner(org.bouncycastle.operator.ContentSigner) IOException(java.io.IOException) CertIOException(org.bouncycastle.cert.CertIOException) KeyStoreException(java.security.KeyStoreException) KeyStore(java.security.KeyStore) X509Certificate(java.security.cert.X509Certificate) Date(java.util.Date) ByteArrayInputStream(java.io.ByteArrayInputStream) BigInteger(java.math.BigInteger) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier) CborBuilder(co.nstant.in.cbor.CborBuilder) NonNull(androidx.annotation.NonNull)

Example 3 with CborBuilder

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);
    }
}
Also used : AtomicFile(android.util.AtomicFile) FileOutputStream(java.io.FileOutputStream) UnicodeString(co.nstant.in.cbor.model.UnicodeString) ByteString(co.nstant.in.cbor.model.ByteString) IOException(java.io.IOException) CertIOException(org.bouncycastle.cert.CertIOException) CborBuilder(co.nstant.in.cbor.CborBuilder)

Example 4 with CborBuilder

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);
}
Also used : CertificateEncodingException(java.security.cert.CertificateEncodingException) X509Certificate(java.security.cert.X509Certificate) CborBuilder(co.nstant.in.cbor.CborBuilder)

Example 5 with CborBuilder

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;
}
Also used : DataItem(co.nstant.in.cbor.model.DataItem) UnicodeString(co.nstant.in.cbor.model.UnicodeString) UnicodeString(co.nstant.in.cbor.model.UnicodeString) MapBuilder(co.nstant.in.cbor.builder.MapBuilder) CborBuilder(co.nstant.in.cbor.CborBuilder) NonNull(androidx.annotation.NonNull)

Aggregations

CborBuilder (co.nstant.in.cbor.CborBuilder)49 NonNull (androidx.annotation.NonNull)17 ByteArrayOutputStream (java.io.ByteArrayOutputStream)16 CborEncoder (co.nstant.in.cbor.CborEncoder)15 DataItem (co.nstant.in.cbor.model.DataItem)14 UnicodeString (co.nstant.in.cbor.model.UnicodeString)14 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)9 Test (org.junit.Test)9 CborException (co.nstant.in.cbor.CborException)8 ByteString (co.nstant.in.cbor.model.ByteString)8 MediumTest (androidx.test.filters.MediumTest)7 MapBuilder (co.nstant.in.cbor.builder.MapBuilder)7 InvalidKeyException (java.security.InvalidKeyException)7 ArrayBuilder (co.nstant.in.cbor.builder.ArrayBuilder)6 X509Certificate (java.security.cert.X509Certificate)6 PublicKey (java.security.PublicKey)4 ECPoint (java.security.spec.ECPoint)4 SimpleValue (co.nstant.in.cbor.model.SimpleValue)3 CoseException (com.google.cose.exceptions.CoseException)3 IOException (java.io.IOException)3