Merge pull request #16959 from Snuffleupagus/rm-CipherTransformFactory-closure
Remove the closure from the `CipherTransformFactory` class
This commit is contained in:
commit
98671c3618
@ -1418,14 +1418,14 @@ class CipherTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
class CipherTransformFactory {
|
||||||
const defaultPasswordBytes = new Uint8Array([
|
static #defaultPasswordBytes = new Uint8Array([
|
||||||
0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56,
|
0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56,
|
||||||
0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
|
0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
|
||||||
0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a,
|
0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function createEncryptionKey20(
|
#createEncryptionKey20(
|
||||||
revision,
|
revision,
|
||||||
password,
|
password,
|
||||||
ownerPassword,
|
ownerPassword,
|
||||||
@ -1471,7 +1471,7 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareKeyData(
|
#prepareKeyData(
|
||||||
fileId,
|
fileId,
|
||||||
password,
|
password,
|
||||||
ownerPassword,
|
ownerPassword,
|
||||||
@ -1494,7 +1494,7 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
}
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
while (i < 32) {
|
while (i < 32) {
|
||||||
hashData[i++] = defaultPasswordBytes[j++];
|
hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++];
|
||||||
}
|
}
|
||||||
// as now the padded password in the hashData[0..i]
|
// as now the padded password in the hashData[0..i]
|
||||||
for (j = 0, n = ownerPassword.length; j < n; ++j) {
|
for (j = 0, n = ownerPassword.length; j < n; ++j) {
|
||||||
@ -1525,7 +1525,7 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
|
|
||||||
if (revision >= 3) {
|
if (revision >= 3) {
|
||||||
for (i = 0; i < 32; ++i) {
|
for (i = 0; i < 32; ++i) {
|
||||||
hashData[i] = defaultPasswordBytes[i];
|
hashData[i] = CipherTransformFactory.#defaultPasswordBytes[i];
|
||||||
}
|
}
|
||||||
for (j = 0, n = fileId.length; j < n; ++j) {
|
for (j = 0, n = fileId.length; j < n; ++j) {
|
||||||
hashData[i++] = fileId[j];
|
hashData[i++] = fileId[j];
|
||||||
@ -1548,7 +1548,9 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cipher = new ARCFourCipher(encryptionKey);
|
cipher = new ARCFourCipher(encryptionKey);
|
||||||
checkData = cipher.encryptBlock(defaultPasswordBytes);
|
checkData = cipher.encryptBlock(
|
||||||
|
CipherTransformFactory.#defaultPasswordBytes
|
||||||
|
);
|
||||||
for (j = 0, n = checkData.length; j < n; ++j) {
|
for (j = 0, n = checkData.length; j < n; ++j) {
|
||||||
if (userPassword[j] !== checkData[j]) {
|
if (userPassword[j] !== checkData[j]) {
|
||||||
return null;
|
return null;
|
||||||
@ -1558,7 +1560,7 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
return encryptionKey;
|
return encryptionKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeUserPassword(password, ownerPassword, revision, keyLength) {
|
#decodeUserPassword(password, ownerPassword, revision, keyLength) {
|
||||||
const hashData = new Uint8Array(32);
|
const hashData = new Uint8Array(32);
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const n = Math.min(32, password.length);
|
const n = Math.min(32, password.length);
|
||||||
@ -1567,7 +1569,7 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
}
|
}
|
||||||
let j = 0;
|
let j = 0;
|
||||||
while (i < 32) {
|
while (i < 32) {
|
||||||
hashData[i++] = defaultPasswordBytes[j++];
|
hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++];
|
||||||
}
|
}
|
||||||
let hash = calculateMD5(hashData, 0, i);
|
let hash = calculateMD5(hashData, 0, i);
|
||||||
const keyLengthInBytes = keyLength >> 3;
|
const keyLengthInBytes = keyLength >> 3;
|
||||||
@ -1595,9 +1597,7 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
return userPassword;
|
return userPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
const identityName = Name.get("Identity");
|
#buildObjectKey(num, gen, encryptionKey, isAes = false) {
|
||||||
|
|
||||||
function buildObjectKey(num, gen, encryptionKey, isAes = false) {
|
|
||||||
const key = new Uint8Array(encryptionKey.length + 9);
|
const key = new Uint8Array(encryptionKey.length + 9);
|
||||||
const n = encryptionKey.length;
|
const n = encryptionKey.length;
|
||||||
let i;
|
let i;
|
||||||
@ -1619,242 +1619,229 @@ const CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
|
return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildCipherConstructor(cf, name, num, gen, key) {
|
#buildCipherConstructor(cf, name, num, gen, key) {
|
||||||
if (!(name instanceof Name)) {
|
if (!(name instanceof Name)) {
|
||||||
throw new FormatError("Invalid crypt filter name.");
|
throw new FormatError("Invalid crypt filter name.");
|
||||||
}
|
}
|
||||||
|
const self = this;
|
||||||
const cryptFilter = cf.get(name.name);
|
const cryptFilter = cf.get(name.name);
|
||||||
let cfm;
|
const cfm = cryptFilter?.get("CFM");
|
||||||
if (cryptFilter !== null && cryptFilter !== undefined) {
|
|
||||||
cfm = cryptFilter.get("CFM");
|
|
||||||
}
|
|
||||||
if (!cfm || cfm.name === "None") {
|
if (!cfm || cfm.name === "None") {
|
||||||
return function cipherTransformFactoryBuildCipherConstructorNone() {
|
return function () {
|
||||||
return new NullCipher();
|
return new NullCipher();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (cfm.name === "V2") {
|
if (cfm.name === "V2") {
|
||||||
return function cipherTransformFactoryBuildCipherConstructorV2() {
|
return function () {
|
||||||
return new ARCFourCipher(
|
return new ARCFourCipher(
|
||||||
buildObjectKey(num, gen, key, /* isAes = */ false)
|
self.#buildObjectKey(num, gen, key, /* isAes = */ false)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (cfm.name === "AESV2") {
|
if (cfm.name === "AESV2") {
|
||||||
return function cipherTransformFactoryBuildCipherConstructorAESV2() {
|
return function () {
|
||||||
return new AES128Cipher(
|
return new AES128Cipher(
|
||||||
buildObjectKey(num, gen, key, /* isAes = */ true)
|
self.#buildObjectKey(num, gen, key, /* isAes = */ true)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (cfm.name === "AESV3") {
|
if (cfm.name === "AESV3") {
|
||||||
return function cipherTransformFactoryBuildCipherConstructorAESV3() {
|
return function () {
|
||||||
return new AES256Cipher(key);
|
return new AES256Cipher(key);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw new FormatError("Unknown crypto method");
|
throw new FormatError("Unknown crypto method");
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
constructor(dict, fileId, password) {
|
||||||
class CipherTransformFactory {
|
const filter = dict.get("Filter");
|
||||||
constructor(dict, fileId, password) {
|
if (!isName(filter, "Standard")) {
|
||||||
const filter = dict.get("Filter");
|
throw new FormatError("unknown encryption method");
|
||||||
if (!isName(filter, "Standard")) {
|
}
|
||||||
throw new FormatError("unknown encryption method");
|
this.filterName = filter.name;
|
||||||
}
|
this.dict = dict;
|
||||||
this.filterName = filter.name;
|
const algorithm = dict.get("V");
|
||||||
this.dict = dict;
|
if (
|
||||||
const algorithm = dict.get("V");
|
!Number.isInteger(algorithm) ||
|
||||||
if (
|
(algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5)
|
||||||
!Number.isInteger(algorithm) ||
|
) {
|
||||||
(algorithm !== 1 &&
|
throw new FormatError("unsupported encryption algorithm");
|
||||||
algorithm !== 2 &&
|
}
|
||||||
algorithm !== 4 &&
|
this.algorithm = algorithm;
|
||||||
algorithm !== 5)
|
let keyLength = dict.get("Length");
|
||||||
) {
|
if (!keyLength) {
|
||||||
throw new FormatError("unsupported encryption algorithm");
|
// Spec asks to rely on encryption dictionary's Length entry, however
|
||||||
}
|
// some PDFs don't have it. Trying to recover.
|
||||||
this.algorithm = algorithm;
|
if (algorithm <= 3) {
|
||||||
let keyLength = dict.get("Length");
|
// For 1 and 2 it's fixed to 40-bit, for 3 40-bit is a minimal value.
|
||||||
if (!keyLength) {
|
keyLength = 40;
|
||||||
// Spec asks to rely on encryption dictionary's Length entry, however
|
|
||||||
// some PDFs don't have it. Trying to recover.
|
|
||||||
if (algorithm <= 3) {
|
|
||||||
// For 1 and 2 it's fixed to 40-bit, for 3 40-bit is a minimal value.
|
|
||||||
keyLength = 40;
|
|
||||||
} else {
|
|
||||||
// Trying to find default handler -- it usually has Length.
|
|
||||||
const cfDict = dict.get("CF");
|
|
||||||
const streamCryptoName = dict.get("StmF");
|
|
||||||
if (cfDict instanceof Dict && streamCryptoName instanceof Name) {
|
|
||||||
cfDict.suppressEncryption = true; // See comment below.
|
|
||||||
const handlerDict = cfDict.get(streamCryptoName.name);
|
|
||||||
keyLength = handlerDict?.get("Length") || 128;
|
|
||||||
if (keyLength < 40) {
|
|
||||||
// Sometimes it's incorrect value of bits, generators specify
|
|
||||||
// bytes.
|
|
||||||
keyLength <<= 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!Number.isInteger(keyLength) ||
|
|
||||||
keyLength < 40 ||
|
|
||||||
keyLength % 8 !== 0
|
|
||||||
) {
|
|
||||||
throw new FormatError("invalid key length");
|
|
||||||
}
|
|
||||||
|
|
||||||
const ownerBytes = stringToBytes(dict.get("O")),
|
|
||||||
userBytes = stringToBytes(dict.get("U"));
|
|
||||||
// prepare keys
|
|
||||||
const ownerPassword = ownerBytes.subarray(0, 32);
|
|
||||||
const userPassword = userBytes.subarray(0, 32);
|
|
||||||
const flags = dict.get("P");
|
|
||||||
const revision = dict.get("R");
|
|
||||||
// meaningful when V is 4 or 5
|
|
||||||
const encryptMetadata =
|
|
||||||
(algorithm === 4 || algorithm === 5) &&
|
|
||||||
dict.get("EncryptMetadata") !== false;
|
|
||||||
this.encryptMetadata = encryptMetadata;
|
|
||||||
|
|
||||||
const fileIdBytes = stringToBytes(fileId);
|
|
||||||
let passwordBytes;
|
|
||||||
if (password) {
|
|
||||||
if (revision === 6) {
|
|
||||||
try {
|
|
||||||
password = utf8StringToString(password);
|
|
||||||
} catch {
|
|
||||||
warn(
|
|
||||||
"CipherTransformFactory: Unable to convert UTF8 encoded password."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
passwordBytes = stringToBytes(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
let encryptionKey;
|
|
||||||
if (algorithm !== 5) {
|
|
||||||
encryptionKey = prepareKeyData(
|
|
||||||
fileIdBytes,
|
|
||||||
passwordBytes,
|
|
||||||
ownerPassword,
|
|
||||||
userPassword,
|
|
||||||
flags,
|
|
||||||
revision,
|
|
||||||
keyLength,
|
|
||||||
encryptMetadata
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
const ownerValidationSalt = ownerBytes.subarray(32, 40);
|
// Trying to find default handler -- it usually has Length.
|
||||||
const ownerKeySalt = ownerBytes.subarray(40, 48);
|
const cfDict = dict.get("CF");
|
||||||
const uBytes = userBytes.subarray(0, 48);
|
const streamCryptoName = dict.get("StmF");
|
||||||
const userValidationSalt = userBytes.subarray(32, 40);
|
if (cfDict instanceof Dict && streamCryptoName instanceof Name) {
|
||||||
const userKeySalt = userBytes.subarray(40, 48);
|
cfDict.suppressEncryption = true; // See comment below.
|
||||||
const ownerEncryption = stringToBytes(dict.get("OE"));
|
const handlerDict = cfDict.get(streamCryptoName.name);
|
||||||
const userEncryption = stringToBytes(dict.get("UE"));
|
keyLength = handlerDict?.get("Length") || 128;
|
||||||
const perms = stringToBytes(dict.get("Perms"));
|
if (keyLength < 40) {
|
||||||
encryptionKey = createEncryptionKey20(
|
// Sometimes it's incorrect value of bits, generators specify
|
||||||
revision,
|
// bytes.
|
||||||
passwordBytes,
|
keyLength <<= 3;
|
||||||
ownerPassword,
|
}
|
||||||
ownerValidationSalt,
|
|
||||||
ownerKeySalt,
|
|
||||||
uBytes,
|
|
||||||
userPassword,
|
|
||||||
userValidationSalt,
|
|
||||||
userKeySalt,
|
|
||||||
ownerEncryption,
|
|
||||||
userEncryption,
|
|
||||||
perms
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!encryptionKey && !password) {
|
|
||||||
throw new PasswordException(
|
|
||||||
"No password given",
|
|
||||||
PasswordResponses.NEED_PASSWORD
|
|
||||||
);
|
|
||||||
} else if (!encryptionKey && password) {
|
|
||||||
// Attempting use the password as an owner password
|
|
||||||
const decodedPassword = decodeUserPassword(
|
|
||||||
passwordBytes,
|
|
||||||
ownerPassword,
|
|
||||||
revision,
|
|
||||||
keyLength
|
|
||||||
);
|
|
||||||
encryptionKey = prepareKeyData(
|
|
||||||
fileIdBytes,
|
|
||||||
decodedPassword,
|
|
||||||
ownerPassword,
|
|
||||||
userPassword,
|
|
||||||
flags,
|
|
||||||
revision,
|
|
||||||
keyLength,
|
|
||||||
encryptMetadata
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!encryptionKey) {
|
|
||||||
throw new PasswordException(
|
|
||||||
"Incorrect Password",
|
|
||||||
PasswordResponses.INCORRECT_PASSWORD
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.encryptionKey = encryptionKey;
|
|
||||||
|
|
||||||
if (algorithm >= 4) {
|
|
||||||
const cf = dict.get("CF");
|
|
||||||
if (cf instanceof Dict) {
|
|
||||||
// The 'CF' dictionary itself should not be encrypted, and by setting
|
|
||||||
// `suppressEncryption` we can prevent an infinite loop inside of
|
|
||||||
// `XRef_fetchUncompressed` if the dictionary contains indirect
|
|
||||||
// objects (fixes issue7665.pdf).
|
|
||||||
cf.suppressEncryption = true;
|
|
||||||
}
|
}
|
||||||
this.cf = cf;
|
|
||||||
this.stmf = dict.get("StmF") || identityName;
|
|
||||||
this.strf = dict.get("StrF") || identityName;
|
|
||||||
this.eff = dict.get("EFF") || this.stmf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) {
|
||||||
|
throw new FormatError("invalid key length");
|
||||||
|
}
|
||||||
|
|
||||||
createCipherTransform(num, gen) {
|
const ownerBytes = stringToBytes(dict.get("O")),
|
||||||
if (this.algorithm === 4 || this.algorithm === 5) {
|
userBytes = stringToBytes(dict.get("U"));
|
||||||
return new CipherTransform(
|
// prepare keys
|
||||||
buildCipherConstructor(
|
const ownerPassword = ownerBytes.subarray(0, 32);
|
||||||
this.cf,
|
const userPassword = userBytes.subarray(0, 32);
|
||||||
this.strf,
|
const flags = dict.get("P");
|
||||||
num,
|
const revision = dict.get("R");
|
||||||
gen,
|
// meaningful when V is 4 or 5
|
||||||
this.encryptionKey
|
const encryptMetadata =
|
||||||
),
|
(algorithm === 4 || algorithm === 5) &&
|
||||||
buildCipherConstructor(
|
dict.get("EncryptMetadata") !== false;
|
||||||
this.cf,
|
this.encryptMetadata = encryptMetadata;
|
||||||
this.stmf,
|
|
||||||
num,
|
const fileIdBytes = stringToBytes(fileId);
|
||||||
gen,
|
let passwordBytes;
|
||||||
this.encryptionKey
|
if (password) {
|
||||||
)
|
if (revision === 6) {
|
||||||
);
|
try {
|
||||||
|
password = utf8StringToString(password);
|
||||||
|
} catch {
|
||||||
|
warn(
|
||||||
|
"CipherTransformFactory: Unable to convert UTF8 encoded password."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// algorithms 1 and 2
|
passwordBytes = stringToBytes(password);
|
||||||
const key = buildObjectKey(
|
}
|
||||||
num,
|
|
||||||
gen,
|
let encryptionKey;
|
||||||
this.encryptionKey,
|
if (algorithm !== 5) {
|
||||||
/* isAes = */ false
|
encryptionKey = this.#prepareKeyData(
|
||||||
|
fileIdBytes,
|
||||||
|
passwordBytes,
|
||||||
|
ownerPassword,
|
||||||
|
userPassword,
|
||||||
|
flags,
|
||||||
|
revision,
|
||||||
|
keyLength,
|
||||||
|
encryptMetadata
|
||||||
);
|
);
|
||||||
const cipherConstructor = function buildCipherCipherConstructor() {
|
} else {
|
||||||
return new ARCFourCipher(key);
|
const ownerValidationSalt = ownerBytes.subarray(32, 40);
|
||||||
};
|
const ownerKeySalt = ownerBytes.subarray(40, 48);
|
||||||
return new CipherTransform(cipherConstructor, cipherConstructor);
|
const uBytes = userBytes.subarray(0, 48);
|
||||||
|
const userValidationSalt = userBytes.subarray(32, 40);
|
||||||
|
const userKeySalt = userBytes.subarray(40, 48);
|
||||||
|
const ownerEncryption = stringToBytes(dict.get("OE"));
|
||||||
|
const userEncryption = stringToBytes(dict.get("UE"));
|
||||||
|
const perms = stringToBytes(dict.get("Perms"));
|
||||||
|
encryptionKey = this.#createEncryptionKey20(
|
||||||
|
revision,
|
||||||
|
passwordBytes,
|
||||||
|
ownerPassword,
|
||||||
|
ownerValidationSalt,
|
||||||
|
ownerKeySalt,
|
||||||
|
uBytes,
|
||||||
|
userPassword,
|
||||||
|
userValidationSalt,
|
||||||
|
userKeySalt,
|
||||||
|
ownerEncryption,
|
||||||
|
userEncryption,
|
||||||
|
perms
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!encryptionKey && !password) {
|
||||||
|
throw new PasswordException(
|
||||||
|
"No password given",
|
||||||
|
PasswordResponses.NEED_PASSWORD
|
||||||
|
);
|
||||||
|
} else if (!encryptionKey && password) {
|
||||||
|
// Attempting use the password as an owner password
|
||||||
|
const decodedPassword = this.#decodeUserPassword(
|
||||||
|
passwordBytes,
|
||||||
|
ownerPassword,
|
||||||
|
revision,
|
||||||
|
keyLength
|
||||||
|
);
|
||||||
|
encryptionKey = this.#prepareKeyData(
|
||||||
|
fileIdBytes,
|
||||||
|
decodedPassword,
|
||||||
|
ownerPassword,
|
||||||
|
userPassword,
|
||||||
|
flags,
|
||||||
|
revision,
|
||||||
|
keyLength,
|
||||||
|
encryptMetadata
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!encryptionKey) {
|
||||||
|
throw new PasswordException(
|
||||||
|
"Incorrect Password",
|
||||||
|
PasswordResponses.INCORRECT_PASSWORD
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.encryptionKey = encryptionKey;
|
||||||
|
|
||||||
|
if (algorithm >= 4) {
|
||||||
|
const cf = dict.get("CF");
|
||||||
|
if (cf instanceof Dict) {
|
||||||
|
// The 'CF' dictionary itself should not be encrypted, and by setting
|
||||||
|
// `suppressEncryption` we can prevent an infinite loop inside of
|
||||||
|
// `XRef_fetchUncompressed` if the dictionary contains indirect
|
||||||
|
// objects (fixes issue7665.pdf).
|
||||||
|
cf.suppressEncryption = true;
|
||||||
|
}
|
||||||
|
this.cf = cf;
|
||||||
|
this.stmf = dict.get("StmF") || Name.get("Identity");
|
||||||
|
this.strf = dict.get("StrF") || Name.get("Identity");
|
||||||
|
this.eff = dict.get("EFF") || this.stmf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CipherTransformFactory;
|
createCipherTransform(num, gen) {
|
||||||
})();
|
if (this.algorithm === 4 || this.algorithm === 5) {
|
||||||
|
return new CipherTransform(
|
||||||
|
this.#buildCipherConstructor(
|
||||||
|
this.cf,
|
||||||
|
this.strf,
|
||||||
|
num,
|
||||||
|
gen,
|
||||||
|
this.encryptionKey
|
||||||
|
),
|
||||||
|
this.#buildCipherConstructor(
|
||||||
|
this.cf,
|
||||||
|
this.stmf,
|
||||||
|
num,
|
||||||
|
gen,
|
||||||
|
this.encryptionKey
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// algorithms 1 and 2
|
||||||
|
const key = this.#buildObjectKey(
|
||||||
|
num,
|
||||||
|
gen,
|
||||||
|
this.encryptionKey,
|
||||||
|
/* isAes = */ false
|
||||||
|
);
|
||||||
|
const cipherConstructor = function () {
|
||||||
|
return new ARCFourCipher(key);
|
||||||
|
};
|
||||||
|
return new CipherTransform(cipherConstructor, cipherConstructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AES128Cipher,
|
AES128Cipher,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user