Skip to main content

SecureQR v2.0

The second version of SecureQR exists to simplify the reconstruction and verification process of SecureQR presentations. Changes include new URI-based QR frame-data, compression of the Verifiable Credential payload and better alignment with standards such as SD-JWT (RFC9901).

Security Considerations

Because SecureQR codes are targeted towards simple device-to-device, the wallet and verifier are not able to exchange a nonce. Instead the verifier relies on short lived presentations, which require the phone and verifier clocks to be sufficiently synchronized. To prevent misuse the lifetime of a presentation MUST be less than 15 minutes (exp - iat <= 900).

The verifier MAY temporarily store the wallet key ID and or jti, that is bound to the Verifiable Credential to identify copied credentials. The verifier must verify both presentation- and VC signature as well as the revocation list status, as specified by OpenID4VP 1.0 and W3C VCDM 2.0.

A full OpenID4VP flow is RECOMMENDED for all use-cases with strict security requirements.

High-level overview

diagram

Decoding / Verification

Implement the following steps in order to decode and verify SecureQR presentations:

  1. Parse all QR Code URI frames
    1. Assert all "id"s match
    2. Sort frames according to "n"
  2. Concat QR Codes' chunk data ("d") as Frame Payload
  3. Decompress Frame Payload using zlib and parse JSON
  4. Combine "vc1", "vc2" and "vc3" strings to create VC
    1. vc1 + "." + base64urlEncode(vc2) + "." + vc3
  5. Extract Holder Key from cnf.jwk property of VC payload
  6. Verify key binding signature using Holder Key (RFC9901)
  7. Assert nbf < iat < exp of key binding
  8. Complete verification of VC as specified by OID4VP
    1. Including but not limited to VC signature, iss, exp, iat, nbf

Appendix

Example SecureQR sequence

Frame nr.QR code
0

frame-0 picture

mdlqr:v2
?id=10238162
&n=0
&m=4
&d=eNqVVduSokgQ_Rdfd2i5Iz5tI2KDgiig4jphAIVQXBUKESZ6v
n0Rp3t7OmKjYx6IIi8nM-NkVeaPwdUjBuOB3yiFs13BJVTi7mQBuYHLdJ2421Flb9fxYpvEi04GUMuBJ
DnbnQwXEwX3d889xm5Qu58QF0Ct7vrQnXl3vWS1MqFBhR986xKRXaIfh0Hmng6DMcFxOEFRHE98O3Q21
KkOA9FP80nhAz9D0EkOg850LMHRSYLeXIYORjJsr4dl2esABOPad8eggz45AGAQPAH_2vt42T1TlzKq4
8dPjJoeNZ08HIprL-rvYW-9TOpIb2xLwxThKCjLaqqTEjAwKn4ZLZdQwgvLile8WXuu2qMeQcslIEV6J
UxZMT6uuJSO9SM_ne2rY6bWWrFt2HRPEc5aV7zD4PW1w_m3850KnuR4HCd-UfGo9G8vz5B_u_Pyz2EQI
nQux8NhXddPNfWUF8GQxInR0HsnqxxeicPgexcBNWf_gdr4BTxB
1

frame-1 picture

mdlqr:v2
?id=10238162
&n=1
&m=4
&d=x038T6R-5vl7z8WbbFRu5Pcd6eqA4J3m2G_GLQnSVhwRXqDfR
psYcopbVWoq2cVWD-y8QU1s7Sm_uYSIiPi5m9l2uJ6VG5GJyrBR1DNA3rOnkFW4rnmPCyZzowhzXZIyU
LQL0r4EixvVUlOlRpWSIaZYbTzBnDFOY9YoGknM1I1IeFqUzCxdIQuM8laqp1pqp7aPdIcXhP3C0lbBP
GRWEyMSrNvbLXpQ4jCcNk-rqZpoL15wMV-6_siML09PEea-JEc2PzOjhbaZinIPfD5fmOo5eH7Z1W085
WqpRdKkJi-kbZuGsm5xZZJH0haLVkHvr9jyi3d2G7mZCat5rYtypbVLkoVXu5VOC5TsMXNpym7I2x3tr
7_zjhxUlb_R_tb3_y72h5ZjZQ8Ykn3mX20_DASISlTALHjEW8ASTTNUNL3XA6JXxTkvH-6Ff809B8E8-
-BwB8kZ8O_PgRyRJDXCmd-MH2_Pn9X5EAzY3tMTnxjwQj91vmLg
2

frame-2 picture

