asn1.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* eslint-disable class-methods-use-this */
  2. const {BigInteger} = require('jsbn')
  3. function bigintToValue(bigint) {
  4. let h = bigint.toString(16)
  5. if (h[0] !== '-') {
  6. // 正数
  7. if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
  8. else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
  9. } else {
  10. // 负数
  11. h = h.substr(1)
  12. let len = h.length
  13. if (len % 2 === 1) len += 1 // 补齐到整字节
  14. else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
  15. let mask = ''
  16. for (let i = 0; i < len; i++) mask += 'f'
  17. mask = new BigInteger(mask, 16)
  18. // 对绝对值取反,加1
  19. h = mask.xor(bigint).add(BigInteger.ONE)
  20. h = h.toString(16).replace(/^-/, '')
  21. }
  22. return h
  23. }
  24. class ASN1Object {
  25. constructor() {
  26. this.tlv = null
  27. this.t = '00'
  28. this.l = '00'
  29. this.v = ''
  30. }
  31. /**
  32. * 获取 der 编码比特流16进制串
  33. */
  34. getEncodedHex() {
  35. if (!this.tlv) {
  36. this.v = this.getValue()
  37. this.l = this.getLength()
  38. this.tlv = this.t + this.l + this.v
  39. }
  40. return this.tlv
  41. }
  42. getLength() {
  43. const n = this.v.length / 2 // 字节数
  44. let nHex = n.toString(16)
  45. if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
  46. if (n < 128) {
  47. // 短格式,以 0 开头
  48. return nHex
  49. } else {
  50. // 长格式,以 1 开头
  51. const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
  52. return head.toString(16) + nHex
  53. }
  54. }
  55. getValue() {
  56. return ''
  57. }
  58. }
  59. class DERInteger extends ASN1Object {
  60. constructor(bigint) {
  61. super()
  62. this.t = '02' // 整型标签说明
  63. if (bigint) this.v = bigintToValue(bigint)
  64. }
  65. getValue() {
  66. return this.v
  67. }
  68. }
  69. class DERSequence extends ASN1Object {
  70. constructor(asn1Array) {
  71. super()
  72. this.t = '30' // 序列标签说明
  73. this.asn1Array = asn1Array
  74. }
  75. getValue() {
  76. this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
  77. return this.v
  78. }
  79. }
  80. /**
  81. * 获取 l 占用字节数
  82. */
  83. function getLenOfL(str, start) {
  84. if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
  85. return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
  86. }
  87. /**
  88. * 获取 l
  89. */
  90. function getL(str, start) {
  91. // 获取 l
  92. const len = getLenOfL(str, start)
  93. const l = str.substr(start + 2, len * 2)
  94. if (!l) return -1
  95. const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)
  96. return bigint.intValue()
  97. }
  98. /**
  99. * 获取 v 的位置
  100. */
  101. function getStartOfV(str, start) {
  102. const len = getLenOfL(str, start)
  103. return start + (len + 1) * 2
  104. }
  105. module.exports = {
  106. /**
  107. * ASN.1 der 编码,针对 sm2 签名
  108. */
  109. encodeDer(r, s) {
  110. const derR = new DERInteger(r)
  111. const derS = new DERInteger(s)
  112. const derSeq = new DERSequence([derR, derS])
  113. return derSeq.getEncodedHex()
  114. },
  115. /**
  116. * 解析 ASN.1 der,针对 sm2 验签
  117. */
  118. decodeDer(input) {
  119. // 结构:
  120. // input = | tSeq | lSeq | vSeq |
  121. // vSeq = | tR | lR | vR | tS | lS | vS |
  122. const start = getStartOfV(input, 0)
  123. const vIndexR = getStartOfV(input, start)
  124. const lR = getL(input, start)
  125. const vR = input.substr(vIndexR, lR * 2)
  126. const nextStart = vIndexR + vR.length
  127. const vIndexS = getStartOfV(input, nextStart)
  128. const lS = getL(input, nextStart)
  129. const vS = input.substr(vIndexS, lS * 2)
  130. const r = new BigInteger(vR, 16)
  131. const s = new BigInteger(vS, 16)
  132. return {r, s}
  133. }
  134. }