decentralized-identity / did-jwt

Create and verify DID verifiable JWT's in Javascript
Apache License 2.0
336 stars 71 forks source link

JWE for P-256 #225

Open bshambaugh opened 2 years ago

bshambaugh commented 2 years ago

I see https://w3c-ccg.github.io/lds-jws2020/ .

This suite support cryptographic agility, see [RFC7696]. This table maps a key type to a subset of [IANA_JOSE] supported signing and encryption algorithms. kty crvOrSize signature keyAgreement encryption OKP Ed25519 EdDSA ECDH-ES+A256KW OKP X25519 ECDH ECDH-ES+A256KW EC secp256k1 ES256K ECDH ECDH-ES+A256KW EC P-256 ES256 ECDH ECDH-ES+A256KW EC P-384 ES384 ECDH ECDH-ES+A256KW RSA 2048 PS256 RSA-OAEP

I would like the stuff in bold because I would like JWE with P-256?

Here is some babbling from earlier: [edit most of this thread is blabbering]

This is kind of strange looking:

const kek = concatKDF(sharedSecret, keyLen, alg) const res = xc20pEncrypter(kek)(cek)

function xc20pEncrypter(key: Uint8Array): (cleartext: Uint8Array, aad?: Uint8Array) => EncryptionResult { const cipher = new XChaCha20Poly1305(key) return (cleartext: Uint8Array, aad?: Uint8Array) => { const iv = randomBytes(cipher.nonceLength) const sealed = cipher.seal(iv, cleartext, aad) return { ciphertext: sealed.subarray(0, sealed.length - cipher.tagLength), tag: sealed.subarray(sealed.length - cipher.tagLength), iv, } } }

source: https://github.com/decentralized-identity/did-jwt/blob/master/src/xc20pEncryption.ts#L126-L204

[bshambaugh] Maybe I should ask with an issue what is needed.I'm trying to reverse engineer the code.https://www.rfc-editor.org/rfc/rfc7518.html#section-4.6I need instead:

| ECDH-ES+A256KW | ECDH-ES using Concat KDF and CEK wrapped with | | | "A256KW"

[bshambaugh] I can get A256KW here: https://github.com/StableLib/stablelib/blob/master/packages/aes-kw/aes-kw.test.ts aes-kw.test.ts

// Copyright (C) 2020 Tobias Looker // MIT License. See LICENSE file for details.

import { AESKW } from "./aes-kw"; import { encode, decode } from "@stablelib/hex";

https://github.com/[StableLib/stablelib](https://github.com/StableLib/stablelib)|StableLib/stablelibStableLib/stablelib

[bshambaugh]

I have been eying: https://github.com/panva/jose/tree/main/src/jwe [bshambaugh]

And maybe the jose npm library is the way to go. I still need to fiddle with my JWK, PEM, or DER representation.

[bshambaugh]

the results of that: https://gist.github.com/bshambaugh/4014f8a11025b42774b75f2bbd3f9be7 (edited)

[bshambaugh]

going through the xc20pEncrypter code is manual mode. [bshambaugh]

I'm trying to match this interface with my function: https://github.com/decentralized-identity/did-jwt/blob/master/src/JWE.ts#L55-L60 (edited) JWE.ts

