# Device binding with AnonCreds credentials using attachments ## General idea 1. **Issuer**: Add a device-binding-request to the credential-offer message with a reference to the device binding attribute 2. **Holder**: Recognize the device-binding-request and create a device-binding-response within the credential-request message 3. **Issuer**: Verify the device-binding-reponse and embed the attested key in the credential-issue message ## Benefits * Embeds the creation of a hardware key within the credential issuance protocol * Reduce the amount of overall didcomm messages * Fewer messages are easier for transport * <=3 messages allow for a simple http request based on one out-of-band message * Creates strong association between key attestation and issuance process/protocol * A device-binding key (possible correlation factor) would be recognized and highlighted on issuance (also presentation) ## Drawbacks * All issuance protocols (v1, v2, v3, ...) have to be extended; but it seems possible * `credential-preview` will be different from issued credential; but that is more a question of rendering the attribute ## Issuance protocol v1.0 (Status quo) https://github.com/hyperledger/aries-rfcs/tree/main/features/0036-issue-credential ### Messages #### [propose-credential](https://github.com/hyperledger/aries-rfcs/tree/main/features/0036-issue-credential#propose-credential) ```json= { "@type": "https://didcomm.org/issue-credential/1.1/propose-credential", "@id": "<uuid-of-propose-message>", "comment": "some comment", "credential_proposal": <json-ld object>, "schema_issuer_did": "DID of the proposed schema issuer", "schema_id": "Schema ID string", "schema_name": "Schema name string", "schema_version": "Schema version string", "cred_def_id": "Credential Definition ID string" "issuer_did": "DID of the proposed issuer" } ``` #### [offer-credential](https://github.com/hyperledger/aries-rfcs/tree/main/features/0036-issue-credential#offer-credential) ```json= { "@type": "https://didcomm.org/issue-credential/1.0/offer-credential", "@id": "<uuid-of-offer-message>", "comment": "some comment", "credential_preview": <json-ld object>, "offers~attach": [ { "@id": "libindy-cred-offer-0", "mime-type": "application/json", "data": { "base64": "<bytes for base64>" } } ] } ``` #### [request-credential](https://github.com/hyperledger/aries-rfcs/tree/main/features/0036-issue-credential#request-credential) ```json= { "@type": "https://didcomm.org/issue-credential/1.0/request-credential", "@id": "<uuid-of-request-message>", "comment": "some comment", "requests~attach": [ { "@id": "libindy-cred-request-0", "mime-type": "application/json", "data": { "base64": "<bytes for base64>" } }, ] } ``` #### [issue-credential](https://github.com/hyperledger/aries-rfcs/tree/main/features/0036-issue-credential#issue-credential) ```json= { "@type": "https://didcomm.org/issue-credential/1.0/issue-credential", "@id": "<uuid-of-issue-message>", "comment": "some comment", "credentials~attach": [ { "@id": "libindy-cred-0", "mime-type": "application/json", "data": { "base64": "<bytes for base64>" } } ] } ``` ### Inner objects #### [credential-preview](https://github.com/hyperledger/aries-rfcs/tree/main/features/0036-issue-credential#preview-credential) ```json= { "@type": "https://didcomm.org/issue-credential/1.0/credential-preview", "attributes": [ { "name": "<attribute name>", "mime-type": "<type>", "value": "<value>" }, // more attributes ] } ``` * Attribute preview values can be different from the issued credential attribute values #### [libindy-cred-offer-0](https://github.com/hyperledger/indy-sdk/blob/57dcdae74164d1c7aa06f2cccecaae121cefac25/libindy/src/api/anoncreds.rs#L280) ```json= { "schema_id":"3QowxFtwciWceMFr7WbwnM:2:Name and Age:1.0", "cred_def_id":"3QowxFtwciWceMFr7WbwnM:3:CL:8548:Name and Age", "key_correctness_proof":{ "c":"91094844200868412459497249133757436848048281976724950861777331409745646647675", "xz_cap":"211889047776187384698839547194587366561549251602348876121945607784092527583297680277541609529695365779987891304151526023856403801787836541275031204746250646401524393520575251184327430277299476483183319231631125763938279669546606818321581985321286487665045576540565719150128852845930728880472963504846926059187170852304120779348561304321434526919333297259625093506954137641126052526554734723331423180220192102295741801985019983766702753455404770357956465035805435699212761976427145665329415803976988640399306777965320049126760576650769354972636268804156096090024481081575264281241193387851055574043938850160444281139540899440032182412919993480532027364660895822565447331299930369575203190820432", "xr_cap":[ [ "name", "1583069780877295302650878306558311082487718222153187498637609409930793772614428798456814599095595800558242984581316473743196110755852810493805410155619514365079879282805680846730686128918166440218264936159610451214754936453730405109648133237007247032274628092498575319427801432762599629850335985942446810372663100690241312202704275660736518792354748572022393875899680910217905535332501229986080282255454834148488942042641390219229432318009599746328467774896244800515905590099292605098972745939743833667318907666625792328606022862730501605906007588858511981245190377431854405384959276702234635724647644352987431972684013342361088638650117628548352952194554722280641486789449000363526440601080966" ], [ "age", "1174577335842211052987617643133123129057647216050292313261722213187399222601766352657184606266154545080931455831917184082590553293287122301022070055871194020619216148874374072655820906691697213536373268292157306217524456086949694363919727355852891092834122940493369867002843769326624572727457593223920396658661710593891599570608919869414806639579393472994103609574518784025998749072134851472413220613285822814476562327920532907214737498339895695831408780843434318640285917596326032403220918733231356759708446991550689440709814951326737159955532053261951235880902505444736918028348438067426746713540280033090564704590450350487480372813007584513329478029955633145156771486971154016056464479298638" ], [ "master_secret", "638091816862143212662891655560603656980308052989583823845096507528882803301602447655458408990965815090586202656900037472784764683391429605285624710307921254084740438149535409310090477183075723849947588288741870680770962112611592764680946346839089643550568208048833904147441672171974042184712450125491429561629898493633321270922487391471987055571288488184654601841739544241539586866751781708303882536708261139319135865980721549641022627126058820905944974423114944387400630342126974736777043971647216923860950394424347080913817238704392006711510073980185330338840902912067734491886556162858294839668159461526447433829886400126753849323244129029564730104270892940625111229548160641969961088293559" ] ] }, "nonce":"567480936575876876089373" } ``` * libindy-cred-offer does not contain any attribute values of the issued credential * libindy-cred-offer contains a nonce #### [libindy-cred-request-0](https://github.com/hyperledger/indy-sdk/blob/57dcdae74164d1c7aa06f2cccecaae121cefac25/libindy/src/api/anoncreds.rs#L658) ```json= { "prover_did":"GEaUjQTKsyzE3TeHHksCJR", "cred_def_id":"3QowxFtwciWceMFr7WbwnM:3:CL:8548:Name and Age", "blinded_ms":{ "u":"16449187817568314644796866629848447062449751684524080437259681105949383275044222902573600333668174734572088115381900108198033185334353158572890396849838200679640966465068886387890698184247910000286180056330338464594237372726273916570022551498299512687229842285439221280255459669147531394494586345549658105664453772281929448011163890914009245891195839249418226872085721506137003921122994436911878764101158716166031163436075439337687176945912899119765593074693822375774130281513509621863248975565722859410689002828435682248441827074843268596649688910235703399908921200563981825553778019509036761588390412910129545530850", "ur":"1 02F87077927FD836F711091EC610EE8E4D3A1218F317755F7742CF396D19D886 1 24C2CA8EE1ECEC24F845748174F2A02CBDB15218410E56F976D644FF79B9380F 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8", "hidden_attributes":[ "master_secret" ], "committed_attributes":{ } }, "blinded_ms_correctness_proof":{ "c":"62870784117142813461421316012589351101000968783630439739403245707871897403869", "v_dash_cap":"1787532197014944504822691027438740673240383459836980694137830457590253755833918440180612067199661245455784115797076605754889245382357964328658196171872559031326018693293330982676558256251444542955528812373667514800534377644458774705744638415436586286374235531502690219693730095275245813190782042341672433554374792047594793484480242247778414087303191471049360800080240429500806436628892389842038610026861929079271834380969433884092934644549690049120858271009185693578524794244701343265685199810966917651262980271708137288077850548689523301382409881173287416437402607651415205624188978042468551592145318399282292016486173481313307619348974419194819380178827402160125579633054284153544009532914399392566766213454098634806", "m_caps":{ "master_secret":"1060209001511756809415819615062724636499360489829112910699352633467786083853244269166914443446667050616485598097942658289545568578756206736860674413440919476635228767301698657872" }, "r_caps":{ } }, "nonce":"944884920631152623414182" } ``` * libindy-cred-request contains a blinded master secret * libindy-cred-request contains a prover did #### [libindy-cred-0](https://github.com/hyperledger/indy-sdk/blob/57dcdae74164d1c7aa06f2cccecaae121cefac25/libindy/src/api/anoncreds.rs#L338) ```json= { "schema_id":"3QowxFtwciWceMFr7WbwnM:2:Name and Age:1.0", "cred_def_id":"3QowxFtwciWceMFr7WbwnM:3:CL:8548:NameAndAge", "rev_reg_id":null, "values":{ "Name":{ "raw":"John", "encoded":"76355713903561865866741292988746191972523015098789458240077478826513114743258" }, "Age":{ "raw":"11", "encoded":"11" } }, "signature":{ "p_credential":{ "m_2":"31604996388549251638683403938591077896667211302698264121162249814020132185678", "a":"73018103709614569189474370447990159817146841514890663961472948323968072379776001397754372781115297534358376354578604827565907826840838708814936273902805220253633389719802624023405437713535739578402637765665679672475188088358206412763759428774646072799084477911444847166610422007711370508082224168670055076280905932426140575431699356850633206743084154857533625994078309445493435365212252845588691200686419707428143028771251614834399814221243905934304752311891991663406687941228311234038057201723598053469202163580504637644685183341013770137129869217914433595960686485193427483754027300776272886013661862077192970292230", "e":"259344723055062059907025491480697571938277889515152306249728583105665800713306759149981690559193987143012367913206299323899696942213235956742930113994926478458968892813193398516287", "v":"6166911418737585566102561004802281040981047009460542806309962684772071149464774629739115185520651580909893878436442035211768070399478363083594905010607817820899772752161522309700475941413569724290376442037519521190239256883155596549393149088669266432914090229113315067734596785619392094553217289345465945907214218230910957089813176362882290558599472468356517846325529390479797095346516012717814742092093581204758098910646987671982982050149252724726505480563573113051459929375002878654900438299539835656502499675041659459760669624771666069604670356068362252735694662313421546171039214721642596800076918570983900722777123801921526646420147858409852744177908005089362848059486518941080170387674972125994574505960583004974873305476568645388519032795698122504977478238088670046779998898591228987765255405665423099832002012588" }, "r_credential":null }, "signature_correctness_proof":{ "se":"8336706709499898551918222739092680156558373782334343404832288096432945238782560416120048902083081722842593260466635361458519158622892494339663601046911070717671442125381191146371099193912187767267283301894999688882109172392380696868207053728281195440484213438065594416813125809392755118711452423053088821356152199463794659303812088777549389103906622028823386922327124936623851689683875972271866042864607957734831675730052945805710649915202621470149510656630929554001876604150207750366316520561962037044037871337271644762938396419785266645493403077767251473892450647441161524596020314698917446719064701961853752680386", "c":"5275731485954812706483304094022834380514466121447145665923196465927994273208" }, "rev_reg":null, "witness":null } ``` * libindy-cred contains the raw and encoded attribute value ## Proposal for an Issuance protocol v1.2 ### Messages #### offer-credential ```json= { "@type": "https://didcomm.org/issue-credential/1.2/offer-credential", "@id": "<uuid-of-offer-message>", "comment": "some comment", "credential_preview": <json-ld object>, "offers~attach": [ { "@id": "libindy-cred-offer-0", "mime-type": "application/json", "data": { "base64": "<bytes for base64>" } } ], "device_binding": <device-binding-request> } ``` #### request-credential ```json= { "@type": "https://didcomm.org/issue-credential/1.0/request-credential", "@id": "<uuid-of-request-message>", "comment": "some comment", "requests~attach": [ { "@id": "libindy-cred-request-0", "mime-type": "application/json", "data": { "base64": "<bytes for base64>" } }, ], "device_binding": <device-binding-response> } ``` ### Inner objects #### device-binding-request ```json= { "@type": "https://didcomm.org/issue-credential/1.2/device-binding-request", "requests" : [ { "offer": <libindy-cred-offer id> "referent": <attribute name> "acceptedKeyStorage" : [ "TEE", "Strongbox", "SecureEnclave", "SecureElement" ], "nonce": <a nonce> // could use the nonce from libindy-cred-offer } ] } ``` #### device-binding-response ```json= { "@type": "https://didcomm.org/devicebinding/1.2/device-binding-response", "responses" : [ { "id" : <did:key ?> "request" : <libindy-cred-request id>, "referent": <attribute name>, "keyStorageType" : "TEE_v1", } ], "responses~attach" : [ { "@id" : <did:key ?>, "mime-type" : application/json, "data" : { "androidCertificateChain" : <base64-encoded/ASCII-armored certificates> "keyChallengeSignature" : <base64-encoded ECDSA signature result> } } ] } ``` #### credential-preview ```json= { "@type": "https://didcomm.org/issue-credential/1.2/credential-preview", "attributes": [ { "name": "first_name", "mime-type": "plain/text", "value": "John" }, { "name": "device_binding_key", // fixed attribute name for device binding or not? "mime-type": <some mimetype representing a public key>, // application/something? "value": <some placeholder> }, // more attributes ] } ``` #### Open questions: * How to handle credential preview of device binding keys? * Can we define a mime-type which would clarify the preview? * Should the given mime-tpye be ignored when showing this credential-preview to the user? * How to attach the device-binding-request object and reference the libindy-cred-offer attachment and its credential attribute? * Inline, embedded or append * How to attach the device-binding-response object and reference the libindy-cred-request and its credential attribute? * Inline, embedded or append * Which nonce do we use? * libindy-cred-offer or a new one? * Which format does the key have? ## Credential Issuance v2 https://github.com/hyperledger/aries-rfcs/blob/main/features/0453-issue-credential-v2/README.md We should be able to attach the same device-binding objects proposed for a credential issuance v1.2 to the `offer-credential` and the `request-credential` message of v2. ```json= { "@type": "https://didcomm.org/issue-credential/%VER/offer-credential", "@id": "<uuid of offer message>", "goal_code": "<goal-code>", "replacement_id": "<issuer unique id>", "comment": "<some comment>", "credential_preview": <json-ld object>, "formats" : [ { "attach_id" : "<attach@id value>", "format" : "<format-and-version>", } ], "offers~attach": [ { "@id": "<attach@id value>", "mime-type": "application/json", "data": { "base64": "<bytes for base64>" } } ], "device_binding": <device-binding request object> } ``` * `credential_preview` has not changed in comparison to v1 * `offers~attach` has not changed in comparison to v1 ```json= { "@type": "https://didcomm.org/issue-credential/%VER/request-credential", "@id": "<uuid of request message>", "goal_code": "<goal-code>", "comment": "<some comment>", "formats" : [ { "attach_id" : "<attach@id value>", "format" : "<format-and-version>", } ], "requests~attach": [ { "@id": "<attachment identifier>", "mime-type": "application/json", "data": { "base64": "<bytes for base64>" } }, ], "device_binding": <device-binding response> } ``` * `credentials` ## Proof Presentation Out-of-scope - the presentation/proof of the device binding should be defined in another proposal