Hey Mike,

Thanks for the narrative.  I think you might not be thinking quite as
lazily as some hackers :)  The lazy hacker can cover 99+% of cases with the
following few lines of JS, which could easily be encoded in an appendix:

-----BEGIN-----
RSA_1024_PREFIX =
"30819F300D06092A864886F70D010101050003818D00308189028181";
RSA_2048_PREFIX =
"30820122300D06092A864886F70D01010105000382010F003082010A02820101";
RSA_SUFFIX      = "0203010001";

function SPKI_hex(jwk) {
  if (jwk.kty != "RSA" || jwk.e != "AQAB") {
    throw "Can't encode this";
  }
  if (jwk.n.length == 171) {
    return RSA_1024_PREFIX + b64_to_hex(jwk.n) + RSA_SUFFIX;
  } else if (jwk.n.length == 342) {
    return RSA_2048_PREFIX + b64_to_hex(jwk.n) + RSA_SUFFIX;
  }
  throw "Can't encode this";
}
-----END-----

This is pretty much the encoding design philosophy embraced by PKCS#1
itself:
https://tools.ietf.org/html/rfc3447#section-9.2

Also, if you want to analyze ASN.1 structs very quickly:
http://lapo.it/asn1js/

I have no love for ASN.1, but it's not really any more rocket science than
other binary encodings.

--Richard


On Tue, Mar 10, 2015 at 10:16 PM, Mike Jones <[email protected]>
wrote:

