<div dir="ltr"><div>Hi Zhiyi</div><div><br></div><div>The following responses are made on this protocol revision:</div><div><a href="https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.2/68dd20c6457ffb6d57aac3eb7e06f0497dd4053a" target="_blank">https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.2/68dd20c6457ffb6d57aac3eb7e06f0497dd4053a</a>  <br></div><div><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><font size="4">different assigned numbers</font></div><div>Some assigned numbers differ between protocol (left) and implementation (right).</div><div>NEW vs _NEW</div><div>CHALLENGE vs _CHALLENGE</div><div>DOWNLOAD vs _DOWNLOAD</div><div>EncryptedPayload: 602 vs 630</div><div>InitialVector: 605 vs 632<br></div></div></blockquote><div><br></div><div>Addressed in the latest protocol Wiki page.</div></div></div></blockquote><div><br></div><div>Incomplete.</div><div><ul><li>PROBE in section 2.1 vs _PROBE in section 2.3.1 examples</li><li>NEW in section 2.1 vs _NEW in section 2.3.2 examples</li><li>CHALLENGE in section 2.1 vs _CHALLENGE in section 2.3.3 examples</li><li>DOWNLOAD in section 2.1 vs _DOWNLOAD in section 2.3.4 examples</li></ul></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div><font size="4">nonstandard base64</font></div><div>The CA expects a nonstandard base64 encoding format: encoder must insert a newline after every 64 bytes.</div><div>Either the implementation should remove this requirement, or the protocol should specify this requirement.</div></div></blockquote><div><br></div><div>Sorry, could you elaborate on this? I think previously Ashlesh and Alex met a similar problem before.</div><div>Are you saying the ECDH key base64?</div><div>I checked the code at CA server. I didn't add or require any newlines when parsing base64. I used the base64 API from ndn-cxx:</div><div><br></div><div>```</div><div><div style="color:rgb(0,0,0);font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;line-height:18px;white-space:pre-wrap"><div style="line-height:18px"><div><span style="color:rgb(0,0,255)">uint8_t</span>*</div><div>ECDHState::deriveSecret(<span style="color:rgb(0,0,255)">const</span> std::string& peerKeyStr)</div><div>{</div><div>  <span style="color:rgb(0,0,255)">namespace</span> t = ndn::security::transform;</div><br><div>  OBufferStream os;</div><div>  t::bufferSource(peerKeyStr) >> t::base64Decode() >> t::streamSink(os);</div><div>  <span style="color:rgb(0,0,255)">auto</span> result = os.buf();</div><br><div>  <span style="color:rgb(0,0,255)">return</span> <span style="color:rgb(0,0,255)">this</span>->deriveSecret(result->data(), result->size());</div><div>}</div></div></div></div><div> ```</div><div><b>TODO: </b>solve the problem in a later commit.</div></div></div></blockquote><div><br></div><div><font face="monospace">ndn::security::transform::base64Decode(true)</font> handles PEM format (<a href="https://tools.ietf.org/html/rfc1421" target="_blank">RFC 1421</a> section 4.3.2.4), which requires a newline after every 64 octets. See <a href="https://redmine.named-data.net/issues/3741#note-12" target="_blank">https://redmine.named-data.net/issues/3741#note-12</a> .

