/ src / crypto.js
crypto.js
  1  //import crypto from 'crypto'
  2  
  3  function signed_crc_table() {
  4    var c = 0,
  5      table = new Array(256);
  6  
  7    for (var n = 0; n != 256; ++n) {
  8      c = n;
  9      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 10      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 11      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 12      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 13      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 14      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 15      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 16      c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
 17      table[n] = c;
 18    }
 19  
 20    return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
 21  }
 22  
 23  var T = signed_crc_table();
 24  
 25  function crc32_str(str, seed) {
 26    var C = seed ^ -1;
 27    for (var i = 0, L = str.length, c, d; i < L;) {
 28      c = str.charCodeAt(i++);
 29      if (c < 0x80) {
 30        C = (C >>> 8) ^ T[(C ^ c) & 0xFF];
 31      } else if (c < 0x800) {
 32        C = (C >>> 8) ^ T[(C ^ (192 | ((c >> 6) & 31))) & 0xFF];
 33        C = (C >>> 8) ^ T[(C ^ (128 | (c & 63))) & 0xFF];
 34      } else if (c >= 0xD800 && c < 0xE000) {
 35        c = (c & 1023) + 64;
 36        d = str.charCodeAt(i++) & 1023;
 37        C = (C >>> 8) ^ T[(C ^ (240 | ((c >> 8) & 7))) & 0xFF];
 38        C = (C >>> 8) ^ T[(C ^ (128 | ((c >> 2) & 63))) & 0xFF];
 39        C = (C >>> 8) ^ T[(C ^ (128 | ((d >> 6) & 15) | ((c & 3) << 4))) & 0xFF];
 40        C = (C >>> 8) ^ T[(C ^ (128 | (d & 63))) & 0xFF];
 41      } else {
 42        C = (C >>> 8) ^ T[(C ^ (224 | ((c >> 12) & 15))) & 0xFF];
 43        C = (C >>> 8) ^ T[(C ^ (128 | ((c >> 6) & 63))) & 0xFF];
 44        C = (C >>> 8) ^ T[(C ^ (128 | (c & 63))) & 0xFF];
 45      }
 46    }
 47    return Math.abs(C ^ -1).toString(16);
 48  }
 49  
 50  // This async is really not necessary.
 51  // There should be a better library
 52  async function createHash(payload) {
 53      const textBuffer = new TextEncoder().encode(payload)
 54      const digest = await crypto.subtle.digest('SHA-256', textBuffer)
 55      const hash = await digest
 56      return hash
 57  }
 58  
 59  function buf2hex(buffer) { // buffer is an ArrayBuffer
 60    return [...new Uint8Array(buffer)]
 61        .map(x => x.toString(16).padStart(2, '0'))
 62        .join('');
 63  }
 64  
 65  function createCardHash(payload) {
 66    let crchash = crc32_str(payload)
 67    return crchash
 68  }
 69  
 70  async function hmacHex(message, secretKey, algorithm = "SHA-256") {
 71      // Convert the message and secretKey to Uint8Array
 72      const encoder = new TextEncoder();
 73      const messageUint8Array = encoder.encode(message);
 74      const keyUint8Array = encoder.encode(secretKey);
 75  
 76      // Import the secretKey as a CryptoKey
 77      const cryptoKey = await crypto.subtle.importKey(
 78          "raw",
 79          keyUint8Array,
 80          { name: "HMAC", hash: algorithm },
 81          false,
 82          ["sign"]
 83      );
 84  
 85      // Sign the message with HMAC and the CryptoKey
 86      const signature = await crypto.subtle.sign(
 87          "HMAC",
 88          cryptoKey,
 89          messageUint8Array
 90      );
 91  
 92      // Convert the signature ArrayBuffer to a hex string
 93      const hashArray = Array.from(new Uint8Array(signature));
 94      const hashHex = hashArray
 95          .map((b) => b.toString(16).padStart(2, "0"))
 96          .join("");
 97  
 98      return hashHex;
 99  }
100  
101  async function HMAC(key, message){
102    const g = str => new Uint8Array([...unescape(encodeURIComponent(str))].map(c => c.charCodeAt(0))),
103    k = g(key),
104    m = g(message),
105    c = await crypto.subtle.importKey('raw', k, { name: 'HMAC', hash: 'SHA-256' },true, ['sign']),
106    s = await crypto.subtle.sign('HMAC', c, m);
107    return btoa(String.fromCharCode(...new Uint8Array(s)))
108  }
109  
110  function derivePublicKey(p) {
111    return crypto.createPublicKey(p).export({
112      type: 'spki',
113      format: 'pem'
114    })
115  }
116  
117  function encryptToPublic(pub, info) {
118    return crypto.publicEncrypt(pub, Buffer(info)).toString('hex')
119  }
120  
121  function decryptFromPrivate(priv, hiddenInfo) {
122    return crypto.privateDecrypt(priv, Buffer.from(hiddenInfo, 'hex')).toString('latin1')
123  }
124  
125  export default {
126    createCardHash,
127    createHash,
128    buf2hex,
129    hmacHex,
130    HMAC,
131    encryptToPublic,
132    decryptFromPrivate,
133    derivePublicKey
134  }