index.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. const {sm3, hmac} = require('../sm2/sm3')
  2. /**
  3. * 补全16进制字符串
  4. */
  5. function leftPad(input, num) {
  6. if (input.length >= num) return input
  7. return (new Array(num - input.length + 1)).join('0') + input
  8. }
  9. /**
  10. * 字节数组转 16 进制串
  11. */
  12. function ArrayToHex(arr) {
  13. return arr.map(item => {
  14. item = item.toString(16)
  15. return item.length === 1 ? '0' + item : item
  16. }).join('')
  17. }
  18. /**
  19. * 转成字节数组
  20. */
  21. function hexToArray(hexStr) {
  22. const words = []
  23. let hexStrLength = hexStr.length
  24. if (hexStrLength % 2 !== 0) {
  25. hexStr = leftPad(hexStr, hexStrLength + 1)
  26. }
  27. hexStrLength = hexStr.length
  28. for (let i = 0; i < hexStrLength; i += 2) {
  29. words.push(parseInt(hexStr.substr(i, 2), 16))
  30. }
  31. return words
  32. }
  33. /**
  34. * utf8 串转字节数组
  35. */
  36. function utf8ToArray(str) {
  37. const arr = []
  38. for (let i = 0, len = str.length; i < len; i++) {
  39. const point = str.codePointAt(i)
  40. if (point <= 0x007f) {
  41. // 单字节,标量值:00000000 00000000 0zzzzzzz
  42. arr.push(point)
  43. } else if (point <= 0x07ff) {
  44. // 双字节,标量值:00000000 00000yyy yyzzzzzz
  45. arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
  46. arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
  47. } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
  48. // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
  49. arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
  50. arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
  51. arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
  52. } else if (point >= 0x010000 && point <= 0x10FFFF) {
  53. // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
  54. i++
  55. arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
  56. arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
  57. arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
  58. arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
  59. } else {
  60. // 五、六字节,暂时不支持
  61. arr.push(point)
  62. throw new Error('input is not supported')
  63. }
  64. }
  65. return arr
  66. }
  67. module.exports = function (input, options) {
  68. input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input)
  69. if (options) {
  70. const mode = options.mode || 'hmac'
  71. if (mode !== 'hmac') throw new Error('invalid mode')
  72. let key = options.key
  73. if (!key) throw new Error('invalid key')
  74. key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key)
  75. return ArrayToHex(hmac(input, key))
  76. }
  77. return ArrayToHex(sm3(input))
  78. }