Subject: [jose] My quest to learn how to create SubjectPublicKeyInfo values from scratch

From: Mike Jones <[email-masked]>
Date: Wed, 11 Mar 2015 05:16:57 +0000

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 :)) 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

---

From: Anders Rundgren <[email-masked]>
Date: Wed, 11 Mar 2015 10:02:43 +0100

On 2015-03-11 06:16, Mike Jones wrote:

Hi Mike,
I did approximately the same journey as you did when I created JCS for JavaScript.
It wasn't easy.  A bare-bones ASN.1 encoder is needed + tables holding OIDs for EC keys.

The encodeRSAPublicKey and encodeECPublicKey methods in
https://code.google.com/p/openkeystore/source/browse/javascript/trunk/src/crypto/KeySerialization.js
use decoded JWK values to generate SPKIs.

Since this list is crowded by die-hard ANS.1 experts, you may end-up with lots of feedback :-)

BTW, I noted (unfortunately very late) that Java and .NET use different formats for EC signatures.
None of the documents give any hint about what they produce.  A signature is a signature...well not really.

Cheers,
Anders

> 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.
>
> ·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:
>
> o159 – 0x81 0x9f
>
> o9 – 0x09
>
> o0 – 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 22^nd 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.
>
> ·These length values are encoded as follows:
>
> o290 – 0x82 0x01 0x22
>
> o257 – 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?
>
> 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.
>
> _______________________________________________
> jose mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/jose
>

---

From: Richard Barnes <[email-masked]>
Date: Wed, 11 Mar 2015 05:22:55 -0700

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-masked]>
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.
>
>
>
> ·        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.
>
>
>
> ·        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.
>
>
>

---

From: Stephen Farrell <[email-masked]>
Date: Wed, 11 Mar 2015 12:42:24 +0000

Hi Mike,

Simplest is [0] as used in public key pinning for web
servers. (That should pop out as an RFC any time now
btw.) I really doubt any claim that that there's some
magic needed to make this work as those two lines
of script show.

But given you wanted to learn, and not just get stuff
done, it's a pity you didn't start from RFC5280, [1]
and RFCs 3279 [2] and 5480. [3] Lots of pages there it's
true, but actually only very few need to be read if
one only cares about SPKI.

Or, maybe just search for the thing you're after [4]
and you'll see a bunch of fine information, including
howto in the search is even better. [5] Or, if you want
code examples those are there too. [6]

I have to admit to being more than surprised that 5 hours
of effort didn't throw up any of that.

But if, after that, you're still desperate, then you could
look at code I wrote, (you would need to be desperate
to try learn from my crappy code:-) [7] being an example
of doing this for RSA in about a dozen JS LOC without any
ASN.1 support using the Stanford JS library, and [8]
being openssl 'C' code. Or the netinf code [9] implements
RFC6920 [10] with implementations of what you need in
other languages like php, python and ruby as well, even
clojure if you want to be fancy:-)

Anyway, it took me ~20 minutes to find all those again,
and I guess it might take a while to read everything and
find the bits you want, but from my POV if someone is
developing a generic library for this kind of thing,
they really should understand all this already, (or I don't
want them writing crypto code on which I depend) or else
if all that's needed a quick bit of code for say a client
that emits a key id, then the stackoverflow approach of
copying from examples should be fine.

Either way, there is IMO not even a scintilla of credibility
to any claim that this is super complex or anything like it.

I think I'd summarise the real argument against SPKI here as
being: "I want to do what I thought of first." And of course
since that's not a very good argument, further discussion
seems to dive into even worse argument, such as this being
too difficult, taking hours or being nasty-old-ASN.1 etc.

Cheers,
S.

[0] https://tools.ietf.org/html/draft-ietf-websec-key-pinning-21#appendix-A
[1] https://tools.ietf.org/html/rfc5280
[2] https://tools.ietf.org/html/rfc3279
[3] https://tools.ietf.org/html/rfc5480
[4]
https://www.google.ie/search?q=subjectpublickeyinfo&sa=G&gbv=1&sei=aC4AVdP1OcHP7gaO9oHoBw
[5]
https://www.google.ie/search?q=subjectpublickeyinfo+howto&btnG=Search&gbv=1
[6] https://www.google.ie/search?q=sha256+spki+code&btnG=Search&gbv=1
[7] http://sourceforge.net/p/hoba/code/ci/master/tree/js/hoba-gen-key.js#l60
[8] http://sourceforge.net/p/hoba/code/ci/master/tree/lib/hoba-crypt.cc#l74
[9] http://sourceforge.net/p/netinf/code/ci/default/tree/
[10] http://tools.ietf.org/html/rfc6920

On 11/03/15 05:16, Mike Jones 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
> 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.
> 
> 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
> *        The tags for SEQUENCE, OID, NULL, BIT STRING, and INTEGER
> are respectively 0x30, 0x06, 0x05, 0x03, and 0x02.
> 
> *        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.
> 
> 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
> *        From this, I deduced (possibly incorrectly :)) 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.)
> 
> *        How are the OIDs in the table at
> *        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
> 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.
> 
> 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-masked] https://www.ietf.org/mailman/listinfo/jose
>

