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.

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:

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.

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:

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?

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