worker-pastebin/src/crypto.coffee

50 lines
1.5 KiB
CoffeeScript

utf8Bytes = (str) ->
new TextEncoder 'utf-8'
.encode str
hex = (buf) -> (Array.prototype.map.call new Uint8Array(buf),
(x) => ('00' + x.toString 16).slice(-2)).join ''
HMAC_SHA256_KEY = (buf) ->
crypto.subtle.importKey 'raw', buf,
{ name: 'HMAC', hash: 'SHA-256' }, true, [ 'sign' ]
HMAC_SHA256 = (key, str) ->
cryptoKey = await HMAC_SHA256_KEY key
buf = utf8Bytes str
await crypto.subtle.sign "HMAC", cryptoKey, buf
SHA256 = (str) ->
crypto.subtle.digest "SHA-256", utf8Bytes str
# For client-side encryption of files,
# always use AES-128-GCM
# Encrypt a File object
# Returns hexed key, iv, encrypted file name and mime type, and the encrypted ArrayBuffer
encryptFile = (file) ->
# Generate a key to use
keyParams =
name: 'AES-GCM'
length: 128
keyUsage = ['encrypt', 'decrypt']
key = await crypto.subtle.generateKey keyParams, true, keyUsage
# Generate IV and configure the cipher
iv = crypto.getRandomValues new Uint8Array 16
algoParams =
name: 'AES-GCM'
iv: iv
tagLength: 128
# Encrypt
encrypted = await crypto.subtle.encrypt algoParams, key, await file.arrayBuffer()
name = hex await crypto.subtle.encrypt algoParams, key, utf8Bytes file.name
mime = 'binary/' + hex await crypto.subtle.encrypt algoParams, key, utf8Bytes file.type
exportedKey = hex await crypto.subtle.exportKey 'raw', key
[exportedKey, hex(iv), name, mime, encrypted]
export {
utf8Bytes,
hex,
HMAC_SHA256,
SHA256,
encryptFile
}