---

From: Stephen Farrell <[email-masked]>
Date: Wed, 11 Mar 2015 13:07:54 +0000

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

That, and of course in this case if SPKI is used, there is no
decoding requirement at all.

It's decoding complex structures (like certs) that's the real PITA
with ASN.1 defined things in my experience, esp when you get errors
in hard-to-handle bits of code generated by compilers. None of that
is at all relevant here.

S.

PS: Interesting that both of our hacky bits of JS code are almost
identical even though mine has nothing to do with JOSE:-)

---

From: Hannes Tschofenig <[email-masked]>
Date: Wed, 11 Mar 2015 18:23:35 +0100

Mike,

I did this in the context of the work on the raw public key document for
TLS.

Using an ASN.1 parser makes sense since the SubjectPublicKeyInfo is not
just a blog but an ASN.1 structure that looks differently depending on
the type of keys encoding (ECC vs. RSA).

My code was done as part of the TLS stack itself it is not as usable as
a command line tool.

You referenced https://tools.ietf.org/html/rfc7250#appendix-A and this
was created by extracing the SubjectPublicKeyInfo field from a
self-signed certificate that was created with the OpenSSL tools.

Ciao
Hannes

On 03/11/2015 06:16 AM, Mike Jones wrote:
> 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.
> 
>  
> 
> 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…
> 
>  
> 
> 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.
> 
>  
> 
> with our partners, this document is only available through payment.” 
> 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:
> ·        There is an apparently unused zero byte (the 22^nd byte of the
> ·        The 1024 bit modulus is represented in 129 bytes, with the
> first byte being zero.
> 
>  
> 
> cert to learn from (especially since JWA requires 2048+ bit RSA keys). 
> I found http://fm4dd.com/openssl/certexamples.htm and chose
> 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.)
> 
> ·        The 2048 bit modulus is represented by 257 bytes, with the
> first byte being zero.
> 
>  
> 
> 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.
> 
>  
> 
> this information, I’d love to see them!
> 
>  
> 
> ==== CONCLUSIONS ====
> 
>  
> 
> 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!
> 
>  
> 
> 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.
> 
>  
>

---

From: Hannes Tschofenig <[email-masked]>
Date: Wed, 11 Mar 2015 19:05:59 +0100

Just adding a bit more info after a chat with my co-worker Manuel (on CC).

If you use the OpenSSL tools then you can generate the
SubjectPublicKeyInfo structure with the following commands:

> openssl ecparam -genkey -name prime256v1 -out ec.key && openssl ec -in
ec.key -pubout -outform der -out ec.pub

> dumpasn1 ec.pub

  0  89: SEQUENCE {
  2  19:   SEQUENCE {
  4   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 13   8:     OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
       :     }
 23  66:   BIT STRING
       :     04 58 74 31 8E DB 77 7C D3 AA 13 E0 81 D2 2C 0F
       :     F1 CA 15 89 5B 50 F5 E2 5F AF 45 DC 3D 29 17 64
       :     B2 0F 1A BE DE A3 77 70 CB D2 0F B5 6B 5F 11 92
       :     C6 38 BE 6A F6 0B 2F 80 B7 AE 7E 4A 0A 33 C4 14
       :     AC
       :   }

Ciao
Hannes

---

From: John Bradley <[email-masked]>
Date: Wed, 11 Mar 2015 15:16:40 -0300

How do you generate it from a raw key in JWK based on "crv", "kty" , "x" and "y" ?

> On Mar 11, 2015, at 3:05 PM, Hannes Tschofenig <[email-masked]> wrote:
>

---

From: Richard Barnes <[email-masked]>
Date: Wed, 11 Mar 2015 11:26:18 -0700

You could do a similar template thing to what I posted above, but with
different values.

---

From: "Manger, James" <[email-masked]>
Date: Thu, 12 Mar 2015 11:29:45 +1100

o   159 - 0x81 0x9f

o   9 - 0x09

o   0 - 0x00

The ASN.1 BIT STRING is DER-encoded as:
|Tag|Len  |Value                                       |
|   |     |Unused-bit-count  Bits-paddeded-with-0-bits |
| 03| 818D| 00               30818902...                 |

For a BIT SRING, the value part of the tag-length-value starts with 1 byte that holds the number of unused bits in the last byte of the value.
As an example, the 7 bits 1110001 are DER-encoded as 03(tag) 02(length) 01(unused bit count) E2(bits plus 1 unused bit)

The modulus and exponent are encapsulated in a SEQUENCE (tag byte 0x30), not just concatenated.

Integers are represented in 2's-complement to handle positive and negative integers. If the top bit of the first byte is 1 you have a negative integer. Hence, you need an extra leading 0x00 byte for some positive integers.

> RSA_2048_PREFIX = "30820122300D06092A864886F70D01010105000382010F003082010A02820101";

There are plenty of "2048-bit RSA keys" where the modulus is actually 2047-bits long (multiply two 1024-bit primes and you get a 2048-bit or 2047-bit modulus). There is no extra leading 0x00 byte when DER-encoding a 2047-bit modulus. Consequently, concatenating a fixed prefix to build a DER-encoding is likely to cause interop bugs.

Example: HS256   1.2.840.113549.2.9

Believe it or not, the first step to DER-encode an OID is to convert the first two numbers (1.2.) to a single number. Multiple the first by 40 and add the second: 1*40 + 2 = 42 = 0x2A (aren't standards great ;). Now 42 and the following four numbers are each represented with a variable-length encoding: 7 bits per byte; 8th bit (most significant bit) indicates if there are more bytes to follow.

Example: 113549 = 6*2^14 + 119 * 2^7 + 13 => encoded in 3 bytes 86 F7 0D, which you can see in the middle of RSA_2048_PREFIX above.

P.S. The draft splits the number 113549 (and JCA labels) over two lines. Yuck. Might be better to put the XML DSIG uris in a separate table to avoid wrapping.

Whenever you put a whole number of bytes into a BIT STRING you get the 0x00 byte as there are no unused bits.

--
James Manger

---

From: Mike Jones <[email-masked]>
Date: Thu, 12 Mar 2015 00:49:47 +0000

Thanks for explaining about the unused bit count, James.  Another mystery solved!

Your point about 2048 bit keys sometimes being 2047 bits in length seems quite pertinent, as it changes the encoded key length (and therefore several other encoded lengths) by a byte.

About the draft splitting the number 113549 (and JCA labels) over two lines, I'll plan to work with the RFC editor to see what we can do about that.

                                                                Thanks again,
                                                                -- Mike

From: Manger, James [mailto:[email-masked]]
Sent: Wednesday, March 11, 2015 5:30 PM
To: Mike Jones; [email-masked]
Subject: RE: My quest to learn how to create SubjectPublicKeyInfo values from scratch

o   159 - 0x81 0x9f

o   9 - 0x09

o   0 - 0x00

--
James Manger

---

From: Richard Barnes <[email-masked]>
Date: Wed, 11 Mar 2015 22:45:02 -0700

On Wed, Mar 11, 2015 at 5:29 PM, Manger, James <
[email-masked]> wrote:

> | 03| 818D| 00               30818902…                 |
>
>
>
> For a BIT SRING, the value part of the tag-length-value starts with 1 byte
> that holds the number of unused bits in the last byte of the value.
>
> As an example, the 7 bits 1110001 are DER-encoded as 03(tag) 02(length)
> 01(unused bit count) E2(bits plus 1 unused bit)
>
>
>
> Integers are represented in 2’s-complement to handle positive and negative
> integers. If the top bit of the first byte is 1 you have a negative
> integer. Hence, you need an extra leading 0x00 byte for some positive
> integers.
>
>
>
> > RSA_2048_PREFIX =
> There are plenty of “2048-bit RSA keys” where the modulus is actually
> 2047-bits long (multiply two 1024-bit primes and you get a 2048-bit or
> 2047-bit modulus). There is no extra leading 0x00 byte when DER-encoding a
> 2047-bit modulus. Consequently, concatenating a fixed prefix to build a
> DER-encoding is likely to cause interop bugs.
>

I'm sorry, what?  Could you please provide an example of two 1024-bit
primes that multiply to a 2047-bit value?  Last I checked, (1<<N + x)*(1<<N
+ y) > 1<<(2*N).

--Richard

> Believe it or not, the first step to DER-encode an OID is to convert the
> first two numbers (1.2.) to a single number. Multiple the first by 40 and
> add the second: 1*40 + 2 = 42 = 0x2A (aren’t standards great ;). Now 42 and
> the following four numbers are each represented with a variable-length
> encoding: 7 bits per byte; 8th bit (most significant bit) indicates if
> there are more bytes to follow.
>
> Example: 113549 = 6*2^14 + 119 * 2^7 + 13 => encoded in 3 bytes 86 F7 0D,
> which you can see in the middle of RSA_2048_PREFIX above.
>
>
>
> P.S. The draft splits the number 113549 (and JCA labels) over two lines.
> Yuck. Might be better to put the XML DSIG uris in a separate table to avoid
> wrapping.
>
>
>

---

From: "Manger, James" <[email-masked]>
Date: Thu, 12 Mar 2015 18:04:08 +1100

>> There are plenty of “2048-bit RSA keys” where the modulus is actually 2047-bits long (multiply two 1024-bit primes and you get a 2048-bit or 2047-bit modulus). There is no extra leading 0x00 byte when DER-encoding a 2047-bit modulus. Consequently, concatenating a fixed prefix to build a DER-encoding is likely to cause interop bugs.

> I'm sorry, what?  Could you please provide an example of two 1024-bit primes that multiply to a 2047-bit value?  Last I checked, (1<<N + x)*(1<<N + y) > 1<<(2*N).

p1 = 2^1023 + 1
p2 = 2^1023 + 3
n = p1 * p2 = 2^2046 + 2^1025 + 3

p1 & p2 are 1024-bit numbers (probably not actually prime).
Their product n is a 2047-bit number.

The calculation is (1<<N - x)*(1<<N - y) = (1<<2N - z)

--
James Manger