>  I’ve always loved learning new things, so I decided yesterday to try to
> learn first-hand how to write code that emitted X.509 SubjectPublicKeyInfo
> (SPKI) values from scratch.  By “from scratch”, I mean using development
> tools without built-in X.509 or ASN.1 support.
>
>
>
> I took this on because of Stephen’s suggestion
> http://www.ietf.org/mail-archive/web/jose/current/msg04954.html that
> people could just hash the SPKI values to create a key thumbprint.  Given
> I’d helped create the JSON-based hash input described in
> http://tools.ietf.org/html/draft-ietf-jose-jwk-thumbprint-03, I wanted to
> give his alternative suggestion a fair shake (and learn some new things
> along the way).  This admittedly stream-of-consciousness and overly long
> message describes my expedition to date…
>
>
>
> Thus far, I’ve spent 5 hours trying to learn to do this.  I spent about
> the first two hours searching for examples of creating the bytes of X.509
> certificates or SubjectPublicKeyInfo values without using ASN.1 and/or
> X.509 libraries.  I failed.
>
>
>
> Next, I tried to read the authoritative reference for what’s in the SPKI
> field – the X.509 spec.  Unfortunately,
> http://www.itu.int/rec/T-REC-X.509/en told me “This text was produced
> through a joint activity with ISO and IEC. According to the agreement with
> our partners, this document is only available through payment.”  Since
> most developers would stop at that point, I did too.
>
>
>
> After that, I changed tacks and tried to find examples of sample
> certificates with commentary on what all the values mean – the kind of info
> developers would want when coding this.  I had better luck with that.
> After about another hour of Web searching, I found this really useful
> example: http://tools.ietf.org/html/rfc7250#appendix-A.  I also found
> this one: http://www.jensign.com/JavaScience/dotnet/JKeyNet/index.html.
> Going through them byte-by-byte enabled me to reverse engineer some of the
> ASN.1 and X.509 constructs used.
>
>
>
> Things I learned by looking at these 1024-bit RSA public key
> representations included:
>
> ·        ASN.1 uses byte-aligned Tag-Length-Value encodings.
>
> ·        The tags for SEQUENCE, OID, NULL, BIT STRING, and INTEGER are
> respectively 0x30, 0x06, 0x05, 0x03, and 0x02.
>
> ·        These Length values are encoded as follows:
>
> o   159 – 0x81 0x9f
>
> o   9 – 0x09
>
> o   0 – 0x00
>
> ·        The OID 1.2.840.113549.1.1.1 is encoded in 9 bytes as 0x2a 0x86
> 0x48 0x86 0xf7 0x0d 0x01 0x01 0x01.
>
> ·        The OID is followed by an ASN.1 NULL - 0x05 0x00.
>
> ·        The RSA Key is represented as an encapsulated bit field.
>
> ·        There is an apparently unused zero byte (the 22nd byte of the
> SPKI field in the RFC 7250 example) as the first byte of this bit field.
>
> ·        The rest of the bit field contains concatenated representations
> of the modulus and the exponent as ASN.1 INTEGERs.
>
> ·        The 1024 bit modulus is represented in 129 bytes, with the first
> byte being zero.
>
>
>
> This brought me up to hour four.  Next, I went looking for a 2048 bit cert
> to learn from (especially since JWA requires 2048+ bit RSA keys).  I found
> http://fm4dd.com/openssl/certexamples.htm and chose
> 2048b-rsa-example-cert.der, from which I also learned:
>
> ·        These length values are encoded as follows:
>
> o   290 – 0x82 0x01 0x22
>
> o   257 – 0x82 0x01 0x01
>
> ·        From this, I deduced (possibly incorrectly J) that if the high
> bit of the first length byte is 0, the remaining 7 bits represent the
> length, but if the high bit of the first length byte is 1, the remaining 7
> bits represent the number of bytes used to represent the actual length.
> (Hence the use of 0x81 for representing values in the range 128-255 and the
> use of 0x82 for representing values in the range 256-32767.)
>
> ·        Length values are represented in big-endian byte order.
>
> ·        The 2048 bit key representation also starts with an apparently
> unused zero byte.
>
> ·        The 2048 bit modulus is represented by 257 bytes, with the first
> byte being zero.
>
>
>
> Things I haven’t yet learned that I’d need to know to really write this
> code:
>
> ·        How are the OIDs in the table at
> http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#appendix-A
> represented as ASN.1 OID values?
>
> ·        Are multiple OIDs sometimes present before the ASN.1 NULL, and
> if so, which algorithms require which sets of OIDs in what order?
>
> ·        Is there always the apparently unused zero byte in the key
> representation or if not, when is it present and absent?
>
> ·        Is there always a leading zero byte in the RSA modulus or if
> not, when is it present and absent?
>
> ·        How are elliptic curve keys represented?
>
>
>
> This brought me up to about the fifth hour of my investigation, and I
> decided to stop and write up my findings to date.  Highlighted versions of
> the example certificate from RFC 7250 and the SPKI value from fm4dd.com
> are attached, should any of you want to follow along with my reverse
> engineering.  Tags are yellow.  Lengths are green.  OIDs are purple.  The
> apparently unused byte is red.  Key values are blue.
>
>
>
> I readily admit that I could have easily missed something while
> searching.  If someone can point me to self-contained descriptions of this
> information, I’d love to see them!
>
>
>
> ==== CONCLUSIONS ====
>
>
>
> 1.  I think it would be a fine thing to do to write an RFC describing the
> mapping between key values and their SPKI representations.  This could take
> the form of a cookbook with entries like “For a 2048 bit RSA key using
> RSASSA with SHA-256, emit these bytes, filling in slots A and B in the
> template with the 256 bites of the mantissa and the 3 bytes of the
> exponent”.  Based on my searching, I don’t think this information exists
> anywhere in a self-contained form accessible to developers (but I could be
> wrong, of course).  I’m not going to personally do it, but if any of you
> want go for it, have at it!
>
>
>
> 2.  If my experience is representative, telling developers to just hash
> the SPKI representation of a JWK won’t be very effective unless they
> already have X.509 support.  Most will probably give up well before the 5
> hours that I’ve invested to get this this partial understanding of what I’d
> need to know.  If my experience is representative,
> draft-ietf-jose-jwk-thumbprint will be much easier to implement for these
> developers.
>
>
>
>                               Trying to live in the shoes of developers,
>
>                                                             -- Mike
>
>
>
> _______________________________________________
> jose mailing list
> [email protected]
> https://www.ietf.org/mailman/listinfo/jose
>
>
_______________________________________________
jose mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/jose

Reply via email to