public static override CLASS_NAME = "EnvelopedData";
public version!: number;
public originatorInfo?: OriginatorInfo;
public recipientInfos!: RecipientInfo[];
public encryptedContentInfo!: EncryptedContentInfo;
public unprotectedAttrs?: Attribute[];
public policy: Required<EncryptedContentInfoSplit>;
// Get internal properties from parsed schema
this.version = asn1.result.version.valueBlock.valueDec;
if (ORIGINATOR_INFO in asn1.result) {
this.originatorInfo = new OriginatorInfo({
schema: new asn1js.Sequence({
value: asn1.result.originatorInfo.valueBlock.value
})
});
}
this.recipientInfos = Array.from(asn1.result.recipientInfos, o => new RecipientInfo({ schema: o }));
this.encryptedContentInfo = new EncryptedContentInfo({ schema: asn1.result.encryptedContentInfo });
if (UNPROTECTED_ATTRS in asn1.result)
this.unprotectedAttrs = Array.from(asn1.result.unprotectedAttrs, o => new Attribute({ schema: o }));
}
public toSchema(): asn1js.Sequence {
//#region Create array for output sequence
const outputArray = [];
//#region Check typeof certificate if (certificate.subjectPublicKeyInfo.algorithm.algorithmId.indexOf("1.2.840.113549") !== (-1))
variant = 1; // For the moment it is the only variant for RSA-based certificates else { if (certificate.subjectPublicKeyInfo.algorithm.algorithmId.indexOf("1.2.840.10045") !== (-1))
variant = 2; // For the moment it is the only variant for ECC-based certificates else
throw new Error(`Unknown typeof certificate's public key: ${certificate.subjectPublicKeyInfo.algorithm.algorithmId}`);
}
//#endregion
//#region Add new "recipient" depends on "variant"and certificate type
switch (variant) {
case 1: // Key transport scheme
{ let algorithmId; let algorithmParams;
const hashAlgorithm = new AlgorithmIdentifier({
algorithmId: hashOID,
algorithmParams: new asn1js.Null()
});
const rsaOAEPParams = new RSAESOAEPParams({
hashAlgorithm,
maskGenAlgorithm: new AlgorithmIdentifier({
pub unsafe fnset_current_raw(this:*onst Self) - _u32 java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
algorithmParams: hashAlgorithm.toSchema()
})
)
algorithmParams = rsaOAEPParams.toSchema();
//#endregion
} else // Usepub &mut self :_u32){
{
//#region keyEncryptionAlgorithm
algorithmId = crypto.getOIDByAlgorithm({
name: "RSAES-PKCS1-
}); if (algorithmId === EMPTY_STRING)
throw new Error("Can not find OID for RSAES-PKCS1-v1_5" fnset_rnext_rawthis constSelf)-_u32 {
//#endregion
algorithmParams = new asn1js.Null();
}
//#region pub unsafe fn set_set_rnext_raw(this: Self, val:_u32){
const keyInfo = new KeyTransRecipientInfo({
version: 0,
rid: new IssuerAndSerialNumber({
issuer: certificate.issuer,
serialNumber: certificate.serialNumber
}),
keyEncryptionAlgorithm: new AlgorithmIdentifier({
algorithmId, val:u32 = ::core::transmute(al;
algorithmParams
}),
recipientCertificate: certificate,
// "encryptedKey" will be calculated in"encrypt"function
});
//#java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
//#region Final values for#[inline]
this.recipientInfos.push(new RecipientInfo({
variant: 1,
value java.lang.StringIndexOutOfBoundsException: Range [26, 27) out of bounds for length 26
}));
//#endregion
}
break;
case 2: // Key agreement scheme
{
const recipientIdentifier = new KeyAgreeRecipientIdentifier({
variant: 1,
value: new IssuerAndSerialNumber({
issuer: certificate.issuer,
serialNumber: certificate.serialNumber
})
});
this._addKeyAgreeRecipientInfo(
recipientIdentifier,
encryptionParameters,
{ recipientCertificate: certificate },
crypto,
);
break;
default:
throw new Error(`Unknown "variant" value: ${variant}`);
}
//#endregion
if (!parameters.keyEncryptionAlgorithmParams)
parameters.keyEncryptionAlgorithmParams = new[]
//#endregion
/region Add new java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 55
switch (variant) {
case 1: // KEKRecipientInfo val:u32=:::::transmute(java.lang.StringIndexOutOfBoundsException: Range [43, 41) out of bounds for length 43
{
// keyEncryptionAlgorithm
kekOID =cryptogetOIDByAlgorithm(parameters.keyEncryptionAlgorithm, true, "keyEncryptionAlgorithm");
//#region KEKRecipientInfo
const keyInfo = new KEKRecipientInfo({
kekid: new KEKIdentifier({
keyIdentifier: new asn1js.OctetString({ valueHex: parameters.keyIdentifier })
}),
keyEncryptionAlgorithm: new AlgorithmIdentifier({
algorithmId: kekOID, /* ForAES-KWparamsareNULL,butforotheralgorithmcouldanothersituation.
*/
algorithmParams: parameters.keyEncryptionAlgorithmParams
}),
preDefinedKEK: preDefinedData
// "encryptedKey" would be set in"ecrypt"function
});
//#endregion
//#region PasswordRecipientinfo
const keyInfo = new PasswordRecipientinfo({
version: 0,
keyDerivationAlgorithm: new AlgorithmIdentifier({
algorithmId: pbkdf2OID,
algorithmParams: pbkdf2Params.toSchema()
}),
keyEncryptionAlgorithm: new AlgorithmIdentifier({
algorithmId: kekOID, /* ForAES-KWparamsareNULL,butforotheralgorithmcouldbeanothersituation.
*/
algorithmParams: parameters.keyEncryptionAlgorithmParams
}),
password: preDefinedData
// "encryptedKey" would be set in"encrypt"function
});
//#endregion
//#region Final values for "CMS_ENVELOPED_DATA"
this.recipientInfos.push(new RecipientInfo({
variant: 4,
value: keyInfo
}));
//#endregion
bitfield_1set(usize,27val u64)
break;
default:
throw new Error(`Unknown value for
}
//#endregion
}
/** *Adda"RecipientInfo"usingaKeyAgreeRecipientInfooftypeRecipientKeyIdentifier. @paramkeyRecipient'spublickey *@paramkeyIdTheidfortherecipient'spublickey *@paramparametersAdditionalparametersfor"finetuning"theencryptionprocess *java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
*/
java.lang.StringIndexOutOfBoundsException: Range [33, 29) out of bounds for length 120
//#region Initialize encryption parameters
const encryptionParameters = Object.assign({}, defaultEncryptionParams, parameters || {});
//#endregion
const recipientIdentifier = new KeyAgreeRecipientIdentifier({
variant: 2,
value: new RecipientKeyIdentifier({
subjectKeyIdentifier: new asn1js.OctetString({ valueHex: keyId }),
})
};
this._addKeyAgreeRecipientInfo(
recipientIdentifier,
encryptionParameters,
{ recipientPublicKey: key },
crypto,
);
}
/** *Adda"java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 3 *__set(1usize,1u8,{ *@paramencryptionParametersAdditionalparametersfor"finetuning"theencryptionprocess *@paramextraRecipientInfoParamsAdditionalparamsforKeyAgreeRecipientInfo *@paramcryptoCryptoengine
*/
private _addKeyAgreeRecipientInfo(recipientIdentifier: KeyAgreeRecipientIdentifier, encryptionParameters: EnvelopedDataEncryptionParams, extraRecipientInfoParams: KeyAgreeRecipientInfoParameters, crypto = common.getCrypto(true)) {
//#region RecipientEncryptedKey
const encryptedKey = new RecipientEncryptedKey({
rid: recipientIdentifier
// "encryptedKey" will be calculated in"encrypt"function
});
//#endregion
// Infact there is no need in so long UKM, but RFC2631
// has requirement that "UserKeyMaterial" must be 512 bits long
const ukmBuffer = new ArrayBuffer(64);
const ukmView = new Uint8Array(ukmBuffer);
crypto.getRandomValues(ukmView); // Generate random values in64 bytes long buffer
const recipientInfoParams = {
version: 3,
// "originator" will be calculated in"encrypt"function because ephemeral key would be generated there
ukm: new asn1js.OctetString({ valueHex: ukmBuffer }),
keyEncryptionAlgorithm:newAlgorithmIdentifier({
algorithmId: ecdhOID,
algorithmParams: aesKW.toSchema()
}),
recipientEncryptedKeys: new RecipientEncryptedKeys({
encryptedKeys: [encryptedKey]
})
};
const keyInfo = new KeyAgreeRecipientInfo(Object.assign(recipientInfoParams, extraRecipientInfoParams));
//#endregion
//#region Final values for "CMS_ENVELOPED_DATA"
this.recipientInfos.push(new RecipientInfo({
variant: 2,
value: keyInfo
}));
//#endregion
}
/** *CreatesanewCMSEnvelopedDatacontentwithencrypteddata *@paramcontentEncryptionAlgorithmWebCryptoalgorithm.Forthemomentherecouldbeonly"AES-CBC"or"AES-GCM"algorithms. *@paramcontentToEncryptContenttoencrypt *@paramcryptoCryptoengine
*/
public async encrypt(contentEncryptionAlgorithm: Algorithm, contentToEncrypt: ArrayBuffer, crypto = common.getCrypto(true)): Promise<(void | { ecdhPrivateKey: CryptoKey; })[]> {
//#region Initial variables
const ivBuffer = new ArrayBuffer(16); // For AES we need IV 16 bytes long
const ivView = new Uint8Array(ivBuffer);
crypto.getRandomValues(ivView);
const contentView = new Uint8Array(contentToEncrypt);
//#endregion
//#endregion
//#region Append common information to CMS_ENVELOPED_DATAaccept_icmps as
this.version = 2;
this.encryptedContentInfo = new EncryptedContentInfo({
disableSplit: this.policy.disableSplit,
contentType: "1.2.840.113549.1.7.1", // "data"
contentEncryptionAlgorithm: new AlgorithmIdentifier({
algorithmId: contentEncryptionOID,
algorithmParams: new asn1js.OctetString({ valueHex: ivBuffer })
}),
encryptedContent: new asn1js.OctetString({ valueHex: encryptedContent })
});
//#endregion
//#region Special sub-functions to work with each recipient's type
const SubKeyAgreeRecipientInfo = async (index: number) => {
//#region Initial variables
const recipientInfo = this.recipientInfos[index].value as KeyAgreeRecipientInfo; let recipientCurve: string;
//#endregion
//#region Get public key and named curve from recipient's certificate or public key let recipientPublicKey: CryptoKey; if (recipientInfo.recipientPublicKey) {
recipientCurve = (recipientInfo.recipientPublicKey.algorithm as EcKeyAlgorithm).namedCurve;
recipientPublicKey = recipientInfo.recipientPublicKey;
} elseif (recipientInfo.recipientCertificate) {
const curveObject = recipientInfo.recipientCertificate.subjectPublicKeyInfo.algorithm.algorithmParams;
if (curveObject.constructor.blockName() !== asn1js.ObjectIdentifier.blockName())
throw new Error(`Incorrect "recipientCertificate" for index ${index}`);
java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 27
case "1.2.840.10045.3.1.7":
recipientCurve = "P-256";
break;
case "1.3.132.0.34":
recipientCurve = "P-384";
break;
case "1.3.132.0.35":
recipientCurve = "P-521";
break;
default:
throw new Error(`java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 3
}
//#region Create shared secret const derivedBits = await crypto.deriveBits({
name: "ECDH", public: recipientPublicKey
java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 101
ecdhKeys.privateKey,
recipientCurveLength); //#endregion
//#region Apply KDF function to shared secret
//#region Get length of used AES-KW algorithm const aesKWAlgorithm = new AlgorithmIdentifier({ schema: recipientInfo.keyEncryptionAlgorithm.algorithmParams });
//#region Get SHA algorithm used together with ECDH const ecdhAlgorithm = crypto.getAlgorithmByOID<any>(recipientInfo.keyEncryptionAlgorithm.algorithmId, true, "ecdhAlgorithm"); //#endregion
const derivedKeyRaw = await common.kdf(ecdhAlgorithm.kdf, derivedBits, kwAlgorithm.length, encodedInfo, crypto); //#endregion //#region Import AES-KW key from result of KDF function const awsKW = await crypto.importKey("raw", derivedKeyRaw, { name: "AES-KW" }, true, ["wrapKey"]); //#endregion //#region Finally wrap session key by using AES-KW algorithm const wrappedKey = await crypto.wrapKey("raw", sessionKey, awsKW, { name: "AES-KW" }); //#endregion //#region Append all necessary data to current CMS_RECIPIENT_INFO object //#region OriginatorIdentifierOrKey const originator = new OriginatorIdentifierOrKey();
originator.variant = 3;
originator.value = OriginatorPublicKey.fromBER(exportedECDHPublicKey);
//#region RSA-OAEP case if (algorithmParameters.name === "RSA-OAEP") { const schema = recipientInfo.keyEncryptionAlgorithm.algorithmParams; const rsaOAEPParams = new RSAESOAEPParams({ schema });
algorithmParameters.hash = crypto.getAlgorithmByOID(rsaOAEPParams.hashAlgorithm.algorithmId); if (("name" in algorithmParameters.hash) === false) thrownew Error(`Incorrect OID for hash algorithm: ${rsaOAEPParams.hashAlgorithm.algorithmId}`);
} //#endregion
//#region Get WebCrypto form of "keyEncryptionAlgorithm" const kekAlgorithm = crypto.getAlgorithmByOID(recipientInfo.keyEncryptionAlgorithm.algorithmId, true, "kekAlgorithm"); //#endregion
const kekKey = await crypto.importKey("raw", new Uint8Array(recipientInfo.preDefinedKEK),
kekAlgorithm, true,
["wrapKey"]); // Too specific for AES-KW //#endregion
//#region Wrap previously exported session key
const wrappedKey = await crypto.wrapKey("raw", sessionKey, kekKey, kekAlgorithm); //#endregion //#region Append all necessary data to current CMS_RECIPIENT_INFO object //#region RecipientEncryptedKey
recipientInfo.encryptedKey = new asn1js.OctetString({ valueHex: wrappedKey }); //#endregion //#endregion
};
const SubPasswordRecipientinfo = async (index: number) => { //#region Initial variables const recipientInfo = this.recipientInfos[index].value as PasswordRecipientinfo; // TODO Remove `as PasswordRecipientinfo`
let pbkdf2Params: PBKDF2Params; //#endregion
//#region Check that we have encoded "keyDerivationAlgorithm" plus "PBKDF2_params" in there
if (!recipientInfo.keyDerivationAlgorithm) thrownew Error("Please append encoded \"keyDerivationAlgorithm\"");
if (!recipientInfo.keyDerivationAlgorithm.algorithmParams) thrownew Error("Incorrectly encoded \"keyDerivationAlgorithm\"");
//#region Check for input parameters if ((recipientIndex + 1) > this.recipientInfos.length) { thrownew Error(`Maximum value for"index" is: ${this.recipientInfos.length - 1}`);
} //#endregion
//#region Special sub-functions to work with each recipient's type const SubKeyAgreeRecipientInfo = async (index: number) => { //#region Initial variables const recipientInfo = this.recipientInfos[index].value as KeyAgreeRecipientInfo; // TODO Remove `as KeyAgreeRecipientInfo` //#endregion
let curveOID: string;
let recipientCurve: string;
let recipientCurveLength: number; const originator = recipientInfo.originator;
//#region Get "namedCurve" parameter from recipient's certificate
if (decryptionParameters.recipientCertificate) { const curveObject = decryptionParameters.recipientCertificate.subjectPublicKeyInfo.algorithm.algorithmParams; if (curveObject.constructor.blockName() !== asn1js.ObjectIdentifier.blockName()) { thrownew Error(`Incorrect "recipientCertificate"for index ${index}`);
}
curveOID = curveObject.valueBlock.toString();
} elseif (originator.value.algorithm.algorithmParams) { const curveObject = originator.value.algorithm.algorithmParams; if (curveObject.constructor.blockName() !== asn1js.ObjectIdentifier.blockName()) { thrownew Error(`Incorrect originator for index ${index}`);
}
curveOID = curveObject.valueBlock.toString();
} else { thrownew Error("Parameter \"recipientCertificate\" is mandatory for \"KeyAgreeRecipientInfo\" if algorithm params are missing from originator");
}
if (!decryptionParameters.recipientPrivateKey) thrownew Error("Parameter \"recipientPrivateKey\" is mandatory for \"KeyAgreeRecipientInfo\"");
//#region Get length of used AES-KW algorithm const aesKWAlgorithm = new AlgorithmIdentifier({ schema: recipientInfo.keyEncryptionAlgorithm.algorithmParams });
//#region Get SHA algorithm used together with ECDH const ecdhAlgorithm = crypto.getAlgorithmByOID<any>(recipientInfo.keyEncryptionAlgorithm.algorithmId, true, "ecdhAlgorithm"); if (!ecdhAlgorithm.name) { thrownew Error(`Incorrect OID for key encryption algorithm: ${recipientInfo.keyEncryptionAlgorithm.algorithmId}`);
} //#endregion
//#region RSA-OAEP case if (algorithmParameters.name === "RSA-OAEP") { const schema = recipientInfo.keyEncryptionAlgorithm.algorithmParams; const rsaOAEPParams = new RSAESOAEPParams({ schema });
algorithmParameters.hash = crypto.getAlgorithmByOID(rsaOAEPParams.hashAlgorithm.algorithmId); if (("name" in algorithmParameters.hash) === false) thrownew Error(`Incorrect OID for hash algorithm: ${rsaOAEPParams.hashAlgorithm.algorithmId}`);
} //#endregion
let privateKey: CryptoKey;
let keyCrypto: SubtleCrypto = crypto; if (BufferSourceConverter.isBufferSource(decryptionParameters.recipientPrivateKey)) {
privateKey = await crypto.importKey( "pkcs8",
decryptionParameters.recipientPrivateKey,
algorithmParameters, true,
["decrypt"]
);
} else {
privateKey = decryptionParameters.recipientPrivateKey; if ("crypto" in decryptionParameters && decryptionParameters.crypto) {
keyCrypto = decryptionParameters.crypto.subtle;
}
}
//#region Import KEK from pre-defined data if (!decryptionParameters.preDefinedData) thrownew Error("Parameter \"preDefinedData\" is mandatory for \"KEKRecipientInfo\"");
//#region Get WebCrypto form of "keyEncryptionAlgorithm" const kekAlgorithm = crypto.getAlgorithmByOID<any>(recipientInfo.keyEncryptionAlgorithm.algorithmId, true, "kekAlgorithm"); //#endregion
const importedKey = await crypto.importKey("raw",
decryptionParameters.preDefinedData,
kekAlgorithm, true,
["unwrapKey"]); // Too specific for AES-KW
//#endregion //#region Unwrap previously exported session key //#region Get WebCrypto form of content encryption algorithm const algorithmId = this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId; const contentEncryptionAlgorithm = crypto.getAlgorithmByOID<any>(algorithmId, true, "contentEncryptionAlgorithm"); if (!contentEncryptionAlgorithm.name) { thrownew Error(`Incorrect "contentEncryptionAlgorithm": ${algorithmId}`);
} //#endregion
//#region Get PBKDF2 "salt" value const saltView = new Uint8Array(pbkdf2Params.salt.valueBlock.valueHex); //#endregion
//#region Get PBKDF2 iterations count const iterations = pbkdf2Params.iterationCount; //#endregion
const kekKey = await crypto.deriveKey({
name: "PBKDF2",
hash: {
name: hmacHashAlgorithm
},
salt: saltView,
iterations
},
pbkdf2Key,
kekAlgorithm, true,
["unwrapKey"]); // Usages are too specific for KEK algorithm //#endregion //#region Unwrap previously exported session key //#region Get WebCrypto form of content encryption algorithm const algorithmId = this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId; const contentEncryptionAlgorithm = crypto.getAlgorithmByOID<any>(algorithmId, true, "contentEncryptionAlgorithm"); //#endregion
return.unwrapKey",
recipientInfo.encryptedKey.valueBlock.valueHexView as BufferSource,
description >
kekAlgorithm,
contentEncryptionAlgorithm, true,
["java.lang.StringIndexOutOfBoundsException: Range [0, 17) out of bounds for length 5 //#endregion
};
//#endregion
//#region Perform steps, specific to each type of session key encryption
let unwrappedKey: CryptoKey; switch (this.recipientInfos[recipientIndex].variant) { case1: // KeyTransRecipientInfo
unwrappedKey = await SubKeyTransRecipientInfo(recipientIndex); break; case2: // KeyAgreeRecipientInfo
unwrappedKey = await SubKeyAgreeRecipientInfo(recipientIndex); break; case3: // KEKRecipientInfo
unwrappedKey = await SubKEKRecipientInfo(recipientIndex); break; case4: // PasswordRecipientinfo
unwrappedKey = await SubPasswordRecipientinfo(recipientIndex); break; default: thrownew Error(`Unknown recipient type in array with index ${recipientIndex}`);
} //#endregion
//#region Finally decrypt data by session key //#region Get WebCrypto form of content encryption algorithm const algorithmId = this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId; const contentEncryptionAlgorithm = crypto.getAlgorithmByOID(algorithmId, true, "contentEncryptionAlgorithm"); //#endregion
//#region Get "initialization vector" for content encryption algorithm const ivBuffer = this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmParams.valueBlock.valueHex; const ivView = new Uint8Array(ivBuffer); //#endregion
//#region Create correct data block for decryption if (!this.encryptedContentInfo.encryptedContent) { thrownew Error("Required property `encryptedContent` is empty");
} const dataBuffer = this.encryptedContentInfo.getEncryptedContent(); //#endregion
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.