mdlqr:v2
?id=10238162
&n=2
&m=4
&d=SgwLP-iKKJph2SPKIcBZjuBZF_PpE4HRrMNgPDMCmOMxHKC6-
MClf6dJqpJEKfPskXPjJBA4KC9InOze0etjwlR-8eWQ6d0etXZYFsNJDKdMghnT_JghngiGZgiS_QvHx
zj-DnAyzxcd5P8B7HqvUCry9E8xVkdt8gtEEV-DuqEEi_5CfKjwS2DPmIM-T_YIwT6C67Mke8IZjOV4B
6Ndj8N42mUxZjQiccb3Ac92s_q13xNUtyfonSYqAUcsWH-CdgE9N_Niq4jxyQ4vE5VfGKlsYDuuWZUzv
TAYwTnFwFtYnmcsZ_OwTsDFgJelNyfVJXJYc326RvAa_Nw2SqKZQABxSK8Jwdq0mrrNNjrYbRon5dcyr
KG9BUl33tQE_9ntxbcdV9gQ_e9-6_zO9q7bn9GU0trnZik-t91XyikD91BmVdOjVFGmVVGl1UkN97uwl
qP8thTVVm1jXI3U2z0u6HewXC0gfc9TuSQT7Q2ZlSHd6eRSzrR4
3

frame-2 picture

mdlqr:v2
?id=10238162
&n=3
&m=4
&d=R4ahRwZ9Te5LTBlWePKscG0Se8PcbqCZEs16E1Mavr7sk3Npt
YA1qVB1E0U3SX7l7s6anOGMeHESzrSNqFJgnZUQ5JkmQdxWwmPJeuaSkEvMUnQuaKtosbto80DCzgKkW
c6IBcsqLzmTjQyTEagsCVRZdaEQB4PXfwEFs62c
&p=00000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000

Example SecureQR payload

Frame payload after decompression:

{
vc1: "eyJraWQiOiJkaWQ6d2ViOmRlbW8uYWRkLWlkLmRldiNodFFaWXIiLCJ0eXAiOiJkYytzZC1qd3QiLCJhbGciOiJFUzI1NiJ9",
vc2: '{"nbf":1770133791,"vct":"DemoCredential","_sd_alg":"sha-256","iss":"did:web:demo.add-id.dev","cnf":{"jwk":{"kty":"EC","crv":"P-256","x":"2PtPyYUN-JB_BJOuEP2FdS-3kH8OOiF0rUUkQ9TwcbM","y":"sOd2D4QBE6Dk_Q7m4kP_9EGZu_nMwNrWy6mZ31aRPJc"}},"exp":1927900191,"vc":{"@context":["https://www.w3.org/2018/credentials/v1"],"type":["VerifiableCredential","DemoCredential"],"credentialSubject":{"id":"did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbnYYhRGsVD5jshyJMpdtcAcJ2uhRw9c7gCKSrhoPFFndrzL2YqgLx3z3EJwtuJnt5rQVcBTG5ayTwtj8F5Ebj2ifLs5GmQtUd8ozFwENmYmYetPa9BBZLUNQgKh5QCSjBUx","_sd":["a57NKmuEMlNHcgqTHEGZI5eIEfj-bHl_6op58LNVEDI","Apq5uAgAHXwzkE7wFztFCw2q2YYTSJRz0JCojFW-jQg","JYIHcpbyIyGBQKwPDIuNzO26ivYzFfLtlZ-TOTIbh9Y"]},"credentialStatus":{"id":"https://add-id.dev/credential-status/2","type":"BitstringStatusListEntry","statusPurpose":"revocation","statusListIndex":28223805,"statusListCredential":"https://add-id.dev/credential-status/2","statusSize":1},"credentialSchema":{"id":"https://add-id.dev/v1/registry/schemas/d067196b-e4f1-46a5-958d-ac57d3ededb4","type":"FullJsonSchemaValidator2021"},"issuer":"did:web:demo.add-id.dev","issued":"2026-02-03T15:49:51.1545126+00:00","issuanceDate":"2026-02-03T15:49:51.1545126+00:00","validFrom":"2026-02-03T15:49:51.1545126+00:00","validUntil":"2031-02-03T15:49:51.1545126+00:00","expirationDate":"2031-02-03T15:49:51.1545126+00:00"},"iat":1770133791,"jti":"be626f05-679a-4bc7-94b6-588205eed96f"}',
vc3: "4XNDJg71L6eCtXg4KTorWJDkfYhqCM9LSmIS-X7yQsGPrS5BafkdcLUccSOGKhwldqSiqOcK2MOta6TRfvjivg~WyJlNTdBdkh4R1BUVzNMWnVPdXVyam9RIiwiYWdlIiwxMl0~eyJ0eXAiOiJrYitqd3QiLCJhbGciOiJFUzI1NiJ9eyJpYXQiOjE3NzAyODIyMDQsIm5iZiI6MTc3MDI4MjIwNCwiZXhwIjoxODMzMzk2MDU1LCJhdWQiOiIuLi4iLCJub25jZSI6Ii4uLiIsInNkX2hhc2giOiJrbHk3SUhfcUhRT1ZSTWViTm1yRVk3N0RqZlpsUzd6T3hMblJPT29QbXpNIn0PO-KJR4Wh5zMtks3CUNqbB6xv56H4tPvChB9YKekf8pP4FkfADsTp2J2_Kj-S0jDUy4xpa9n1y0LdgEBlKoKnw"
}

