Spaces:
Sleeping
Sleeping
| import { encode, concat, uint32be } from './buffer_utils.js'; | |
| import { checkEncCryptoKey } from './crypto_key.js'; | |
| import { digest } from './helpers.js'; | |
| function lengthAndInput(input) { | |
| return concat(uint32be(input.length), input); | |
| } | |
| async function concatKdf(Z, L, OtherInfo) { | |
| const dkLen = L >> 3; | |
| const hashLen = 32; | |
| const reps = Math.ceil(dkLen / hashLen); | |
| const dk = new Uint8Array(reps * hashLen); | |
| for (let i = 1; i <= reps; i++) { | |
| const hashInput = new Uint8Array(4 + Z.length + OtherInfo.length); | |
| hashInput.set(uint32be(i), 0); | |
| hashInput.set(Z, 4); | |
| hashInput.set(OtherInfo, 4 + Z.length); | |
| const hashResult = await digest('sha256', hashInput); | |
| dk.set(hashResult, (i - 1) * hashLen); | |
| } | |
| return dk.slice(0, dkLen); | |
| } | |
| export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(), apv = new Uint8Array()) { | |
| checkEncCryptoKey(publicKey, 'ECDH'); | |
| checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits'); | |
| const algorithmID = lengthAndInput(encode(algorithm)); | |
| const partyUInfo = lengthAndInput(apu); | |
| const partyVInfo = lengthAndInput(apv); | |
| const suppPubInfo = uint32be(keyLength); | |
| const suppPrivInfo = new Uint8Array(); | |
| const otherInfo = concat(algorithmID, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo); | |
| const Z = new Uint8Array(await crypto.subtle.deriveBits({ | |
| name: publicKey.algorithm.name, | |
| public: publicKey, | |
| }, privateKey, getEcdhBitLength(publicKey))); | |
| return concatKdf(Z, keyLength, otherInfo); | |
| } | |
| function getEcdhBitLength(publicKey) { | |
| if (publicKey.algorithm.name === 'X25519') { | |
| return 256; | |
| } | |
| return (Math.ceil(parseInt(publicKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3); | |
| } | |
| export function allowed(key) { | |
| switch (key.algorithm.namedCurve) { | |
| case 'P-256': | |
| case 'P-384': | |
| case 'P-521': | |
| return true; | |
| default: | |
| return key.algorithm.name === 'X25519'; | |
| } | |
| } | |