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

definitions.ts « typescript « test - github.com/openpgpjs/openpgpjs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3bc2f54751ce3046318cce08b64862e6cdbb1b7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/**
 * npm run-script test-type-definitions
 *
 * If types are off, either this will fail to build with TypeScript, or it will fail to run.
 *  - 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 {
  generateKey, readKey, readKeys, readPrivateKey, PrivateKey, Key, PublicKey, revokeKey,
  readMessage, createMessage, Message, createCleartextMessage,
  encrypt, decrypt, sign, verify, config, enums,
  generateSessionKey, encryptSessionKey, decryptSessionKeys,
  LiteralDataPacket, PacketList, CompressedDataPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket, CleartextMessage,
  WebStream, NodeStream,
} from '../..';

(async () => {

  // Generate keys
  const keyOptions = { userIDs: [{ email: 'user@corp.co' }], config: { v5Keys: true } };
  const { privateKey: privateKeyArmored, publicKey: publicKeyArmored } = await generateKey(keyOptions);
  const { privateKey: privateKeyBinary } = await generateKey({ ...keyOptions, format: 'binary' });
  const { privateKey, publicKey, revocationCertificate } = await generateKey({ ...keyOptions, format: 'object' });
  expect(privateKey).to.be.instanceOf(PrivateKey);
  expect(publicKey).to.be.instanceOf(PublicKey);
  expect(typeof revocationCertificate).to.equal('string');
  const privateKeys = [privateKey];
  const publicKeys = [privateKey.toPublic()];

  // Parse keys
  expect(await readKeys({ armoredKeys: publicKeyArmored })).to.have.lengthOf(1);
  const parsedKey: Key = await readKey({ armoredKey: publicKeyArmored });
  expect(parsedKey.armor(config)).to.equal(publicKeyArmored);
  expect(parsedKey.isPrivate()).to.be.false;
  const parsedPrivateKey: PrivateKey = await readPrivateKey({ armoredKey: privateKeyArmored });
  expect(parsedPrivateKey.isPrivate()).to.be.true;
  const parsedBinaryPrivateKey: PrivateKey = await readPrivateKey({ binaryKey: privateKeyBinary });
  expect(parsedBinaryPrivateKey.isPrivate()).to.be.true;
  // a generic Key can be directly used as PublicKey, since both classes have the same properties
  // eslint-disable-next-line no-unused-vars
  const unusedPublicKey: PublicKey = parsedKey;

  // Check PrivateKey type inference
  if (parsedKey.isPrivate()) {
    expect(parsedKey.isDecrypted()).to.be.true;
  } else {
    // @ts-expect-error isDecrypted is not defined for public keys
    try { parsedKey.isDecrypted(); } catch (e) {}
  }
  (await privateKey.update(privateKey)).isDecrypted();
  (await privateKey.toPublic().update(privateKey)).isDecrypted();
  // @ts-expect-error isDecrypted is not defined for public keys
  try { (await privateKey.toPublic().update(privateKey.toPublic())).isDecrypted(); } catch (e) {}

  // Revoke keys
  await revokeKey({ key: privateKey });
  // @ts-expect-error for missing revocation certificate
  try { await revokeKey({ key: publicKey }); } catch (e) {}
  const { privateKey: revokedPrivateKey, publicKey: revokedPublicKey } = await revokeKey({ key: privateKey, revocationCertificate, format: 'object' });
  expect(revokedPrivateKey).to.be.instanceOf(PrivateKey);
  expect(revokedPublicKey).to.be.instanceOf(PublicKey);
  const revokedKeyPair = await revokeKey({ key: publicKey, revocationCertificate, format: 'object' });
  // @ts-expect-error for null private key
  try { revokedKeyPair.privateKey.armor(); } catch (e) {}
  expect(revokedKeyPair.privateKey).to.be.null;
  expect(revokedKeyPair.publicKey).to.be.instanceOf(PublicKey);

  // Encrypt text message (armored)
  const text = 'hello';
  const textMessage = await createMessage({ text: 'hello', format: 'text' });
  const encryptedArmor: string = await encrypt({ encryptionKeys: publicKeys, message: textMessage });
  expect(encryptedArmor).to.include('-----BEGIN PGP MESSAGE-----');

  // Encrypt binary message (unarmored)
  const binary = new Uint8Array([1, 2]);
  const binaryMessage = await createMessage({ binary });
  const encryptedBinary: Uint8Array = await encrypt({ encryptionKeys: publicKeys, message: binaryMessage, format: 'binary' });
  expect(encryptedBinary).to.be.instanceOf(Uint8Array);

  // Decrypt text message (armored)
  const encryptedTextMessage = await readMessage({ armoredMessage: encryptedArmor });
  const decryptedText = await decrypt({ decryptionKeys: privateKeys, message: encryptedTextMessage });
  const decryptedTextData: string = decryptedText.data;
  expect(decryptedTextData).to.equal(text);

  // Decrypt binary message (unarmored)
  const encryptedBinaryMessage = await readMessage({ binaryMessage: encryptedBinary });
  const decryptedBinary = await decrypt({ decryptionKeys: privateKeys, message: encryptedBinaryMessage, format: 'binary' });
  const decryptedBinaryData: Uint8Array = decryptedBinary.data;
  expect(decryptedBinaryData).to.deep.equal(binary);

  // Encrypt message (inspect packets)
  const encryptedBinaryObject: Message<Uint8Array> = await encrypt({ encryptionKeys: publicKeys, message: binaryMessage, format: 'object' });
  expect(encryptedBinaryObject).to.be.instanceOf(Message);
  const encryptedTextObject: Message<string> = await encrypt({ encryptionKeys: publicKeys, message: textMessage, format: 'object' });
  expect(encryptedTextObject).to.be.instanceOf(Message);

  // Session key functions
  // Get session keys from encrypted message
  const sessionKeys = await decryptSessionKeys({ message: await readMessage({ binaryMessage: encryptedBinary }), decryptionKeys: privateKeys });
  expect(sessionKeys).to.have.length(1);
  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;

  // Sign cleartext message (armored)
  const cleartextMessage = await createCleartextMessage({ text: 'hello' });
  const clearSignedArmor = await sign({ signingKeys: privateKeys, message: cleartextMessage });
  expect(clearSignedArmor).to.include('-----BEGIN PGP SIGNED MESSAGE-----');
  const clearSignedObject: CleartextMessage = await sign({ signingKeys: privateKeys, message: cleartextMessage, format: 'object' });
  expect(clearSignedObject).to.be.instanceOf(CleartextMessage);
  // @ts-expect-error PublicKey not assignable to PrivateKey
  try { await sign({ signingKeys: publicKeys, message: cleartextMessage }); } catch (e) {}
  // @ts-expect-error Key not assignable to PrivateKey
  try { await sign({ signingKeys: parsedKey, message: cleartextMessage }); } catch (e) {}

  // Sign text message (armored)
  const textSignedArmor: string = await sign({ signingKeys: privateKeys, message: textMessage });
  expect(textSignedArmor).to.include('-----BEGIN PGP MESSAGE-----');
  // Sign text message (unarmored)
  const textSignedBinary: Uint8Array = await sign({ signingKeys: privateKeys, message: binaryMessage, format: 'binary' });
  expect(textSignedBinary).to.be.instanceOf(Uint8Array);
  // Sign text and binary messages (inspect packages)
  const binarySignedObject: Message<Uint8Array> = await sign({ signingKeys: privateKeys, message: binaryMessage, format: 'object' });
  expect(binarySignedObject).to.be.instanceOf(Message);
  const textSignedObject: Message<string> = await sign({ signingKeys: privateKeys, message: textMessage, format: 'object' });
  expect(textSignedObject).to.be.instanceOf(Message);

  // Verify signed text message (armored)
  const signedMessage = await readMessage({ armoredMessage: textSignedArmor });
  const verifiedText = await verify({ verificationKeys: publicKeys, message: signedMessage });
  const verifiedTextData: string = verifiedText.data;
  expect(verifiedTextData).to.equal(text);

  // Verify signed binary message (unarmored)
  const message = await readMessage({ binaryMessage: textSignedBinary });
  const verifiedBinary = await verify({ verificationKeys: publicKeys, message, format: 'binary' });
  const verifiedBinaryData: Uint8Array = verifiedBinary.data;
  expect(verifiedBinaryData).to.deep.equal(binary);
  await verify({ verificationKeys: privateKeys, message, format: 'binary' });

  // Generic packetlist
  const packets = new PacketList();
  expect(packets.push()).to.equal(0);
  expect(packets.push(new LiteralDataPacket())).to.equal(1);
  packets.map(packet => packet.write);
  // @ts-expect-error for unsafe downcasting
  packets.map((packet: LiteralDataPacket) => packet.getText());
  // @ts-expect-error for non-packet element
  try { new PacketList().push(1); } catch (e) {}

  // Packetlist of specific type
  const literalPackets = new PacketList<LiteralDataPacket>();
  literalPackets.push(new LiteralDataPacket());
  literalPackets[0].write();
  literalPackets.map((packet: LiteralDataPacket) => packet);
  packets.push(...literalPackets);
  // @ts-expect-error for incompatible packetlist type
  literalPackets.push(...packets);
  // @ts-expect-error for incompatible packet type
  new PacketList<LiteralDataPacket>().push(new CompressedDataPacket());
  // @ts-expect-error for incompatible packet type
  new PacketList<PublicKeyPacket>().push(new PublicSubkeyPacket());
  // @ts-expect-error for incompatible packet type
  new PacketList<SecretKeyPacket>().push(new SecretSubkeyPacket());

  expect(LiteralDataPacket.tag).to.equal(enums.packet.literalData);

  // // Detached - sign text message (armored)
  // import { Message, sign } from 'openpgp';
  // const message = await createMessage({ text: util.removeTrailingSpaces(text) });
  // const signed = await sign({ privateKeys, message, detached: true });
  // console.log(signed); // String

  // // Detached - sign binary message (unarmored)
  // const message = await createMessage({ text });
  // const signed = await sign({ privateKeys, message, detached: true, format: 'binary' });
  // console.log(signed); // Uint8Array

  // @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 => {
  console.error('TypeScript definitions tests failed by throwing the following error');
  console.error(e);
  process.exit(1);
});