| 
									
										
										
										
											2018-11-22 02:09:02 -07:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 14:31:53 -07:00
										 |  |  | // TODO fun idea: create a template from an existing file
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 02:09:02 -07:00
										 |  |  | var x509 = module.exports; | 
					
						
							| 
									
										
										
										
											2018-11-22 04:32:33 -07:00
										 |  |  | var ASN1 = require('./asn1.js'); | 
					
						
							|  |  |  | var Enc = require('./encoding.js'); | 
					
						
							| 
									
										
										
										
											2018-11-22 02:09:02 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | x509.guess = function (der, asn1) { | 
					
						
							|  |  |  |   // accepting der for compatability with other usages
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var meta = { kty: 'RSA', format: 'pkcs1', public: true }; | 
					
						
							|  |  |  |   //meta.asn1 = ASN1.parse(u8);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (asn1.children.every(function(el) { | 
					
						
							|  |  |  |     return 0x02 === el.type; | 
					
						
							|  |  |  |   })) { | 
					
						
							|  |  |  |     if (2 === asn1.children.length) { | 
					
						
							|  |  |  |       // rsa pkcs1 public
 | 
					
						
							|  |  |  |       return meta; | 
					
						
							|  |  |  |     } else if (asn1.children.length >= 9) { | 
					
						
							|  |  |  |       // the standard allows for "otherPrimeInfos", hence at least 9
 | 
					
						
							|  |  |  |       meta.public = false; | 
					
						
							|  |  |  |       // rsa pkcs1 private
 | 
					
						
							|  |  |  |       return meta; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       throw new Error("not an RSA PKCS#1 public or private key (wrong number of ints)"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-22 02:36:21 -07:00
										 |  |  |   } else { | 
					
						
							|  |  |  |     meta.format = 'pkcs8'; | 
					
						
							| 
									
										
										
										
											2018-11-22 02:09:02 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return meta; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-11-22 04:32:33 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | x509.parsePkcs1 = function parseRsaPkcs1(buf, asn1, jwk) { | 
					
						
							|  |  |  |   if (!asn1.children.every(function(el) { | 
					
						
							|  |  |  |     return 0x02 === el.type; | 
					
						
							|  |  |  |   })) { | 
					
						
							|  |  |  |     throw new Error("not an RSA PKCS#1 public or private key (not all ints)"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (2 === asn1.children.length) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     jwk.n = Enc.bufToUrlBase64(asn1.children[0].value); | 
					
						
							|  |  |  |     jwk.e = Enc.bufToUrlBase64(asn1.children[1].value); | 
					
						
							|  |  |  |     return jwk; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   } else if (asn1.children.length >= 9) { | 
					
						
							|  |  |  |     // the standard allows for "otherPrimeInfos", hence at least 9
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     jwk.n = Enc.bufToUrlBase64(asn1.children[1].value); | 
					
						
							|  |  |  |     jwk.e = Enc.bufToUrlBase64(asn1.children[2].value); | 
					
						
							|  |  |  |     jwk.d = Enc.bufToUrlBase64(asn1.children[3].value); | 
					
						
							|  |  |  |     jwk.p = Enc.bufToUrlBase64(asn1.children[4].value); | 
					
						
							|  |  |  |     jwk.q = Enc.bufToUrlBase64(asn1.children[5].value); | 
					
						
							|  |  |  |     jwk.dp = Enc.bufToUrlBase64(asn1.children[6].value); | 
					
						
							|  |  |  |     jwk.dq = Enc.bufToUrlBase64(asn1.children[7].value); | 
					
						
							|  |  |  |     jwk.qi = Enc.bufToUrlBase64(asn1.children[8].value); | 
					
						
							|  |  |  |     return jwk; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     throw new Error("not an RSA PKCS#1 public or private key (wrong number of ints)"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | x509.parsePkcs8 = function parseRsaPkcs8(buf, asn1, jwk) { | 
					
						
							|  |  |  |   if (2 === asn1.children.length | 
					
						
							|  |  |  |     && 0x03 === asn1.children[1].type | 
					
						
							|  |  |  |     && 0x30 === asn1.children[1].value[0]) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     asn1 = ASN1.parse(asn1.children[1].value); | 
					
						
							|  |  |  |     jwk.n = Enc.bufToUrlBase64(asn1.children[0].value); | 
					
						
							|  |  |  |     jwk.e = Enc.bufToUrlBase64(asn1.children[1].value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   } else if (3 === asn1.children.length | 
					
						
							|  |  |  |     && 0x04 === asn1.children[2].type | 
					
						
							|  |  |  |     && 0x30 === asn1.children[2].children[0].type | 
					
						
							|  |  |  |     && 0x02 === asn1.children[2].children[0].children[0].type) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     asn1 = asn1.children[2].children[0]; | 
					
						
							|  |  |  |     jwk.n = Enc.bufToUrlBase64(asn1.children[1].value); | 
					
						
							|  |  |  |     jwk.e = Enc.bufToUrlBase64(asn1.children[2].value); | 
					
						
							|  |  |  |     jwk.d = Enc.bufToUrlBase64(asn1.children[3].value); | 
					
						
							|  |  |  |     jwk.p = Enc.bufToUrlBase64(asn1.children[4].value); | 
					
						
							|  |  |  |     jwk.q = Enc.bufToUrlBase64(asn1.children[5].value); | 
					
						
							|  |  |  |     jwk.dp = Enc.bufToUrlBase64(asn1.children[6].value); | 
					
						
							|  |  |  |     jwk.dq = Enc.bufToUrlBase64(asn1.children[7].value); | 
					
						
							|  |  |  |     jwk.qi = Enc.bufToUrlBase64(asn1.children[8].value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     throw new Error("not an RSA PKCS#8 public or private key (wrong format)"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return jwk; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-11-22 14:31:53 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | x509.packPkcs1 = function (jwk) { | 
					
						
							|  |  |  |   var n = ASN1.UInt(Enc.base64ToHex(jwk.n)); | 
					
						
							|  |  |  |   var e = ASN1.UInt(Enc.base64ToHex(jwk.e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!jwk.d) { | 
					
						
							|  |  |  |     return Enc.hexToBuf(ASN1('30', n, e)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return Enc.hexToBuf(ASN1('30' | 
					
						
							|  |  |  |   , ASN1.UInt('00') | 
					
						
							|  |  |  |   , n | 
					
						
							|  |  |  |   , e | 
					
						
							|  |  |  |   , ASN1.UInt(Enc.base64ToHex(jwk.d)) | 
					
						
							|  |  |  |   , ASN1.UInt(Enc.base64ToHex(jwk.p)) | 
					
						
							|  |  |  |   , ASN1.UInt(Enc.base64ToHex(jwk.q)) | 
					
						
							|  |  |  |   , ASN1.UInt(Enc.base64ToHex(jwk.dp)) | 
					
						
							|  |  |  |   , ASN1.UInt(Enc.base64ToHex(jwk.dq)) | 
					
						
							|  |  |  |   , ASN1.UInt(Enc.base64ToHex(jwk.qi)) | 
					
						
							|  |  |  |   )); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-11-22 23:41:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | x509.packPkcs8 = function (jwk) { | 
					
						
							|  |  |  |   if (!jwk.d) { | 
					
						
							|  |  |  |     // Public RSA
 | 
					
						
							|  |  |  |     return Enc.hexToBuf(ASN1('30' | 
					
						
							|  |  |  |       , ASN1('30' | 
					
						
							|  |  |  |         , ASN1('06', '2a864886f70d010101') | 
					
						
							|  |  |  |         , ASN1('05') | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |       , ASN1.BitStr(ASN1('30' | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.n)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.e)) | 
					
						
							|  |  |  |       )) | 
					
						
							|  |  |  |     )); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Private RSA
 | 
					
						
							|  |  |  |   return Enc.hexToBuf(ASN1('30' | 
					
						
							|  |  |  |     , ASN1.UInt('00') | 
					
						
							|  |  |  |     , ASN1('30' | 
					
						
							|  |  |  |       , ASN1('06', '2a864886f70d010101') | 
					
						
							|  |  |  |       , ASN1('05') | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     , ASN1('04' | 
					
						
							|  |  |  |       , ASN1('30' | 
					
						
							|  |  |  |         , ASN1.UInt('00') | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.n)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.e)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.d)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.p)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.q)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.dp)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.dq)) | 
					
						
							|  |  |  |         , ASN1.UInt(Enc.base64ToHex(jwk.qi)) | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |   )); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | x509.packSpki = x509.packPkcs8; |