[Nfd-dev] [EXT]Re: Update on NDNCERT protocol
Davide Pesavento
davidepesa at gmail.com
Mon Apr 13 12:28:57 PDT 2020
On Mon, Apr 13, 2020 at 8:18 AM Junxiao Shi via Nfd-dev
<nfd-dev at lists.cs.ucla.edu> wrote:
>
> Hi Zhiyi
>
> I'm trying to implement the protocol in NDNts. I've pasted my implementation of the crypto operations at the end of this message.
> I have unit-tested these operations and they seem to be working. Since Node.js implements crypto via OpenSSL, this implies OpenSSL has sufficient primitives for crypto needed by NDNCERT.
>
> I noticed some more issues in the protocol.
>
>
> Several steps specify the use of signed Interest.
> They should also specify which uniqueness assurance fields are required in the SignatureInfo: SignatureNonce, SignatureTime, SignatureSeqNum.
>
>
> Several steps specify MustBeFresh in Interest, but lacks FreshnessPeriod in Data. A Data without FreshnessPeriod cannot satisfy an Interest with MustBeFresh.
> Given signed Interests are unique, it's unnecessary to include MustBeFresh.
>
>
> Several TLVs are specified as *OCTET in ABNF, but text says "human readable string".
> It also needs to specify what codec to use, such as UTF-8. If you want to restrict to ASCII instead, specify as *CHAR.
I would NOT recommend to restrict ourselves to ASCII, it's 2020...
> CA profile packet should have FinalBlockId (set to the same as last name component), so that it is compatible with segmentation convention.
>
>
> NEW response uses "challenge" TLV-TYPE, but it lacks number assignment.
>
>
> The AES-GCM session key is established by ECDH followed by HKDF.
> WebCrypto cannot directly derive the HKDF key from ECDH. Instead, the workflow is:
>
> derive bits from ECDH
> import bits as HKDF key
> derive AES-GCM key from HKDF key
>
> The protocol specifies that the AES-GCM key is 128 bits. However, it does not specify how many bits go into the HKDF key.
> Given ECDH on P-256 curve can establish a shared secret of 256 bits, I'd recommend specifying 256 bits.
I'm not sure why this needs to be specified. The ECDH shared secret is
normally the X coordinate of the calculated point, i.e. 32 bytes with
NIST P-256. By saying that one must run HKDF with the ECDH shared
secret as input, it's pretty obvious that you use the entire secret,
nothing more, nothing less. I don't think there's any ambiguity here.
>
>
> In PROBE/CHALLENGE request, parameter-value is specified as a string.
> Some probe methods and challenges may natively use binary information. Thus, this field could be defined as binary instead.
> parameter-key could stay as string, and defined as *CHAR if restricted to ASCII.
>
>
> Yours, Junxiao
>
>
>
> const ECDH_PARAMS: EcKeyGenParams & EcKeyImportParams = {
> name: "ECDH",
> namedCurve: "P-256",
> };
>
> export async function generateEcdhKey(): Promise<CryptoKeyPair> {
> return crypto.subtle.generateKey(ECDH_PARAMS, false, ["deriveBits"]);
> }
>
> export async function importEcdhPub(raw: Uint8Array): Promise<CryptoKey> {
> return crypto.subtle.importKey("raw", raw, ECDH_PARAMS, true, []);
> }
>
> export async function exportEcdhPub(key: CryptoKey): Promise<Uint8Array> {
> const raw = await crypto.subtle.exportKey("raw", key);
> return new Uint8Array(raw);
> }
>
> export async function makeSessionKey(
> ecdhPvt: CryptoKey,
> ecdhPub: CryptoKey,
> salt: Uint8Array,
> requestId: Uint8Array,
> ): Promise<CryptoKey> {
> const hkdfBits = await crypto.subtle.deriveBits({ name: "ECDH", public: ecdhPub }, ecdhPvt, 256);
> const hkdfKey = await crypto.subtle.importKey("raw", hkdfBits, "HKDF", false, ["deriveKey"]);
> return crypto.subtle.deriveKey(
> {
> name: "HKDF",
> salt,
> info: requestId,
> hash: "SHA-256",
> } as any,
> hkdfKey,
> {
> name: "AES-GCM",
> length: 128,
> },
> false,
> ["encrypt", "decrypt"],
> );
> }
>
> export interface Encrypted {
> iv: Uint8Array;
> ciphertext: Uint8Array;
> }
>
> export async function sessionEncrypt(key: CryptoKey, plaintext: Uint8Array): Promise<Encrypted> {
> const iv = crypto.getRandomValues(new Uint8Array(12));
> const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, plaintext);
> return { iv, ciphertext: new Uint8Array(ciphertext) };
> }
>
> export async function sessionDecrypt(key: CryptoKey, { iv, ciphertext }: Encrypted): Promise<Uint8Array> {
> const plaintext = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ciphertext);
> return new Uint8Array(plaintext);
> }
>
> _______________________________________________
> Nfd-dev mailing list
> Nfd-dev at lists.cs.ucla.edu
> http://www.lists.cs.ucla.edu/mailman/listinfo/nfd-dev
More information about the Nfd-dev
mailing list