SD-JWT presentation after reassembly:

eyJraWQiOiJkaWQ6d2ViOmRlbW8uYWRkLWlkLmRldiNodFFaWXIiLCJ0eXAiOiJkYytzZC1qd3QiLCJh
bGciOiJFUzI1NiJ9.eyJuYmYiOjE3NzAxMzM3OTEsInZjdCI6IkRlbW9DcmVkZW50aWFsIiwiX3NkX2F
sZyI6InNoYS0yNTYiLCJpc3MiOiJkaWQ6d2ViOmRlbW8uYWRkLWlkLmRldiIsImNuZiI6eyJqd2siOns
ia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIyUHRQeVlVTi1KQl9CSk91RVAyRmRTLTNrSDhPT2l
GMHJVVWtROVR3Y2JNIiwieSI6InNPZDJENFFCRTZEa19RN200a1BfOUVHWnVfbk13TnJXeTZtWjMxYVJ
QSmMifX0sImV4cCI6MTkyNzkwMDE5MSwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3J
nLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkRlbW9
DcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6MmRtekQ4MWNnUHg
4VmtpN0pidXVNbUZZcldQZ1lveXR5a1VaM2V5cWh0MWo5S2JuWVloUkdzVkQ1anNoeUpNcGR0Y0FjSjJ
1aFJ3OWM3Z0NLU3Job1BGRm5kcnpMMllxZ0x4M3ozRUp3dHVKbnQ1clFWY0JURzVheVR3dGo4RjVFYmo
yaWZMczVHbVF0VWQ4b3pGd0VObVltWWV0UGE5QkJaTFVOUWdLaDVRQ1NqQlV4IiwiX3NkIjpbImE1N05
LbXVFTWxOSGNncVRIRUdaSTVlSUVmai1iSGxfNm9wNThMTlZFREkiLCJBcHE1dUFnQUhYd3prRTd3Rnp
0RkN3MnEyWVlUU0pSejBKQ29qRlctalFnIiwiSllJSGNwYnlJeUdCUUt3UERJdU56TzI2aXZZekZmTHR
sWi1UT1RJYmg5WSJdfSwiY3JlZGVudGlhbFN0YXR1cyI6eyJpZCI6Imh0dHBzOi8vYWRkLWlkLmRldi9
jcmVkZW50aWFsLXN0YXR1cy8yIiwidHlwZSI6IkJpdHN0cmluZ1N0YXR1c0xpc3RFbnRyeSIsInN0YXR
1c1B1cnBvc2UiOiJyZXZvY2F0aW9uIiwic3RhdHVzTGlzdEluZGV4IjoyODIyMzgwNSwic3RhdHVzTGl
zdENyZWRlbnRpYWwiOiJodHRwczovL2FkZC1pZC5kZXYvY3JlZGVudGlhbC1zdGF0dXMvMiIsInN0YXR
1c1NpemUiOjF9LCJjcmVkZW50aWFsU2NoZW1hIjp7ImlkIjoiaHR0cHM6Ly9hZGQtaWQuZGV2L3YxL3J
lZ2lzdHJ5L3NjaGVtYXMvZDA2NzE5NmItZTRmMS00NmE1LTk1OGQtYWM1N2QzZWRlZGI0IiwidHlwZSI
6IkZ1bGxKc29uU2NoZW1hVmFsaWRhdG9yMjAyMSJ9LCJpc3N1ZXIiOiJkaWQ6d2ViOmRlbW8uYWRkLWl
kLmRldiIsImlzc3VlZCI6IjIwMjYtMDItMDNUMTU6NDk6NTEuMTU0NTEyNiswMDowMCIsImlzc3VhbmN
lRGF0ZSI6IjIwMjYtMDItMDNUMTU6NDk6NTEuMTU0NTEyNiswMDowMCIsInZhbGlkRnJvbSI6IjIwMjY
tMDItMDNUMTU6NDk6NTEuMTU0NTEyNiswMDowMCIsInZhbGlkVW50aWwiOiIyMDMxLTAyLTAzVDE1OjQ
5OjUxLjE1NDUxMjYrMDA6MDAiLCJleHBpcmF0aW9uRGF0ZSI6IjIwMzEtMDItMDNUMTU6NDk6NTEuMTU
0NTEyNiswMDowMCJ9LCJpYXQiOjE3NzAxMzM3OTEsImp0aSI6ImJlNjI2ZjA1LTY3OWEtNGJjNy05NGI
2LTU4ODIwNWVlZDk2ZiJ9.4XNDJg71L6eCtXg4KTorWJDkfYhqCM9LSmIS-X7yQsGPrS5BafkdcLUccS
OGKhwldqSiqOcK2MOta6TRfvjivg~WyJlNTdBdkh4R1BUVzNMWnVPdXVyam9RIiwiYWdlIiwxMl0~eyJ
0eXAiOiJrYitqd3QiLCJhbGciOiJFUzI1NiJ9.eyJpYXQiOjE3NzAyODIzMjMsIm5iZiI6MTc3MDI4Mj
MyMywiZXhwIjoxODMzMzk2MTc0LCJhdWQiOiIuLi4iLCJub25jZSI6Ii4uLiIsInNkX2hhc2giOiJrbH
k3SUhfcUhRT1ZSTWViTm1yRVk3N0RqZlpsUzd6T3hMblJPT29QbXpNIn0.8K-murMMLBZdRscUHbk6gz
RFqBijEZXm1EUFWaydaMDVRWH_491S3f2-OMBNMQsXFKFgzGY2AWGnuHzBl1fAGg