export interface Encrypter { alg: string enc: string encrypt: (cleartext: Uint8Array, protectedHeader: ProtectedHeader, aad?: Uint8Array) => Promise encryptCek?: (cek: Uint8Array) => Promise

https://github.com/[decentralized-identity/did-jwt](https://github.com/decentralized-identity/did-jwt)|decentralized-identity/did-jwtdecentralized-identity/did-jwt

[bshambaugh]

It's not really clear how the JOSE library is going to give me that easily. I think if I can match the interface it will work with the rest of the library. [bshambaugh]

well hmm....here's an idea of how the JOSE library looks:https://github.com/panva/jose/blob/main/docs/functions/jwe_flattened_decrypt.flattenedDecrypt.md#readme

[bshambaugh]

const jwe = { ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', iv: '8Fy7A_IuoX5VXG9s', tag: 'W76IYV6arGRuDSaSyWrQNg', encrypted_key: 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0' }

const { plaintext, protectedHeader, additionalAuthenticatedData } = await jose.flattenedDecrypt(jwe, privateKey)

console.log(protectedHeader) const decoder = new TextDecoder() console.log(decoder.decode(plaintext)) console.log(decoder.decode(additionalAuthenticatedData))

[bshambaugh]

compare to: https://github.com/decentralized-identity/did-jwt/blob/master/src/JWE.ts#L37-L44

[bshambaugh]

export interface JWE { protected: string iv: string ciphertext: string tag: string aad?: string recipients?: Recipient[] }

[bshambaugh]

they should ultimately both follow a standard.

[bshambaugh]

"https://www.rfc-editor.org/rfc/rfc7516 , https://www.rfc-editor.org/rfc/rfc7518

bshambaugh commented 2 years ago

This ramble thread may not make sense to many. I'm trying to go through the https://github.com/decentralized-identity/did-jwt/blob/master/src/xc20pEncryption.ts code and seeing how I can map over to JWE for P-256.

bshambaugh commented 2 years ago

psudocode for what I think a code chunk might look like: const kek = concatKDF(sharedSecret, keyLen, alg) const res = aeskw(kek)(cek) /// maybe this is what "using Concat KDF and CEK wrapped with | | | "A256KW"" looks like

something says, maybe I don't need to do this I know @ oed always wants things to be light weight though ... so fitting the output to the existing interfaces (if even possible) to the npm package JOSE may not be the way to go... ??

bshambaugh commented 2 years ago

I feel like I have to match all (or most) of these interfaces for JWE encryption/decryption with P-256: https://github.com/decentralized-identity/did-jwt/blob/master/src/JWE.ts#L11-L66

bshambaugh commented 2 years ago

Aside from RFC7516 and RFC7518 this is the best documentation I have found for JWE: https://www.youtube.com/watch?v=0r-ZDqpYYYI (JSON Web Encryption[JWE] - JWT_3 -- 100bytes.com)

bshambaugh commented 2 years ago

Here is how Transmute does it for P-384: https://github.com/transmute-industries/did-key.js/blob/c9a478da12508fefd8018d82ab95638ea6980dd7/packages/did-key-web-crypto/README.md#ecdh-esa256kw

bshambaugh commented 2 years ago

Here are some of my notes ed25519Encryption

I realize I have not read every word in RFC 7516 and RFC 7518. I will do this tomorrow. Like a drunkard walking home, I gradually gather information and understanding.

bshambaugh commented 2 years ago

I believe xc20encrpyter should be replaced with a function using aes-gcm instead or possibly kept as xc20encrypter (chacha20-poly1305). it corresponds to the "ec" parameter. a256kw corresponds to the "alg" parameter. Thankfully, I also have David Wong's book. I need to spend time perusing this material rather than skipping around.

bshambaugh commented 2 years ago

compare content encryption algorithm "aes-gcm" with key wrapping "a256kw"

mirceanis commented 2 years ago

In the current codebase, there were some assumptions made that don't hold well against the present day. The names of the encrypters/decrypters are not sufficient to describe what they do.

The algorithm for content encryption key wrapping is ECDH-ES+XC20PKW which means this:

If I'm not mistaken, the content is then encrypted using XChaha20Poly1305 too, but using the content key cek


To add P-256 ECDH-ES+A256PKW you would be changing the algorithm from above to use P-256 recipient and ephemeral keys to perform the ECDH-ES (instead of the X25519 keys we already use), and then using AES256KW to wrap the content encryption key.

Then, I believe the content is encrypted using A256GCM.


The P-256 functionality can be imported from elliptic and I believe the AES256KW and A256GCM are exported by stablelib, so there should be no new library imports. @oed should be as happy about this as I am :)

If you want to start implementing this, please do so with minimal changes to the rest of the codebase. If such changes are necessary, please flag them and we can create separate small PRs for them. This is preferable to creating one BIG PR.

Have fun!

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

bshambaugh commented 2 years ago

@mirceanis , I have a big checklist of what I need to do, and this doesn't hit the top. Thanks for outlining this. I'll keep it in mind for another time around. Should I close this issue or stash it somewhere so I don't forget?

mirceanis commented 2 years ago

I'll leave this open and pin it so that it doesn't get automatically staled. It seems like we have the tools in place to add this required algorithm (P-256 ECDH-ES+A256PKW). What we lack is bandwidth :) Perhaps if we rephrase it better or split it into smaller tasks some other folks would like to tackle this.

If you plan to work on this or a connected issue please say so, so that we don't overlap by mistake.

bshambaugh commented 1 year ago

_The following is a file on my computer called description_of_did_jwt.txt in /home/ubuntu/Downloads (last modified 8/31/2022). I am posting it here to grease the skids in my brain and for easy reference:


'ECDH-1PU+XC20PKW'

ECDH-ES+A256KW

DID you know that I've been working to amend the did-jwt library to include support for the secp256r1 curve? Here are some interpretations of the library I chose to JOT down:

Internal Interdependencies:


/// do this same decomposition with ts-ucan to see if you can derive a a verifiable cred from did-jwt (from did-jwt-vc) ... ts-ucan not on computer (need to download)

bshambaugh commented 1 year ago

The above writing must have been written between PR https://github.com/decentralized-identity/did-jwt/pull/240 and https://github.com/decentralized-identity/did-jwt/pull/246

TallTed commented 1 year ago

@bshambaugh @mirceanis — If you intend for this thread (which I came to via W3C CCG 2/7/23 - Multi-Signature Verifiable Credentials and Conditional Proofs — AgendaRaw transcript, Raw audio, Raw video) to be digested by others, it will be valuable to cycle through your previous comments and insert markdown tags to format things more clearly, at least and especially for the code-chunks where indentation can help a lot with comprehensibility, and to strip out the repetitive "talking to yourself" [bshambaugh] lines in the initial comment, even if it is "mostly blabbering".

bshambaugh commented 1 year ago

@TallTed , I appreciate the comment. I will need to peruse and refine. It is typical of me to have a quite messy thread and then speak with more succinctness as I gain understanding of a previously unfamiliar subject. This thread was useful to me because it allowed me to organize my developing comprehension. I linked to this Issue to provide context of my intentions to Jack, but I am leaning toward the prediction of this not interfering with his efforts. I think your suggestion of greater organization could help accomplish the task of implementing JWE for P256. Perhaps, I could write something more succinct and then point to this rougher draft.