mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-11-24 06:25:50 +00:00
fix: add type definitions for s2kNames
This commit is contained in:
parent
64138a37c7
commit
e3302d6b3b
10
openpgp.d.ts
vendored
10
openpgp.d.ts
vendored
@ -733,6 +733,16 @@ interface VerifyMessageResult<T extends MaybeStream<Data> = MaybeStream<Data>> {
|
|||||||
signatures: VerificationResult[];
|
signatures: VerificationResult[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type S2KType = enums.s2k.argon2 | enums.s2k.gnu | enums.s2k.iterated | enums.s2k.salted | enums.s2k.simple
|
||||||
|
|
||||||
|
type S2KNames = 'argon2' | 'gnu' | 'iterated' | 'salted' | 'simple' | string
|
||||||
|
export interface S2K {
|
||||||
|
type: S2KNames
|
||||||
|
read(bytes: Uint8Array):number
|
||||||
|
write(): Uint8Array
|
||||||
|
produceKey(passphrase: string, keySize: number): Promise<Uint8Array>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Armor an OpenPGP binary packet block
|
* Armor an OpenPGP binary packet block
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import enums from '../../enums';
|
|||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
import crypto from '../../crypto';
|
import crypto from '../../crypto';
|
||||||
import type { default as loadArgonWasmModuleType } from 'argon2id';
|
import type { default as loadArgonWasmModuleType } from 'argon2id';
|
||||||
// import defaultConfig from '../../config';
|
|
||||||
import { Config } from '../../../openpgp';
|
import { Config } from '../../../openpgp';
|
||||||
const ARGON2_TYPE = 0x02; // id
|
const ARGON2_TYPE = 0x02; // id
|
||||||
const ARGON2_VERSION = 0x13;
|
const ARGON2_VERSION = 0x13;
|
||||||
@ -27,16 +27,15 @@ let argon2Promise: ReturnType<typeof loadArgonWasmModuleType>;
|
|||||||
const ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = 2 << 19;
|
const ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = 2 << 19;
|
||||||
|
|
||||||
class Argon2S2K {
|
class Argon2S2K {
|
||||||
type: 'argon2';
|
type: 'argon2';
|
||||||
private salt: Uint8Array;
|
private salt: Uint8Array;
|
||||||
private t: number;
|
private t: number;
|
||||||
private p: number;
|
private p: number;
|
||||||
private encodedM: number;
|
private encodedM: number;
|
||||||
/**
|
/**
|
||||||
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
||||||
*/
|
*/
|
||||||
constructor(config:Config) {
|
constructor(config: Config) {
|
||||||
|
|
||||||
const { passes, parallelism, memoryExponent } = config.s2kArgon2Params;
|
const { passes, parallelism, memoryExponent } = config.s2kArgon2Params;
|
||||||
|
|
||||||
this.type = 'argon2';
|
this.type = 'argon2';
|
||||||
@ -55,10 +54,10 @@ class Argon2S2K {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsing function for argon2 string-to-key specifier.
|
* Parsing function for argon2 string-to-key specifier.
|
||||||
* @param {Uint8Array} bytes - Payload of argon2 string-to-key specifier
|
* @param {Uint8Array} bytes - Payload of argon2 string-to-key specifier
|
||||||
* @returns {Integer} Actual length of the object.
|
* @returns {Integer} Actual length of the object.
|
||||||
*/
|
*/
|
||||||
read(bytes: Uint8Array) {
|
read(bytes: Uint8Array) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
@ -73,27 +72,27 @@ class Argon2S2K {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes s2k information
|
* Serializes s2k information
|
||||||
* @returns {Uint8Array} Binary representation of s2k.
|
* @returns {Uint8Array} Binary representation of s2k.
|
||||||
*/
|
*/
|
||||||
write(): Uint8Array {
|
write(): Uint8Array {
|
||||||
const arr = [
|
const arr = [
|
||||||
new Uint8Array([enums.write(enums.s2k, this.type)]),
|
new Uint8Array([enums.write(enums.s2k, this.type)]),
|
||||||
this.salt,
|
this.salt,
|
||||||
new Uint8Array([this.t, this.p, this.encodedM])
|
new Uint8Array([this.t, this.p, this.encodedM]),
|
||||||
];
|
];
|
||||||
|
|
||||||
return util.concatUint8Array(arr);
|
return util.concatUint8Array(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produces a key using the specified passphrase and the defined
|
* Produces a key using the specified passphrase and the defined
|
||||||
* hashAlgorithm
|
* hashAlgorithm
|
||||||
* @param {String} passphrase - Passphrase containing user input
|
* @param {String} passphrase - Passphrase containing user input
|
||||||
* @returns {Promise<Uint8Array>} Produced key with a length corresponding to `keySize`
|
* @returns {Promise<Uint8Array>} Produced key with a length corresponding to `keySize`
|
||||||
* @throws {Argon2OutOfMemoryError|Errors}
|
* @throws {Argon2OutOfMemoryError|Errors}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async produceKey(passphrase: string, keySize: number): Promise<Uint8Array> {
|
async produceKey(passphrase: string, keySize: number): Promise<Uint8Array> {
|
||||||
const decodedM = 2 << (this.encodedM - 1);
|
const decodedM = 2 << (this.encodedM - 1);
|
||||||
|
|
||||||
@ -101,7 +100,8 @@ class Argon2S2K {
|
|||||||
// on first load, the argon2 lib is imported and the WASM module is initialized.
|
// on first load, the argon2 lib is imported and the WASM module is initialized.
|
||||||
// the two steps need to be atomic to avoid race conditions causing multiple wasm modules
|
// the two steps need to be atomic to avoid race conditions causing multiple wasm modules
|
||||||
// being loaded when `argon2Promise` is not initialized.
|
// being loaded when `argon2Promise` is not initialized.
|
||||||
loadArgonWasmModule = loadArgonWasmModule || (await import('argon2id')).default;
|
loadArgonWasmModule =
|
||||||
|
loadArgonWasmModule || (await import('argon2id')).default;
|
||||||
argon2Promise = argon2Promise || loadArgonWasmModule();
|
argon2Promise = argon2Promise || loadArgonWasmModule();
|
||||||
|
|
||||||
// important to keep local ref to argon2 in case the module is reloaded by another instance
|
// important to keep local ref to argon2 in case the module is reloaded by another instance
|
||||||
@ -117,7 +117,7 @@ class Argon2S2K {
|
|||||||
tagLength: keySize,
|
tagLength: keySize,
|
||||||
memorySize: decodedM,
|
memorySize: decodedM,
|
||||||
parallelism: this.p,
|
parallelism: this.p,
|
||||||
passes: this.t
|
passes: this.t,
|
||||||
});
|
});
|
||||||
|
|
||||||
// a lot of memory was used, reload to deallocate
|
// a lot of memory was used, reload to deallocate
|
||||||
@ -128,13 +128,17 @@ class Argon2S2K {
|
|||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error && e.message && (
|
if (
|
||||||
e.message.includes('Unable to grow instance memory') || // Chrome
|
e instanceof Error &&
|
||||||
e.message.includes('failed to grow memory') || // Firefox
|
e.message &&
|
||||||
e.message.includes('WebAssembly.Memory.grow') || // Safari
|
(e.message.includes('Unable to grow instance memory') || // Chrome
|
||||||
e.message.includes('Out of memory') // Safari iOS
|
e.message.includes('failed to grow memory') || // Firefox
|
||||||
)) {
|
e.message.includes('WebAssembly.Memory.grow') || // Safari
|
||||||
throw new Argon2OutOfMemoryError('Could not allocate required memory for Argon2');
|
e.message.includes('Out of memory')) // Safari iOS
|
||||||
|
) {
|
||||||
|
throw new Argon2OutOfMemoryError(
|
||||||
|
'Could not allocate required memory for Argon2'
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,12 @@
|
|||||||
* @module type/s2k
|
* @module type/s2k
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Config, enums as enumsType } from '../../../openpgp';
|
import type {
|
||||||
|
Config,
|
||||||
|
S2KNames,
|
||||||
|
S2KType,
|
||||||
|
enums as enumsType,
|
||||||
|
} from '../../../openpgp';
|
||||||
import enums from '../../enums';
|
import enums from '../../enums';
|
||||||
|
|
||||||
import crypto from '../../crypto';
|
import crypto from '../../crypto';
|
||||||
@ -36,16 +41,16 @@ import util from '../../util';
|
|||||||
|
|
||||||
class GenericS2K {
|
class GenericS2K {
|
||||||
private algorithm: number;
|
private algorithm: number;
|
||||||
type: string;
|
type: S2KNames;
|
||||||
private c: number;
|
private c: number;
|
||||||
private salt: Uint8Array | null;
|
private salt: Uint8Array | null;
|
||||||
/**
|
/**
|
||||||
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
||||||
*/
|
*/
|
||||||
constructor(s2kType: enumsType.s2k.simple | enumsType.s2k.salted | enumsType.s2k.iterated, config:Config ) {
|
constructor(s2kType: S2KType, config: Config) {
|
||||||
/**
|
/**
|
||||||
* Hash function identifier, or 0 for gnu-dummy keys
|
* Hash function identifier
|
||||||
* @type {module:enums.hash | 0}
|
* @type {module:enums.hash}
|
||||||
*/
|
*/
|
||||||
this.algorithm = enums.hash.sha256;
|
this.algorithm = enums.hash.sha256;
|
||||||
/**
|
/**
|
||||||
@ -81,7 +86,7 @@ class GenericS2K {
|
|||||||
* @param {Uint8Array} bytes - Payload of string-to-key specifier
|
* @param {Uint8Array} bytes - Payload of string-to-key specifier
|
||||||
* @returns {Integer} Actual length of the object.
|
* @returns {Integer} Actual length of the object.
|
||||||
*/
|
*/
|
||||||
read(bytes: Uint8Array): Number {
|
read(bytes: Uint8Array): number {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
this.algorithm = bytes[i++];
|
this.algorithm = bytes[i++];
|
||||||
|
|
||||||
@ -103,10 +108,8 @@ class GenericS2K {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
throw new UnsupportedError('Unknown s2k type.'); // unreachable
|
throw new UnsupportedError('Unknown s2k type.'); // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,17 +118,19 @@ class GenericS2K {
|
|||||||
* @returns {Uint8Array} Binary representation of s2k.
|
* @returns {Uint8Array} Binary representation of s2k.
|
||||||
*/
|
*/
|
||||||
write(): Uint8Array {
|
write(): Uint8Array {
|
||||||
const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])];
|
const arr = [
|
||||||
|
new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm]),
|
||||||
|
];
|
||||||
|
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'simple':
|
case 'simple':
|
||||||
break;
|
break;
|
||||||
case 'salted':
|
case 'salted':
|
||||||
if (!this.salt) { throw Error('Salt was not set') }
|
if (!this.salt) throw Error('Salt was not set');
|
||||||
arr.push(this.salt);
|
arr.push(this.salt);
|
||||||
break;
|
break;
|
||||||
case 'iterated':
|
case 'iterated':
|
||||||
this.salt &&arr.push(this.salt);
|
this.salt && arr.push(this.salt);
|
||||||
arr.push(new Uint8Array([this.c]));
|
arr.push(new Uint8Array([this.c]));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -154,10 +159,17 @@ class GenericS2K {
|
|||||||
let toHash;
|
let toHash;
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'simple':
|
case 'simple':
|
||||||
toHash = util.concatUint8Array([new Uint8Array(prefixlen), encodedPassphrase]);
|
toHash = util.concatUint8Array([
|
||||||
|
new Uint8Array(prefixlen),
|
||||||
|
encodedPassphrase,
|
||||||
|
]);
|
||||||
break;
|
break;
|
||||||
case 'salted':
|
case 'salted':
|
||||||
toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, encodedPassphrase]);
|
toHash = util.concatUint8Array([
|
||||||
|
new Uint8Array(prefixlen),
|
||||||
|
this.salt,
|
||||||
|
encodedPassphrase,
|
||||||
|
]);
|
||||||
break;
|
break;
|
||||||
case 'iterated': {
|
case 'iterated': {
|
||||||
const data = util.concatUint8Array([this.salt, encodedPassphrase]);
|
const data = util.concatUint8Array([this.salt, encodedPassphrase]);
|
||||||
@ -165,7 +177,11 @@ class GenericS2K {
|
|||||||
const count = Math.max(this.getCount(), datalen);
|
const count = Math.max(this.getCount(), datalen);
|
||||||
toHash = new Uint8Array(prefixlen + count);
|
toHash = new Uint8Array(prefixlen + count);
|
||||||
toHash.set(data, prefixlen);
|
toHash.set(data, prefixlen);
|
||||||
for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) {
|
for (
|
||||||
|
let pos = prefixlen + datalen;
|
||||||
|
pos < count;
|
||||||
|
pos += datalen, datalen *= 2
|
||||||
|
) {
|
||||||
toHash.copyWithin(pos, prefixlen, pos);
|
toHash.copyWithin(pos, prefixlen, pos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -15,21 +15,22 @@
|
|||||||
// License along with this library; if not, write to the Free Software
|
// License along with this library; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
import { S2KNames } from '../../../openpgp';
|
||||||
import enums from '../../enums';
|
import enums from '../../enums';
|
||||||
import { UnsupportedError } from '../../packet/packet';
|
import { UnsupportedError } from '../../packet/packet';
|
||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
|
|
||||||
class GnuS2K {
|
class GnuS2K {
|
||||||
type: 'gnu' = 'gnu';
|
type: S2KNames = 'gnu';
|
||||||
gnuType?: 'gnu-dummy' = undefined;
|
gnuType?: 'gnu-dummy' = undefined;
|
||||||
algorithm: number = enums.hash.sha256
|
algorithm: number = enums.hash.sha256;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}).
|
* Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}).
|
||||||
* @param {Uint8Array} bytes - Payload of string-to-key specifier
|
* @param {Uint8Array} bytes - Payload of string-to-key specifier
|
||||||
* @returns {Integer} Actual length of the object.
|
* @returns {Integer} Actual length of the object.
|
||||||
*/
|
*/
|
||||||
read(bytes: Uint8Array): Number {
|
read(bytes: Uint8Array): number {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
this.algorithm = bytes[i++];
|
this.algorithm = bytes[i++];
|
||||||
if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') {
|
if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') {
|
||||||
|
|||||||
@ -5,8 +5,12 @@ import { UnsupportedError } from '../../packet/packet';
|
|||||||
import GnuS2K from './gnu';
|
import GnuS2K from './gnu';
|
||||||
|
|
||||||
import defaultConfig from '../../config';
|
import defaultConfig from '../../config';
|
||||||
import { Config } from '../../../openpgp';
|
import { Config, S2K, S2KType } from '../../../openpgp';
|
||||||
const allowedS2KTypesForEncryption = new Set([enums.s2k.argon2, enums.s2k.iterated]);
|
|
||||||
|
const allowedS2KTypesForEncryption = new Set([
|
||||||
|
enums.s2k.argon2,
|
||||||
|
enums.s2k.iterated,
|
||||||
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a new S2K instance of the given type
|
* Instantiate a new S2K instance of the given type
|
||||||
@ -15,7 +19,10 @@ const allowedS2KTypesForEncryption = new Set([enums.s2k.argon2, enums.s2k.iterat
|
|||||||
* @returns {Object} New s2k object
|
* @returns {Object} New s2k object
|
||||||
* @throws {Error} for unknown or unsupported types
|
* @throws {Error} for unknown or unsupported types
|
||||||
*/
|
*/
|
||||||
export function newS2KFromType (type: number, config:Config = defaultConfig ): Argon2S2K | GenericS2K | GnuS2K {
|
export function newS2KFromType(
|
||||||
|
type: S2KType,
|
||||||
|
config: Config = defaultConfig
|
||||||
|
): S2K {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case enums.s2k.gnu:
|
case enums.s2k.gnu:
|
||||||
return new GnuS2K();
|
return new GnuS2K();
|
||||||
@ -36,7 +43,7 @@ export function newS2KFromType (type: number, config:Config = defaultConfig ): A
|
|||||||
* @returns {Object} New s2k object
|
* @returns {Object} New s2k object
|
||||||
* @throws {Error} for unknown or unsupported types
|
* @throws {Error} for unknown or unsupported types
|
||||||
*/
|
*/
|
||||||
export function newS2KFromConfig(config:Config = defaultConfig) {
|
export function newS2KFromConfig(config: Config = defaultConfig) {
|
||||||
const { s2kType } = config;
|
const { s2kType } = config;
|
||||||
|
|
||||||
if (!allowedS2KTypesForEncryption.has(s2kType)) {
|
if (!allowedS2KTypesForEncryption.has(s2kType)) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user