import webcrypto from '../webcrypto.js' ; import randomBytes from '../random-bytes.js' ; import { toString as uint8ArrayToString } from 'uint8arrays/to-string' ; import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' ; import * as utils from './rsa-utils.js' ; import { jwk2pub , jwk2priv } from './jwk2pem.js' ; import errcode from 'err-code' ; export { utils } ; export async function generateKey ( bits ) { const pair = await webcrypto . get ( ) . subtle . generateKey ( { name : 'RSASSA-PKCS1-v1_5' , modulusLength : bits , publicExponent : new Uint8Array ( [ 0x01 , 0x00 , 0x01 ] ) , hash : { name : 'SHA-256' } } , true , [ 'sign' , 'verify' ] ) ; const keys = await exportKey ( pair ) ; return { privateKey : keys [ 0 ] , publicKey : keys [ 1 ] } ; } export async function unmarshalPrivateKey ( key ) { const privateKey = await webcrypto . get ( ) . subtle . importKey ( 'jwk' , key , { name : 'RSASSA-PKCS1-v1_5' , hash : { name : 'SHA-256' } } , true , [ 'sign' ] ) ; const pair = [ privateKey , await derivePublicFromPrivate ( key ) ] ; const keys = await exportKey ( { privateKey : pair [ 0 ] , publicKey : pair [ 1 ] } ) ; return { privateKey : keys [ 0 ] , publicKey : keys [ 1 ] } ; } export { randomBytes as getRandomValues } ; export async function hashAndSign ( key , msg ) { const privateKey = await webcrypto . get ( ) . subtle . importKey ( 'jwk' , key , { name : 'RSASSA-PKCS1-v1_5' , hash : { name : 'SHA-256' } } , false , [ 'sign' ] ) ; const sig = await webcrypto . get ( ) . subtle . sign ( { name : 'RSASSA-PKCS1-v1_5' } , privateKey , Uint8Array . from ( msg ) ) ; return new Uint8Array ( sig , 0 , sig . byteLength ) ; } export async function hashAndVerify ( key , sig , msg ) { const publicKey = await webcrypto . get ( ) . subtle . importKey ( 'jwk' , key , { name : 'RSASSA-PKCS1-v1_5' , hash : { name : 'SHA-256' } } , false , [ 'verify' ] ) ; return await webcrypto . get ( ) . subtle . verify ( { name : 'RSASSA-PKCS1-v1_5' } , publicKey , sig , msg ) ; } async function exportKey ( pair ) { if ( pair . privateKey == null || pair . publicKey == null ) { throw errcode ( new Error ( 'Private and public key are required' ) , 'ERR_INVALID_PARAMETERS' ) ; } return await Promise . all ( [ webcrypto . get ( ) . subtle . exportKey ( 'jwk' , pair . privateKey ) , webcrypto . get ( ) . subtle . exportKey ( 'jwk' , pair . publicKey ) ] ) ; } async function derivePublicFromPrivate ( jwKey ) { return await webcrypto . get ( ) . subtle . importKey ( 'jwk' , { kty : jwKey . kty , n : jwKey . n , e : jwKey . e } , { name : 'RSASSA-PKCS1-v1_5' , hash : { name : 'SHA-256' } } , true , [ 'verify' ] ) ; } function convertKey ( key , pub , msg , handle ) { const fkey = pub ? jwk2pub ( key ) : jwk2priv ( key ) ; const fmsg = uint8ArrayToString ( Uint8Array . from ( msg ) , 'ascii' ) ; const fomsg = handle ( fmsg , fkey ) ; return uint8ArrayFromString ( fomsg , 'ascii' ) ; } export function encrypt ( key , msg ) { return convertKey ( key , true , msg , ( msg , key ) => key . encrypt ( msg ) ) ; } export function decrypt ( key , msg ) { return convertKey ( key , false , msg , ( msg , key ) => key . decrypt ( msg ) ) ; }