Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/openpgpjs/openpgpjs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlarabr <larabr@protonmail.com>2022-03-09 19:00:12 +0300
committerGitHub <noreply@github.com>2022-03-09 19:00:12 +0300
commitd89cc48bf33f7f9b9bff9f87e0da0f04724d700c (patch)
treedc20c213f8a795169a6de83a490e60e05e339d35
parenta1ef5f509f01504225ec9e7faf339b06ce467827 (diff)
TypeScript: rely on new `web-stream-tools` types, fix `SignOptions` (#1502)
The updated stream types improve type inference and checks, in particular when using ReadableStreams. Also: - add `EncryptSessionKeyOptions` to make it easier to declare wrapper functions of `encryptSessionKey`; - tighter output type inference in `Message.getText()` and `.getLiteralData()`.
-rw-r--r--openpgp.d.ts46
-rw-r--r--package-lock.json20
-rw-r--r--package.json5
-rw-r--r--test/typescript/definitions.ts52
4 files changed, 75 insertions, 48 deletions
diff --git a/openpgp.d.ts b/openpgp.d.ts
index 911a78fc..a30cbdc6 100644
--- a/openpgp.d.ts
+++ b/openpgp.d.ts
@@ -7,6 +7,8 @@
* - Errietta Kostala <https://github.com/errietta>
*/
+import type { WebStream as GenericWebStream, NodeStream as GenericNodeStream } from '@openpgp/web-stream-tools';
+
/* ############## v5 KEY #################### */
// The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties.
// The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey.
@@ -171,15 +173,9 @@ export class CleartextMessage {
/* ############## v5 MSG #################### */
export function generateSessionKey(options: { encryptionKeys: MaybeArray<PublicKey>, date?: Date, encryptionUserIDs?: MaybeArray<UserID>, config?: PartialConfig }): Promise<SessionKey>;
-export function encryptSessionKey(options: SessionKey & {
- encryptionKeys?: MaybeArray<PublicKey>, passwords?: MaybeArray<string>, format?: 'armored', wildcard?: boolean, encryptionKeyIDs?: MaybeArray<KeyID>, date?: Date, encryptionUserIDs?: MaybeArray<UserID>, config?: PartialConfig
-}) : Promise<string>;
-export function encryptSessionKey(options: SessionKey & {
- encryptionKeys?: MaybeArray<PublicKey>, passwords?: MaybeArray<string>, format: 'binary', wildcard?: boolean, encryptionKeyIDs?: MaybeArray<KeyID>, date?: Date, encryptionUserIDs?: MaybeArray<UserID>, config?: PartialConfig
-}) : Promise<Uint8Array>;
-export function encryptSessionKey(options: SessionKey & {
- encryptionKeys?: MaybeArray<PublicKey>, passwords?: MaybeArray<string>, format: 'object', wildcard?: boolean, encryptionKeyIDs?: MaybeArray<KeyID>, date?: Date, encryptionUserIDs?: MaybeArray<UserID>, config?: PartialConfig
-}) : Promise<Message<Data>>;
+export function encryptSessionKey(options: EncryptSessionKeyOptions & { format?: 'armored' }): Promise<string>;
+export function encryptSessionKey(options: EncryptSessionKeyOptions & { format: 'binary' }): Promise<Uint8Array>;
+export function encryptSessionKey(options: EncryptSessionKeyOptions & { format: 'object' }): Promise<Message<Data>>;
export function decryptSessionKeys<T extends MaybeStream<Data>>(options: { message: Message<T>, decryptionKeys?: MaybeArray<PrivateKey>, passwords?: MaybeArray<string>, date?: Date, config?: PartialConfig }): Promise<SessionKey[]>;
export function readMessage<T extends MaybeStream<string>>(options: { armoredMessage: T, config?: PartialConfig }): Promise<Message<T>>;
@@ -271,7 +267,7 @@ export class Message<T extends MaybeStream<Data>> {
/** Get literal data that is the body of the message
*/
- public getLiteralData(): MaybeStream<Uint8Array> | null;
+ public getLiteralData(): (T extends Stream<Data> ? WebStream<Uint8Array> : Uint8Array) | null;
/** Returns the key IDs of the keys that signed the message
*/
@@ -279,7 +275,7 @@ export class Message<T extends MaybeStream<Data>> {
/** Get literal data as text
*/
- public getText(): MaybeStream<string> | null;
+ public getText(): (T extends Stream<Data> ? WebStream<string> : string) | null;
public getFilename(): string | null;
@@ -548,18 +544,10 @@ export class PacketList<T extends AnyPacket> extends Array<T> {
/* ############## v5 STREAM #################### */
type Data = Uint8Array | string;
-interface BaseStream<T extends Data> extends AsyncIterable<T> { }
-interface WebStream<T extends Data> extends BaseStream<T> { // copied+simplified version of ReadableStream from lib.dom.d.ts
- readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function;
- cancel(reason?: any): Promise<void>;
-}
-interface NodeStream<T extends Data> extends BaseStream<T> { // copied+simplified version of ReadableStream from @types/node/index.d.ts
- readable: boolean; pipe: Function; unpipe: Function; wrap: Function;
- read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this;
- isPaused(): boolean; unshift(chunk: string | Uint8Array): void;
-}
-type Stream<T extends Data> = WebStream<T> | NodeStream<T>;
-type MaybeStream<T extends Data> = T | Stream<T>;
+export interface WebStream<T extends Data> extends GenericWebStream<T> {}
+export interface NodeStream<T extends Data> extends GenericNodeStream<T> {}
+export type Stream<T extends Data> = WebStream<T> | NodeStream<T>;
+export type MaybeStream<T extends Data> = T | Stream<T>;
/* ############## v5 GENERAL #################### */
type MaybeArray<T> = T | Array<T>;
@@ -627,7 +615,7 @@ interface DecryptOptions {
interface SignOptions {
message: CleartextMessage | Message<MaybeStream<Data>>;
- signingKeys?: MaybeArray<PrivateKey>;
+ signingKeys: MaybeArray<PrivateKey>;
format?: 'armored' | 'binary' | 'object';
detached?: boolean;
signingKeyIDs?: MaybeArray<KeyID>;
@@ -652,6 +640,16 @@ interface VerifyOptions {
config?: PartialConfig;
}
+interface EncryptSessionKeyOptions extends SessionKey {
+ encryptionKeys?: MaybeArray<PublicKey>,
+ passwords?: MaybeArray<string>,
+ format?: 'armored' | 'binary' | 'object',
+ date?: Date,
+ wildcard?: boolean,
+ encryptionKeyIDs?: MaybeArray<KeyID>,
+ encryptionUserIDs?: MaybeArray<UserID>,
+ config?: PartialConfig
+}
interface SerializedKeyPair<T extends string|Uint8Array> {
privateKey: T;
diff --git a/package-lock.json b/package-lock.json
index e768a9a1..2c59caa6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -267,13 +267,21 @@
"dev": true
},
"@openpgp/web-stream-tools": {
- "version": "0.0.9",
- "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.9.tgz",
- "integrity": "sha512-GEKuXpQRshUqgKH4sMcwYbHolxaUSHIowcIMd02EsnLv4q5acP0z9pRUy3kjV0ZyRPgyD0vXAy60Rf0MPKoCMw==",
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.10.tgz",
+ "integrity": "sha512-1ONZADML0fb0RJR5UiGYPnRf9VaYBYUBc1gF9jyq57sHkr58cp5/BQHS+ivrqbRw21Sb70FKTssmJbRe71V+kw==",
"dev": true,
"requires": {
"@mattiasbuelens/web-streams-adapter": "~0.1.0",
"web-streams-polyfill": "~3.0.3"
+ },
+ "dependencies": {
+ "web-streams-polyfill": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz",
+ "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==",
+ "dev": true
+ }
}
},
"@rollup/plugin-commonjs": {
@@ -5401,9 +5409,9 @@
"dev": true
},
"web-streams-polyfill": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz",
- "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz",
+ "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==",
"dev": true
},
"which": {
diff --git a/package.json b/package.json
index a19b1ba4..a5ccc3ee 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,7 @@
"@openpgp/pako": "^1.0.12",
"@openpgp/seek-bzip": "^1.0.5-git",
"@openpgp/tweetnacl": "^1.0.3",
- "@openpgp/web-stream-tools": "0.0.9",
+ "@openpgp/web-stream-tools": "^0.0.10",
"@rollup/plugin-commonjs": "^11.1.0",
"@rollup/plugin-node-resolve": "^7.1.3",
"@rollup/plugin-replace": "^2.3.2",
@@ -87,7 +87,8 @@
"rollup": "^2.38.5",
"rollup-plugin-terser": "^7.0.2",
"sinon": "^4.3.0",
- "typescript": "^4.1.2"
+ "typescript": "^4.1.2",
+ "web-streams-polyfill": "^3.2.0"
},
"dependencies": {
"asn1.js": "^5.0.0"
diff --git a/test/typescript/definitions.ts b/test/typescript/definitions.ts
index deeedba0..3bc2f547 100644
--- a/test/typescript/definitions.ts
+++ b/test/typescript/definitions.ts
@@ -5,6 +5,8 @@
* - if it fails to build, edit the file to match type definitions
* - if it fails to run, edit this file to match the actual library API, then edit the definitions file (openpgp.d.ts) accordingly.
*/
+import { ReadableStream as WebReadableStream } from 'web-streams-polyfill';
+import { createReadStream } from 'fs';
import { expect } from 'chai';
import {
@@ -12,7 +14,8 @@ import {
readMessage, createMessage, Message, createCleartextMessage,
encrypt, decrypt, sign, verify, config, enums,
generateSessionKey, encryptSessionKey, decryptSessionKeys,
- LiteralDataPacket, PacketList, CompressedDataPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket, CleartextMessage
+ LiteralDataPacket, PacketList, CompressedDataPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket, CleartextMessage,
+ WebStream, NodeStream,
} from '../..';
(async () => {
@@ -100,8 +103,10 @@ import {
// Get session keys from encrypted message
const sessionKeys = await decryptSessionKeys({ message: await readMessage({ binaryMessage: encryptedBinary }), decryptionKeys: privateKeys });
expect(sessionKeys).to.have.length(1);
- const encryptedSessionKeys: string = await encryptSessionKey({ ...sessionKeys[0], passwords: 'pass', algorithm: 'aes128', aeadAlgorithm: 'eax' });
- expect(encryptedSessionKeys).to.include('-----BEGIN PGP MESSAGE-----');
+ const armoredEncryptedSessionKeys: string = await encryptSessionKey({ ...sessionKeys[0], passwords: 'pass', algorithm: 'aes128', aeadAlgorithm: 'eax' });
+ expect(armoredEncryptedSessionKeys).to.include('-----BEGIN PGP MESSAGE-----');
+ const encryptedSessionKeys: Message<any> = await encryptSessionKey({ ...sessionKeys[0], passwords: 'pass', algorithm: 'aes128', aeadAlgorithm: 'eax', format: 'object' });
+ expect(encryptedSessionKeys).to.be.instanceOf(Message);
const newSessionKey = await generateSessionKey({ encryptionKeys: privateKey.toPublic() });
expect(newSessionKey.data).to.exist;
expect(newSessionKey.algorithm).to.exist;
@@ -180,19 +185,34 @@ import {
// const signed = await sign({ privateKeys, message, detached: true, format: 'binary' });
// console.log(signed); // Uint8Array
- // // Streaming - encrypt text message on Node.js (armored)
- // const data = fs.createReadStream(filename, { encoding: 'utf8' });
- // const message = await createMessage({ text: data });
- // const encrypted = await encrypt({ publicKeys, message });
- // encrypted.on('data', chunk => {
- // console.log(chunk); // String
- // });
-
- // // Streaming - encrypt binary message on Node.js (unarmored)
- // const data = fs.createReadStream(filename);
- // const message = await createMessage({ binary: data });
- // const encrypted = await encrypt({ publicKeys, message, format: 'binary' });
- // encrypted.pipe(targetStream);
+ // @ts-expect-error for passing text stream as binary data
+ await createMessage({ binary: new WebReadableStream<string>() });
+ // @ts-expect-error for passing binary stream as text data
+ await createMessage({ text: new WebReadableStream<Uint8Array>() });
+
+ // Streaming - encrypt text message (armored output)
+ try {
+ const nodeTextStream = createReadStream('non-existent-file', { encoding: 'utf8' });
+ const messageFromNodeTextStream = await createMessage({ text: nodeTextStream });
+ (await encrypt({ message: messageFromNodeTextStream, passwords: 'password', format: 'armored' })) as NodeStream<string>;
+ } catch (err) {}
+ const webTextStream = new WebReadableStream<string>();
+ const messageFromWebTextStream = await createMessage({ text: webTextStream });
+ (await encrypt({ message: messageFromWebTextStream, passwords: 'password', format: 'armored' })) as WebStream<string>;
+ messageFromWebTextStream.getText() as WebStream<string>;
+ messageFromWebTextStream.getLiteralData() as WebStream<Uint8Array>;
+
+ // Streaming - encrypt binary message (binary output)
+ try {
+ const nodeBinaryStream = createReadStream('non-existent-file');
+ const messageFromNodeBinaryStream = await createMessage({ binary: nodeBinaryStream });
+ (await encrypt({ message: messageFromNodeBinaryStream, passwords: 'password', format: 'binary' })) as NodeStream<Uint8Array>;
+ } catch (err) {}
+ const webBinaryStream = new WebReadableStream<Uint8Array>();
+ const messageFromWebBinaryStream = await createMessage({ binary: webBinaryStream });
+ (await encrypt({ message: messageFromWebBinaryStream, passwords: 'password', format: 'binary' })) as WebStream<Uint8Array>;
+ messageFromWebBinaryStream.getText() as WebStream<string>;
+ messageFromWebBinaryStream.getLiteralData() as WebStream<Uint8Array>;
console.log('TypeScript definitions are correct');
})().catch(e => {