node_modules/pkijs/org/pkijs/cms_simpl.js
// #region Special sub-functions to work with each recipient's type 
region Special sub-functions to work with each recipient's type
region Special sub - functions to work with each recipient ' s type
function KeyAgreeRecipientInfo(index)
        {
            var currentSequence = Promise.resolve();
            var ecdhPublicKey;
            var ecdhPrivateKey;
            var recipientCurve;
            var recipientCurveLength;
            var exportedECDHPublicKey;
            currentSequence = currentSequence.then(
                function(result)
                {
                    var curveObject = _this.recipientInfos[index].value.recipientCertificate.subjectPublicKeyInfo.algorithm.algorithm_params;
                    if((curveObject instanceof in_window.org.pkijs.asn1.OID) === false)
                        return Promise.reject("Incorrect \"recipientCertificate\" for index " + index);
                    var curveOID = curveObject.value_block.toString();
                    switch(curveOID)
                    {
                        case "1.2.840.10045.3.1.7":
                            recipientCurve = "P-256";
                            recipientCurveLength = 256;
                            break;
                        case "1.3.132.0.34":
                            recipientCurve = "P-384";
                            recipientCurveLength = 384;
                            break;
                        case "1.3.132.0.35":
                            recipientCurve = "P-521";
                            recipientCurveLength = 528;
                            break;
                        default:
                            return Promise.reject("Incorrect curve OID for index " + index);
                    }
                    return recipientCurve;
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    return crypto.generateKey({
                        name: "ECDH",
                        namedCurve: result
                    },
                    true,
                    ["deriveBits"]);
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    ecdhPublicKey = result.publicKey;
                    ecdhPrivateKey = result.privateKey;
                    return crypto.exportKey("spki", ecdhPublicKey);
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    exportedECDHPublicKey = result;
                    return _this.recipientInfos[index].value.recipientCertificate.getPublicKey({
                        algorithm: {
                            algorithm: {
                                name: "ECDH",
                                namedCurve: recipientCurve
                            },
                            usages: []
                        }
                    });
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    return crypto.deriveBits({
                        name: "ECDH",
                        public: result
                    },
                    ecdhPrivateKey,
                    recipientCurveLength);
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    var aesKWAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_params });
                    var KWalgorithm = in_window.org.pkijs.getAlgorithmByOID(aesKWAlgorithm.algorithm_id);
                    if(("name" in KWalgorithm) === false)
                        return Promise.reject("Incorrect OID for key encryption algorithm: " + aesKWAlgorithm.algorithm_id);
                    var kwLength = KWalgorithm.length;
                    var kwLengthBuffer = new ArrayBuffer(4);
                    var kwLengthView = new Uint8Array(kwLengthBuffer);
                    for(var j = 3; j >= 0; j--)
                    {
                        kwLengthView[j] = kwLength;
                        kwLength >>= 8;
                    }
                    var eccInfo = new in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo({
                        keyInfo: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({
                            algorithm_id: aesKWAlgorithm.algorithm_id,
                            algorithm_params: new in_window.org.pkijs.asn1.NULL()
                        }),
                        entityUInfo: _this.recipientInfos[index].value.ukm,
                        suppPubInfo: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: kwLengthBuffer })
                    });
                    var encodedInfo = eccInfo.toSchema().toBER(false);
                    var ecdhAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id);
                    if(("name" in ecdhAlgorithm) === false)
                        return Promise.reject("Incorrect OID for key encryption algorithm: " + _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id);
                    return in_window.org.pkijs.simpl.cms.kdf(ecdhAlgorithm.kdf, result, KWalgorithm.length, encodedInfo);
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    return crypto.importKey("raw", result, { name: "AES-KW" }, true, ["wrapKey"]);
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    return crypto.wrapKey("raw", sessionKey, result, { name: "AES-KW" });
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            currentSequence = currentSequence.then(
                function(result)
                {
                    var asn1 = org.pkijs.fromBER(exportedECDHPublicKey);
                    var originator = new in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey();
                    originator.variant = 3;
                    originator.value = new in_window.org.pkijs.simpl.cms.OriginatorPublicKey({ schema: asn1.result });
                    if("algorithm_params" in originator.value.algorithm)
                        delete originator.value.algorithm.algorithm_params;
                    _this.recipientInfos[index].value.originator = originator;
                    _this.recipientInfos[index].value.recipientEncryptedKeys.encryptedKeys[0].encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result });
                },
                function(error)
                {
                    return Promise.reject(error);
                }
                );
            return currentSequence;
        }