SD-JWT decoded

Header:

{
"alg": "ES256",
"kid": "did:web:demo.add-id.dev#htQZYr",
"typ": "dc+sd-jwt"
}

Payload:

{
"_sd_alg": "sha-256",
"cnf": {
"jwk": {
"crv": "P-256",
"kty": "EC",
"x": "2PtPyYUN-JB_BJOuEP2FdS-3kH8OOiF0rUUkQ9TwcbM",
"y": "sOd2D4QBE6Dk_Q7m4kP_9EGZu_nMwNrWy6mZ31aRPJc"
}
},
"exp": 1927900191, // Feb 03 2031 15:49:51 GMT+0000
"iat": 1770133791, // Feb 03 2026 15:49:51 GMT+0000
"iss": "did:web:demo.add-id.dev",
"jti": "be626f05-679a-4bc7-94b6-588205eed96f",
"nbf": 1770133791, // Feb 03 2026 15:49:51 GMT+0000
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1"
],
"credentialSchema": {
"id": "https://add-id.dev/v1/registry/schemas/d067196b-e4f1-46a5-958d-ac57d3ededb4",
"type": "FullJsonSchemaValidator2021"
},
"credentialStatus": {
"id": "https://add-id.dev/credential-status/2",
"statusListCredential": "https://add-id.dev/credential-status/2",
"statusListIndex": 28223805,
"statusPurpose": "revocation",
"statusSize": 1,
"type": "BitstringStatusListEntry"
},
"credentialSubject": {
"_sd": [
"a57NKmuEMlNHcgqTHEGZI5eIEfj-bHl_6op58LNVEDI",
"Apq5uAgAHXwzkE7wFztFCw2q2YYTSJRz0JCojFW-jQg",
"JYIHcpbyIyGBQKwPDIuNzO26ivYzFfLtlZ-TOTIbh9Y"
],
"id": "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbnYYhRGsVD5jshyJMpdtcAcJ2uhRw9c7gCKSrhoPFFndrzL2YqgLx3z3EJwtuJnt5rQVcBTG5ayTwtj8F5Ebj2ifLs5GmQtUd8ozFwENmYmYetPa9BBZLUNQgKh5QCSjBUx"
},
"expirationDate": "2031-02-03T15:49:51.1545126+00:00",
"issuanceDate": "2026-02-03T15:49:51.1545126+00:00",
"issued": "2026-02-03T15:49:51.1545126+00:00",
"issuer": "did:web:demo.add-id.dev",
"type": [
"VerifiableCredential",
"DemoCredential"
],
"validFrom": "2026-02-03T15:49:51.1545126+00:00",
"validUntil": "2031-02-03T15:49:51.1545126+00:00"
},
"vct": "DemoCredential"
}

Key Binding JWT decoded

Header

{
"typ": "kb+jwt",
"alg": "ES256"
}

Payload

{
"iat": 1770282323, // Feb 05 2026 09:05:23 GMT+0000
"nbf": 1770282323, // Feb 05 2026 09:05:23 GMT+0000
"exp": 1833396174, // Feb 05 2028 20:42:54 GMT+0000
"aud": "...",
"nonce": "...",
"sd_hash": "kly7IH_qHQOVRMebNmrEY77DjfZlS7zOxLnROOoPmzM"
}