import { hex2b64 } from "./lib/jsbn/base64" ; import { Hex } from "./lib/asn1js/hex" ; import { Base64 } from "./lib/asn1js/base64" ; import { ASN1 } from "./lib/asn1js/asn1" ; import { RSAKey } from "./lib/jsbn/rsa" ; import { parseBigInt } from "./lib/jsbn/jsbn" ; import { KJUR } from "./lib/jsrsasign/asn1-1.0" ; param { string | Object } key constructor export class JSEncryptRSAKey extends RSAKey { constructor ( key ? ) { super ( ) ; if ( key ) { if ( typeof key === "string" ) { this . parseKey ( key ) ; } else if ( JSEncryptRSAKey . hasPrivateKeyProperty ( key ) || JSEncryptRSAKey . hasPublicKeyProperty ( key ) ) { this . parsePropertiesFrom ( key ) ; } } } todo argument { string } pem private public parseKey ( pem ) { try { let modulus = 0 ; let public_exponent = 0 ; const reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/ ; const der = reHex . test ( pem ) ? Hex . decode ( pem ) : Base64 . unarmor ( pem ) ; let asn1 = ASN1 . decode ( der ) ; if ( asn1 . sub . length === 3 ) { asn1 = asn1 . sub [ 2 ] . sub [ 0 ] ; } if ( asn1 . sub . length === 9 ) { modulus = asn1 . sub [ 1 ] . getHexStringValue ( ) ; this . n = parseBigInt ( modulus , 16 ) ; public_exponent = asn1 . sub [ 2 ] . getHexStringValue ( ) ; this . e = parseInt ( public_exponent , 16 ) ; const private_exponent = asn1 . sub [ 3 ] . getHexStringValue ( ) ; this . d = parseBigInt ( private_exponent , 16 ) ; const prime1 = asn1 . sub [ 4 ] . getHexStringValue ( ) ; this . p = parseBigInt ( prime1 , 16 ) ; const prime2 = asn1 . sub [ 5 ] . getHexStringValue ( ) ; this . q = parseBigInt ( prime2 , 16 ) ; const exponent1 = asn1 . sub [ 6 ] . getHexStringValue ( ) ; this . dmp1 = parseBigInt ( exponent1 , 16 ) ; const exponent2 = asn1 . sub [ 7 ] . getHexStringValue ( ) ; this . dmq1 = parseBigInt ( exponent2 , 16 ) ; const coefficient = asn1 . sub [ 8 ] . getHexStringValue ( ) ; this . coeff = parseBigInt ( coefficient , 16 ) ; } else if ( asn1 . sub . length === 2 ) { const bit_string = asn1 . sub [ 1 ] ; const sequence = bit_string . sub [ 0 ] ; modulus = sequence . sub [ 0 ] . getHexStringValue ( ) ; this . n = parseBigInt ( modulus , 16 ) ; public_exponent = sequence . sub [ 1 ] . getHexStringValue ( ) ; this . e = parseInt ( public_exponent , 16 ) ; } else { return false ; } return true ; } catch ( ex ) { return false ; } } returns { string } private public getPrivateBaseKey ( ) { const options = { array : [ new KJUR . asn1 . DERInteger ( { int : 0 } ) , new KJUR . asn1 . DERInteger ( { bigint : this . n } ) , new KJUR . asn1 . DERInteger ( { int : this . e } ) , new KJUR . asn1 . DERInteger ( { bigint : this . d } ) , new KJUR . asn1 . DERInteger ( { bigint : this . p } ) , new KJUR . asn1 . DERInteger ( { bigint : this . q } ) , new KJUR . asn1 . DERInteger ( { bigint : this . dmp1 } ) , new KJUR . asn1 . DERInteger ( { bigint : this . dmq1 } ) , new KJUR . asn1 . DERInteger ( { bigint : this . coeff } ) ] } ; const seq = new KJUR . asn1 . DERSequence ( options ) ; return seq . getEncodedHex ( ) ; } returns { string } public public getPrivateBaseKeyB64 ( ) { return hex2b64 ( this . getPrivateBaseKey ( ) ) ; } returns { string } private public getPublicBaseKey ( ) { const first_sequence = new KJUR . asn1 . DERSequence ( { array : [ new KJUR . asn1 . DERObjectIdentifier ( { oid : "1.2.840.113549.1.1.1" } ) , new KJUR . asn1 . DERNull ( ) ] } ) ; const second_sequence = new KJUR . asn1 . DERSequence ( { array : [ new KJUR . asn1 . DERInteger ( { bigint : this . n } ) , new KJUR . asn1 . DERInteger ( { int : this . e } ) ] } ) ; const bit_string = new KJUR . asn1 . DERBitString ( { hex : "00" + second_sequence . getEncodedHex ( ) } ) ; const seq = new KJUR . asn1 . DERSequence ( { array : [ first_sequence , bit_string ] } ) ; return seq . getEncodedHex ( ) ; } returns { string } public public getPublicBaseKeyB64 ( ) { return hex2b64 ( this . getPublicBaseKey ( ) ) ; } param { string } str param { Number } width returns { string } private public static wordwrap ( str , width ? ) { width = width || 64 ; if ( ! str ) { return str ; } const regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})" ; return str . match ( RegExp ( regex , "g" ) ) . join ( "\n" ) ; } returns { string } public public getPrivateKey ( ) { let key = "-----BEGIN RSA PRIVATE KEY-----\n" ; key += JSEncryptRSAKey . wordwrap ( this . getPrivateBaseKeyB64 ( ) ) + "\n" ; key += "-----END RSA PRIVATE KEY-----" ; return key ; } returns { string } public public getPublicKey ( ) { let key = "-----BEGIN PUBLIC KEY-----\n" ; key += JSEncryptRSAKey . wordwrap ( this . getPublicBaseKeyB64 ( ) ) + "\n" ; key += "-----END PUBLIC KEY-----" ; return key ; } param { Object } obj returns { boolean } todo private public static hasPublicKeyProperty ( obj ) { obj = obj || { } ; return ( obj . hasOwnProperty ( "n" ) && obj . hasOwnProperty ( "e" ) ) ; } param { Object } obj returns { boolean } todo private public static hasPrivateKeyProperty ( obj ) { obj = obj || { } ; return ( obj . hasOwnProperty ( "n" ) && obj . hasOwnProperty ( "e" ) && obj . hasOwnProperty ( "d" ) && obj . hasOwnProperty ( "p" ) && obj . hasOwnProperty ( "q" ) && obj . hasOwnProperty ( "dmp1" ) && obj . hasOwnProperty ( "dmq1" ) && obj . hasOwnProperty ( "coeff" ) ) ; } param { Object } obj private public parsePropertiesFrom ( obj ) { this . n = obj . n ; this . e = obj . e ; if ( obj . hasOwnProperty ( "d" ) ) { this . d = obj . d ; this . p = obj . p ; this . q = obj . q ; this . dmp1 = obj . dmp1 ; this . dmq1 = obj . dmq1 ; this . coeff = obj . coeff ; } } }