</div><div>Normally, base64 means the format defined in <a href="https://tools.ietf.org/html/rfc4648#section-4" target="_blank">RFC 4648 section 4</a>, which disallows any newlines. </div><div>According to <a href="https://tools.ietf.org/html/rfc4648#section-3.1" target="_blank">RFC 4648 section 3.1</a>, <br></div><div><br></div><font face="monospace">   MIME [4] is often used as a reference for base 64 encoding.  However,<br>   MIME does not define "base 64" per se, but rather a "base 64 Content-<br>   Transfer-Encoding" for use within MIME.  As such, MIME enforces a<br>   limit on line length of base 64-encoded data to 76 characters.  MIME<br>   inherits the encoding from Privacy Enhanced Mail (PEM) [3], stating<br>   that it is "virtually identical"; however, PEM uses a line length of<br>   64 characters.  The MIME and PEM limits are both due to limits within<br>   SMTP.<br><br>   Implementations MUST NOT add line feeds to base-encoded data unless<br>   the specification referring to this document explicitly directs base<br>   encoders to add line feeds after a specific number of characters.<br><br></font><div>The reason for PEM to insert newlines is to fit within SMTP's line length limit. This consideration does not apply to JSON. Therefore, the recommendation is:</div><div><ul><li>Define the protocol to use base64 format as specified in RFC 4648 section 3.1 (you should cite the RFC section)</li><li>Decode base64 format using <font face="monospace">ndn::security::transform::base64Decode(false)</font> .</li><li>Encode base64 format using <font face="monospace">ndn::security::transform::base64Encode(false)</font> .</li></ul></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div><font size="4">Signed Interest format mismatch<br></font></div><div>Protocol specifies Signed Interest format from NDN Packet Format v0.3.</div><div>The CA expects 2014 Signed Interest format.</div><div>Either one should change to match the other.</div></div></blockquote><div><br></div><div>Addressed in the latest protocol Wiki page.</div></div></div></blockquote><div><br></div><div>Incomplete. Example does not match protocol definition.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div><font size="4">NEW/CHALLENGE statue encoding<br></font></div><div>Protocol specifies "status" field of NEW response is encoded as a number.</div><div>CA implementation encodes it as a string.</div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>"remaining-tries" and "remaining-time" fields have same problem.</div></div></blockquote><div> </div><div><div>Addressed in the latest protocol Wiki page.</div></div></div></div></blockquote><div><br></div><div>OK.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div><font size="4">reuse ECDH key<br></font></div><div>CA is reusing the same ECDH key for all requests. It should generate a unique ECDH key for each request.<br></div></div></blockquote><div><br></div><div>This is truly a problem.</div><div><b>TODO: </b>I will move ECDH state to each request state.</div></div></div></blockquote><div><br></div><div>There's no need to save ECDH state on the CA.</div><div>CA can generate ECDH key pair while processing the NEW command and compute the AES key.</div><div>The ECDH private key can be destroyed immediately, and the CA only needs to save the AES key for later.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div><font size="4">ECDH salt encoding</font></div><div>Protocol does not specify how salt is encoded.</div><div>CA implementation generates 8 bytes of random value, interprets it as uint64, and prints in decimal string.</div><div>Protocol does not specify which endianness is used in this conversion.<br></div></div></blockquote><div><br></div><div>Addressed in the latest protocol Wiki page.<br></div></div></div></blockquote><div><br></div><div>Protocol still does not specify the endianness to convert [8]uint8 into uint64.</div><div>Also, why not use base64, like the other fields?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div><font size="4">ECDH info</font></div><div>Protocol does not specify what is used as "info" in ECDH.</div><div>CA implementation assumes F0F1F2F3F4F5F6F7F8F9.<br></div></div></blockquote><div><br></div><div>Addressed in the latest protocol Wiki page.</div></div></div></blockquote><div><br></div><div>According to <a href="https://tools.ietf.org/html/rfc5869" target="_blank">RFC 5869 </a>section 3.2, the 'info' field should contain application-specific information, such as user identities.</div><div>Therefore, you can get better security by using the wire encoding of the certificate as 'info' field.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><font size="4">hkdf crash</font><div></div><div><a href="https://github.com/named-data/ndncert/blob/aae119aeb9b5387f2fd8f80c56ee8cbfe8c15988/src/crypto-support/crypto-helper.cpp#L170" target="_blank">ECDHState::deriveSecret</a> assumes ECDH_compute_key to return 0 on error, but it actually returns -1.</div><div>Thus, when I provide incorrect ECDH public key, ECDHState::deriveSecret does not detect the error, but assigns -1 to the length field.<br></div><div>Consequently, CaModule::onNew passes secretLen=-1 to hkdf(), which then segfaults.<br></div></div></blockquote><div><br></div><div><b>TODO: </b>I will solve the problem by correcting the comparison.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div><font size="4">AES 128 vs AES 256</font></div><div>Protocol specifies 128-bit AES, but CA expects 256-bit AES.</div></div></blockquote><div><br></div><div>Addressed in the latest protocol Wiki page.</div></div></div></blockquote><div><br></div><div>Using 256-bit AES compromises security property of the protocol, because ECDH using P-256 curve can only give you 128-bit of entropy.</div><div>See <a href="https://www.lists.cs.ucla.edu/pipermail/nfd-dev/2018-November/003459.html" target="_blank">https://www.lists.cs.ucla.edu/pipermail/nfd-dev/2018-November/003459.html</a> .<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div><font size="4">AES mode</font></div><div>Protocol does not specify AES mode. It should say "AES-CBC".<br></div></div></blockquote><div><br></div><div>Addressed in the latest protocol Wiki page.</div></div></div></blockquote><div><br></div><div>OK.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div><font size="4">missing pin-code crash</font></div><div>After selecting "pin" challenge, the next CHALLENGE Interest payload should have "pin-code" key.</div><div>When I misspell it as "pin", the CA crashes because it cannot find "pin-code" key.</div></div></blockquote><div><br></div><div><b>TODO: </b>I will solve the problem by having a try block.<br></div></div></div></blockquote><div><br></div><div>OK.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div><font size="4">negative remaining time</font></div><div>For some reason, CA gives me a negative remaining-time value after I enter a wrong code.</div><div>(these are not original JSON, but console.log output, but nothing is modified)<br></div><div><br></div><b>CHALLENGE request 0</b><br><div>{ 'selected-challenge': 'pin' }<br></div><div><b>CHALLENGE response 0</b><br></div><div>{<br>  status: '1',<br>  'challenge-status': 'need-code',<br>  'remaining-tries': '3',<br>  'remaining-time': '3600'<br>}<br><b>CHALLENGE request 1, wrong code</b><br>{ 'selected-challenge': 'pin', 'pin-code': '855899' }<br></div><div><b>CHALLENGE response 1</b><br></div><div>{<br>  status: '1',<br>  'challenge-status': 'wrong-code',<br>  'remaining-tries': '2',<br>  'remaining-time': '-2046070806'<br>}<br></div><div><b>CHALLENGE request 2</b><br></div><div>{ 'selected-challenge': 'pin', 'pin-code': '850899' }<br></div><div><b>CHALLENGE response 2</b><br></div><div>{<br>  status: '3',<br>  'challenge-status': 'success',<br>  'remaining-tries': '0',<br>  'remaining-time': '0',<br>  'certificate-id': '8930813521911288448'<br>}<br></div></div></blockquote><div><br></div><div><b>TODO: </b>I will solve the problem.</div></div></div></blockquote><div><br></div><div>OK.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div><font size="4">Purpose of certificate-id<br></font></div><div>I wonder what's the purpose of "certificate-id" field? It's not needed in DOWNLOAD or any other command.<br></div></div></blockquote><div><br></div><div>It's not needed in any commands.</div><div>The original purpose of certificate-id is to tell the client what's the expected certificate-id after the DOWNLOAD command.</div><div>After the client fetches the cert, it can check whether the last component of cert is equal to certificate-id, though this is not implemented and may not have real sense.</div><div>Yes, I think I could simply remove this.</div><div><br></div><div>This has already been removed in the lastest Wiki page.</div><div><b>TODO: </b>I will remove this in the implementation soon.</div></div></div></blockquote><div><br></div><div>The certificate-id information is useful, and the protocol can be further simplified:</div><div><ul><li>Instead of certificate-id, add a certificate-name field to the successful CHALLENGE response. It should contain the full name (i.e. including ImplicitDigestSha256Component) of the certificate Data packet.</li><li>The certificate-name needs to be encoded in base64 of the Name binary format. It cannot use URI encoding, because URI encoding of certain field (e.g. version and segment) is not defined in the packet format, and thus may not be supported by all nodes.</li><li>Eliminate DOWNLOAD command.</li><li>Client can retrieve the certificate by expressing an Interest with the certificate name.</li><li>Since the certificate-name field contains the full name, the client can rest assumed that the certificate is indeed issued for this request.</li></ul></div><div><br></div><div>Yours, Junxiao</div></div></div>