rsa-public-key-pem.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // http://stackoverflow.com/questions/18835132/xml-to-pem-in-node-js
  2. /* eslint-disable camelcase */
  3. function rsaPublicKeyPem (modulus_b64, exponent_b64) {
  4. const modulus = Buffer.from(modulus_b64, 'base64')
  5. const exponent = Buffer.from(exponent_b64, 'base64')
  6. let modulus_hex = modulus.toString('hex')
  7. let exponent_hex = exponent.toString('hex')
  8. modulus_hex = prepadSigned(modulus_hex)
  9. exponent_hex = prepadSigned(exponent_hex)
  10. const modlen = modulus_hex.length / 2
  11. const explen = exponent_hex.length / 2
  12. const encoded_modlen = encodeLengthHex(modlen)
  13. const encoded_explen = encodeLengthHex(explen)
  14. const encoded_pubkey = '30' +
  15. encodeLengthHex(
  16. modlen +
  17. explen +
  18. encoded_modlen.length / 2 +
  19. encoded_explen.length / 2 + 2
  20. ) +
  21. '02' + encoded_modlen + modulus_hex +
  22. '02' + encoded_explen + exponent_hex
  23. const der_b64 = Buffer.from(encoded_pubkey, 'hex').toString('base64')
  24. const pem = '-----BEGIN RSA PUBLIC KEY-----\n' +
  25. der_b64.match(/.{1,64}/g).join('\n') +
  26. '\n-----END RSA PUBLIC KEY-----\n'
  27. return pem
  28. }
  29. function prepadSigned (hexStr) {
  30. const msb = hexStr[0]
  31. if (msb < '0' || msb > '7') {
  32. return '00' + hexStr
  33. } else {
  34. return hexStr
  35. }
  36. }
  37. function toHex (number) {
  38. const nstr = number.toString(16)
  39. if (nstr.length % 2) return '0' + nstr
  40. return nstr
  41. }
  42. // encode ASN.1 DER length field
  43. // if <=127, short form
  44. // if >=128, long form
  45. function encodeLengthHex (n) {
  46. if (n <= 127) return toHex(n)
  47. else {
  48. const n_hex = toHex(n)
  49. const length_of_length_byte = 128 + n_hex.length / 2 // 0x80+numbytes
  50. return toHex(length_of_length_byte) + n_hex
  51. }
  52. }
  53. module.exports = rsaPublicKeyPem