Skip to content

Instantly share code, notes, and snippets.

@johnatandias
Last active April 29, 2022 18:11
Show Gist options
  • Save johnatandias/d8b6fa5805fb44f09c94b87e5b8c7d40 to your computer and use it in GitHub Desktop.
Save johnatandias/d8b6fa5805fb44f09c94b87e5b8c7d40 to your computer and use it in GitHub Desktop.
Web Crypto API
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
const encodeData = () => {
const longJson = JSON.stringify([{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}, {
"id": "1003",
"type": "Blueberry"
}, {
"id": "1004",
"type": "Devil's Food"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5007",
"type": "Powdered Sugar"
}, {
"id": "5006",
"type": "Chocolate with Sprinkles"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}, {
"id": "0002",
"type": "donut",
"name": "Raised",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}, {
"id": "0003",
"type": "donut",
"name": "Old Fashioned",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}])
const shortJson = JSON.stringify({
descricao: 'DORIME',
status: 'ATIVO',
})
const textEncoder = new TextEncoder()
const encodedData = textEncoder.encode(JSON.stringify(longJson))
return {
encodedData
}
}
const counter = window.crypto.getRandomValues(new Uint8Array(16))
const generateAesKey = async() => {
const aesCryptoKey = await window.crypto.subtle.generateKey({
name: "AES-CTR",
length: 256
},
true, ["encrypt", "decrypt"]
)
const exportedAesCryptoKey = await window.crypto.subtle.exportKey(
"raw",
aesCryptoKey
);
const exportedAesKeyBuffer = new Uint8Array(exportedAesCryptoKey);
console.log({
exportedAesKeyBuffer
})
return {
aesCryptoKey,
rawAesKey: exportedAesKeyBuffer
}
}
const aesEncrypt = async(aesCryptoKey, encodedData) => {
const aesEncryptedData = await window.crypto.subtle.encrypt({
name: "AES-CTR",
counter,
length: 64
},
aesCryptoKey,
encodedData
);
return {
aesEncryptedData
}
}
const rsaEncryptAesKey = async(aesKey) => {
// const jwk = {
// kty: 'RSA',
// e: 'AQAB',
// use: 'enc',
// kid: 'NSBIXzSuhCzev1VCQ2_bY1BDcnuYTWf4pw9Mz4ZvQGw',
// alg: 'RSA-OAEP-512',
// n: 'lotRefvlFPDHnBrWeArh3AHdrP9UXZ0t1mD7eykE1RoaSGN78dwSEPdPyRVFmk2HGqCIH4kA-mT-KjT4rOr0JZxCoUHcDU_yeYOyFIORXeSv8RKEfYcC6Ifo9HyBtDO4eyUfIu3sTyeD4GO2xYxu-ZzT3_8guctIELXf-8e40WNuztGSmDbvlEu6i7HjT661ubEsfV3JWRqvIzpkgImcMPh7POcEi-PJgiu4cXktO2TLIpg1dnCnIhIlQWOcrSz3wMIsD8tkvqJk1SRuHoyp_V8arfg-ocTt4IpNAmyMmboqwatIQTe7OpN4Pku1sHjH1PFOi9Ta-kQlFBrW_EwQVQ',
// }
// const rsaCryptoKey = await window.crypto.subtle.importKey(
// 'jwk',
// jwk, {
// name: 'RSA-OAEP',
// hash: {
// name: 'SHA-512'
// },
// label: new Uint8Array([1, 0, 1]),
// },
// false, ['encrypt'],
// )
const newKeyPair = await window.crypto.subtle.generateKey({
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {
name: "SHA-256"
},
},
false, ["encrypt", "decrypt"]
)
const {
privateKey,
publicKey: rsaCryptoKey
} = newKeyPair
const rsaEncryptedData = await window.crypto.subtle.encrypt({
name: 'RSA-OAEP',
},
rsaCryptoKey,
aesKey,
)
return {
aesKeyEncryptedInRsa: rsaEncryptedData,
rsaPrivateKey: privateKey,
}
}
const encryptMessage = async() => {
const {
encodedData
} = encodeData()
const {
aesCryptoKey,
rawAesKey
} = await generateAesKey()
const {
aesEncryptedData
} = await aesEncrypt(aesCryptoKey, encodedData)
const {
aesKeyEncryptedInRsa,
rsaPrivateKey,
} = await rsaEncryptAesKey(rawAesKey)
return {
aesEncryptedData,
aesKeyEncryptedInRsa,
rsaPrivateKey,
}
}
(async() => {
const {
aesEncryptedData,
aesKeyEncryptedInRsa,
rsaPrivateKey
} = await encryptMessage()
console.log({
aesEncryptedData,
aesKeyEncryptedInRsa,
rsaPrivateKey
})
// Test only
const decryptMessage = async(aesEncryptedKeyInRsa, privateRsaKey, aesEncryptedData) => {
const aesKey = await window.crypto.subtle.decrypt({
name: 'RSA-OAEP',
},
privateRsaKey,
aesEncryptedKeyInRsa,
)
console.log({
aesKey
})
const aesKeyFinal = await window.crypto.subtle.importKey(
"raw",
aesKey, {
name: "AES-CTR",
counter,
length: 64
},
false, ['decrypt']
);
const data = await window.crypto.subtle.decrypt({
name: "AES-CTR",
counter,
length: 64
},
aesKeyFinal,
aesEncryptedData
);
const textDecoder = new TextDecoder()
const decrytedData = JSON.parse(textDecoder.decode(data))
console.log({
decrytedData
})
}
await decryptMessage(aesKeyEncryptedInRsa, rsaPrivateKey, aesEncryptedData)
})()
</script>
</head>
<body>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment