import { RsaPadding , JsonWebKeyRsaAlg , RsaHash , BinaryKey , RsaJsonWebKey , RsaImportableKey , RsaWrappingKeyAlgorithm , } from './types' ; import { MixedBackendCryptoKey , needs , isCryptoKey , AwsEsdkJsCryptoKey , } from '@aws-crypto/material-management-browser' ; type WebCryptoRsaName = keyof typeof JsonWebKeyRsaAlg ; const OAEP_SHA1_MFG1 = { name : 'RSA-OAEP' , hash : { name : 'SHA-1' } , } ; Object . freeze ( OAEP_SHA1_MFG1 ) ; Object . freeze ( OAEP_SHA1_MFG1 . hash ) ; const OAEP_SHA256_MFG1 = { name : 'RSA-OAEP' , hash : { name : 'SHA-256' } , } ; Object . freeze ( OAEP_SHA256_MFG1 ) ; Object . freeze ( OAEP_SHA256_MFG1 . hash ) ; const OAEP_SHA384_MFG1 = { name : 'RSA-OAEP' , hash : { name : 'SHA-384' } , } ; Object . freeze ( OAEP_SHA384_MFG1 ) ; Object . freeze ( OAEP_SHA384_MFG1 . hash ) ; const OAEP_SHA512_MFG1 = { name : 'RSA-OAEP' , hash : { name : 'SHA-512' } , } ; Object . freeze ( OAEP_SHA512_MFG1 ) ; Object . freeze ( OAEP_SHA512_MFG1 . hash ) ; const JsonWebKeyMap = Object . freeze ( { [ JsonWebKeyRsaAlg [ 'RSA-OAEP' ] ] : OAEP_SHA1_MFG1 , [ JsonWebKeyRsaAlg [ 'RSA-OAEP-256' ] ] : OAEP_SHA256_MFG1 , [ JsonWebKeyRsaAlg [ 'RSA-OAEP-384' ] ] : OAEP_SHA384_MFG1 , [ JsonWebKeyRsaAlg [ 'RSA-OAEP-512' ] ] : OAEP_SHA512_MFG1 , } ) ; const RsaPaddingMap = Object . freeze ( { [ RsaPadding . OAEP_SHA1_MFG1 ] : OAEP_SHA1_MFG1 , [ RsaPadding . OAEP_SHA256_MFG1 ] : OAEP_SHA256_MFG1 , [ RsaPadding . OAEP_SHA384_MFG1 ] : OAEP_SHA384_MFG1 , [ RsaPadding . OAEP_SHA512_MFG1 ] : OAEP_SHA512_MFG1 , } ) ; export function getImportOptions ( keyInfo ) { const { alg } = keyInfo as RsaJsonWebKey ; const { padding } = keyInfo as BinaryKey ; if ( JsonWebKeyMap [ alg ] ) { return { format : 'jwk' , key : keyInfo as RsaJsonWebKey , wrappingAlgorithm : JsonWebKeyMap [ alg ] , } ; } else if ( RsaPaddingMap [ padding ] ) { const { format , key } = keyInfo as BinaryKey ; return { format , key , wrappingAlgorithm : RsaPaddingMap [ padding ] , } ; } throw new Error ( 'Unsupported RsaImportableKey' ) ; } export function getWrappingAlgorithm ( publicKey ? , privateKey ? ) { const privateKeys = flattenMixedCryptoKey ( privateKey ) ; if ( publicKey && privateKeys . length ) { return verify ( ... [ publicKey , ... privateKeys ] . map ( extract ) ) ; } else if ( publicKey ) { return verify ( extract ( publicKey ) ) ; } else if ( privateKeys . length ) { return verify ( ... privateKeys . map ( extract ) ) ; } throw new Error ( 'No Key provided.' ) ; } export function extract ( key ) { const { algorithm } = key ; const { name , hash } = algorithm ; return { name : name as WebCryptoRsaName , hash } ; } export function verify ( ... args ) { const [ wrappingAlgorithm , ... rest ] = args ; needs ( wrappingAlgorithm , 'Can not verify an empty set of algorithms.' ) ; const { name , hash } = wrappingAlgorithm ; needs ( JsonWebKeyRsaAlg [ name ] , 'Algorithm name is not supported.' ) ; needs ( hash && RsaHash [ hash . name ] , 'Hash name is not supported.' ) ; if ( ! rest . length ) return wrappingAlgorithm ; needs ( rest . every ( equalWrappingAlgorithm ) , 'Not all RSA keys have the same wrappingAlgorithm.' ) ; return wrappingAlgorithm ; function equalWrappingAlgorithm ( algorithm ) { return ( algorithm . name === name && algorithm . hash && algorithm . hash . name === hash . name ) ; } } export function flattenMixedCryptoKey ( key ? ) { if ( ! key ) return [ ] ; if ( isCryptoKey ( key ) ) return [ key ] ; const { nonZeroByteCryptoKey , zeroByteCryptoKey } = key ; const keys = [ nonZeroByteCryptoKey , zeroByteCryptoKey ] ; needs ( keys . every ( isCryptoKey ) , 'Not all keys are CryptoKeys.' ) ; return keys ; }