JS原生SHA256备忘

5,427 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

SHA256作为最常用的加密学哈希函数,它的稳定、快速实现可以有效提高应用的安全性。本文在此简单记录以SHA256为主的几个加密学函数在浏览器和Nodejs环境下的原生实现,不依赖任何第三方包。

随机字符串

一个最简单的随机字符串生成方案是

Math.random().toString(36).substring(2)

但这个随机字符串不是加密学安全的!安全的随机字符串生成如下:

Nodejs

特别注意,这里的l不是字符串长度!

const crypto = require('crypto')
const random = l => crypto.randomBytes(l).toString('base64url')

最后的编码方法可以修改为下列值:'ascii', 'utf8', 'utf16le'/'ucs2', 'base64', 'base64url', 'latin1'/'binary', 'hex'

Browser

const base64url = buffer => btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')

function random (l) {
  const a = new Uint8Array(l)
  window.crypto.getRandomValues(a)
  return base64url(a)
}

输出base64url编码的随机串,同样这里的l不是字符串长度!。这里的base64url函数下面还要用到。

SHA256

Nodejs

const sha256 = t => crypto.createHash('sha256').update(t).digest('base64url')

同样,可以修改最后输出的编码方式:'ascii', 'utf8', 'utf16le'/'ucs2', 'base64', 'base64url', 'latin1'/'binary', 'hex'

Browser

const enc = new TextEncoder('utf-8')
const base64url = buffer => btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')

const sha256 = str => window.crypto.subtle.digest('SHA-256', enc.encode(str)).then(base64url)

特别注意:

  1. window.crypto.subtle只能在安全环境(本机或https)下使用!并请特别注意不同浏览器版本的支持情况。
  2. 这个sha256函数是异步的,需要await

HS256

HS256是HMAC with SHA-256的缩写,是一种常用的对称签名方案。

Nodejs

const HS256 = (msg, secret) => crypto.createHmac('sha256', secret).update(msg).digest('base64url')

同样,可以修改最后输出的编码方式:'ascii', 'utf8', 'utf16le'/'ucs2', 'base64', 'base64url', 'latin1'/'binary', 'hex'

Browser

const enc = new TextEncoder('utf-8')
const base64url = buffer => btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')

const HS256 = async (str, secret) => {
  const key = await window.crypto.subtle.importKey('raw', enc.encode(secret), { name: 'HMAC', hash: { name: 'SHA-256' }},false,['sign', 'verify'])
  const signature = await window.crypto.subtle.sign('HMAC', key, enc.encode(str))
  return base64url(signature)
}

特别注意:

  1. window.crypto.subtle只能在安全环境(本机或https)下使用!并请特别注意不同浏览器版本的支持情况。
  2. 这个HS256函数是异步的,需要await