function KeyAgreeRecipientInfo ( index ) { var currentSequence = Promise . resolve ( ) ; var ecdhPublicKey ; var ecdhPrivateKey ; var recipientCurve ; var recipientCurveLength ; var exportedECDHPublicKey ; currentSequence = currentSequence . then ( function ( result ) { var curveObject = _this . recipientInfos [ index ] . value . recipientCertificate . subjectPublicKeyInfo . algorithm . algorithm_params ; if ( ( curveObject instanceof in_window . org . pkijs . asn1 . OID ) === false ) return Promise . reject ( "Incorrect \"recipientCertificate\" for index " + index ) ; var curveOID = curveObject . value_block . toString ( ) ; switch ( curveOID ) { case "1.2.840.10045.3.1.7" : recipientCurve = "P-256" ; recipientCurveLength = 256 ; break ; case "1.3.132.0.34" : recipientCurve = "P-384" ; recipientCurveLength = 384 ; break ; case "1.3.132.0.35" : recipientCurve = "P-521" ; recipientCurveLength = 528 ; break ; default : return Promise . reject ( "Incorrect curve OID for index " + index ) ; } return recipientCurve ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { return crypto . generateKey ( { name : "ECDH" , namedCurve : result } , true , [ "deriveBits" ] ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { ecdhPublicKey = result . publicKey ; ecdhPrivateKey = result . privateKey ; return crypto . exportKey ( "spki" , ecdhPublicKey ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { exportedECDHPublicKey = result ; return _this . recipientInfos [ index ] . value . recipientCertificate . getPublicKey ( { algorithm : { algorithm : { name : "ECDH" , namedCurve : recipientCurve } , usages : [ ] } } ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { return crypto . deriveBits ( { name : "ECDH" , public : result } , ecdhPrivateKey , recipientCurveLength ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { var aesKWAlgorithm = new in_window . org . pkijs . simpl . ALGORITHM_IDENTIFIER ( { schema : _this . recipientInfos [ index ] . value . keyEncryptionAlgorithm . algorithm_params } ) ; var KWalgorithm = in_window . org . pkijs . getAlgorithmByOID ( aesKWAlgorithm . algorithm_id ) ; if ( ( "name" in KWalgorithm ) === false ) return Promise . reject ( "Incorrect OID for key encryption algorithm: " + aesKWAlgorithm . algorithm_id ) ; var kwLength = KWalgorithm . length ; var kwLengthBuffer = new ArrayBuffer ( 4 ) ; var kwLengthView = new Uint8Array ( kwLengthBuffer ) ; for ( var j = 3 ; j >= 0 ; j -- ) { kwLengthView [ j ] = kwLength ; kwLength >>= 8 ; } var eccInfo = new in_window . org . pkijs . simpl . cms . ECC_CMS_SharedInfo ( { keyInfo : new in_window . org . pkijs . simpl . ALGORITHM_IDENTIFIER ( { algorithm_id : aesKWAlgorithm . algorithm_id , algorithm_params : new in_window . org . pkijs . asn1 . NULL ( ) } ) , entityUInfo : _this . recipientInfos [ index ] . value . ukm , suppPubInfo : new in_window . org . pkijs . asn1 . OCTETSTRING ( { value_hex : kwLengthBuffer } ) } ) ; var encodedInfo = eccInfo . toSchema ( ) . toBER ( false ) ; var ecdhAlgorithm = in_window . org . pkijs . getAlgorithmByOID ( _this . recipientInfos [ index ] . value . keyEncryptionAlgorithm . algorithm_id ) ; if ( ( "name" in ecdhAlgorithm ) === false ) return Promise . reject ( "Incorrect OID for key encryption algorithm: " + _this . recipientInfos [ index ] . value . keyEncryptionAlgorithm . algorithm_id ) ; return in_window . org . pkijs . simpl . cms . kdf ( ecdhAlgorithm . kdf , result , KWalgorithm . length , encodedInfo ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { return crypto . importKey ( "raw" , result , { name : "AES-KW" } , true , [ "wrapKey" ] ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { return crypto . wrapKey ( "raw" , sessionKey , result , { name : "AES-KW" } ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; currentSequence = currentSequence . then ( function ( result ) { var asn1 = org . pkijs . fromBER ( exportedECDHPublicKey ) ; var originator = new in_window . org . pkijs . simpl . cms . OriginatorIdentifierOrKey ( ) ; originator . variant = 3 ; originator . value = new in_window . org . pkijs . simpl . cms . OriginatorPublicKey ( { schema : asn1 . result } ) ; if ( "algorithm_params" in originator . value . algorithm ) delete originator . value . algorithm . algorithm_params ; _this . recipientInfos [ index ] . value . originator = originator ; _this . recipientInfos [ index ] . value . recipientEncryptedKeys . encryptedKeys [ 0 ] . encryptedKey = new in_window . org . pkijs . asn1 . OCTETSTRING ( { value_hex : result } ) ; } , function ( error ) { return Promise . reject ( error ) ; } ) ; return currentSequence ; }
region Special sub-functions to work with each recipient's type
region Special sub - functions to work with each recipient ' s type
// #region Initial variables  // #endregion  // #region Get "namedCurve" parameter from recipient's certificate  // #endregion  // #region Generate ephemeral ECDH key  // #endregion  // #region Export public key of ephemeral ECDH key pair  // #endregion  // #region Import recipient's public key  // #endregion  // #region Create shared secret  // #endregion  // #region Apply KDF function to shared secret  // #region Get length of used AES-KW algorithm  // #endregion  // #region Translate AES-KW length to ArrayBuffer  // #endregion  // #region Create and encode "ECC-CMS-SharedInfo" structure  /*
                             Initially RFC5753 says that AES algorithms have absent parameters.
                             But since early implementations all put NULL here. Thus, in order to be
                             "backward compatible", index also put NULL here.
                            */ // #endregion  // #region Get SHA algorithm used together with ECDH  // #endregion  // #endregion  // #region Import AES-KW key from result of KDF function  // #endregion  // #region Finally wrap session key by using AES-KW algorithm  // #endregion  // #region Append all neccessary data to current CMS_RECIPIENT_INFO object  // #region OriginatorIdentifierOrKey  // There is option when we can stay with ECParameters, but here index prefer to avoid the params  // #endregion  // #region RecipientEncryptedKey  /*
                     We will not support using of same ephemeral key for many recipients
                    */ // #endregion   // #endregion 