Skip to content

Commit 25c675a

Browse files
committed
generated temporary implementations for the current RSA interface using
the new WebCrypto and NodeRSA bindings.
1 parent a30d50d commit 25c675a

File tree

15 files changed

+315
-259
lines changed

15 files changed

+315
-259
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
},
2121
"devDependencies": {
2222
"@hyper-hyper-space/node-env": "^0.8.0",
23+
"@peculiar/webcrypto": "^1.1.6",
2324
"@types/jest": "^26.0.19",
2425
"@types/node": "^14.0.13",
2526
"@types/ws": "^7.2.6",
@@ -33,6 +34,7 @@
3334
"@types/node-rsa": "^1.1.0",
3435
"broadcast-channel": "^3.5.3",
3536
"chacha-js": "^2.1.1",
37+
"fast-text-encoding": "^1.0.3",
3638
"get-random-values": "^1.2.0",
3739
"idb": "^5.0.4",
3840
"jsencrypt": "3.0.0-rc.1",
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { RSA } from './RSA';
2+
import { SignatureKeyPair } from 'crypto/sign/SignatureKeyPair';
3+
import { EncodingKeyPair } from './EncodingKeyPair';
4+
5+
6+
7+
class DelegatingRSAImpl implements RSA {
8+
9+
encKeyPair : EncodingKeyPair;
10+
signKeyPair : SignatureKeyPair;
11+
initialized : boolean;
12+
13+
constructor(encKeyPair: EncodingKeyPair, signKeyPair: SignatureKeyPair) {
14+
this.encKeyPair = encKeyPair;
15+
this.signKeyPair = signKeyPair;
16+
this.initialized = false;
17+
}
18+
19+
async generateKey(bits: number): Promise<void> {
20+
21+
await this.signKeyPair.generateKey({b: bits});
22+
await this.encKeyPair.loadKeyPair(this.signKeyPair.getPublicKey(), this.signKeyPair.getPrivateKey());
23+
24+
this.initialized = true;
25+
26+
}
27+
28+
async loadKeyPair(format: string, publicKey: string, privateKey?: string): Promise<void> {
29+
30+
format; // ignore
31+
32+
if (this.initialized) {
33+
throw new Error('RSA key cannot be re-initialized.')
34+
}
35+
36+
await this.signKeyPair.loadKeyPair(publicKey, privateKey);
37+
await this.encKeyPair.loadKeyPair(publicKey, privateKey);
38+
39+
this.initialized = true;
40+
}
41+
42+
getPublicKey(): string {
43+
44+
if (!this.initialized) {
45+
throw new Error('Trying to retrieve public key from uninitialized WebCrypto RSA KeyPair wrapper.')
46+
}
47+
48+
return this.signKeyPair.getPublicKey();
49+
}
50+
51+
getPrivateKey(): string | undefined {
52+
53+
if (!this.initialized) {
54+
throw new Error('Trying to retrieve private key from uninitialized WebCrypto RSA KeyPair wrapper.')
55+
}
56+
57+
58+
return this.signKeyPair.getPrivateKey();
59+
}
60+
61+
async sign(text: string): Promise<string> {
62+
63+
if (!this.initialized) {
64+
throw new Error('Trying to create signature using uninitialized WebCrypto RSA KeyPair wrapper.')
65+
}
66+
67+
return this.signKeyPair?.sign(text);
68+
}
69+
70+
async verify(text: string, signature: string): Promise<boolean> {
71+
72+
if (!this.initialized) {
73+
throw new Error('Trying to verify signature using uninitialized WebCrypto RSA KeyPair wrapper.')
74+
}
75+
76+
return this.signKeyPair.verify(text, signature);
77+
}
78+
79+
async encrypt(plainText: string): Promise<string> {
80+
81+
if (!this.initialized) {
82+
throw new Error('Trying to encrypt using uninitialized WebCrypto RSA KeyPair wrapper.')
83+
}
84+
85+
return this.encKeyPair.encrypt(plainText);
86+
}
87+
88+
async decrypt(cypherText: string): Promise<string> {
89+
90+
if (!this.initialized) {
91+
throw new Error('Trying to decrypt using uninitialized WebCrypto RSA KeyPair wrapper.')
92+
}
93+
94+
return this.encKeyPair.decrypt(cypherText);
95+
}
96+
}
97+
98+
export { DelegatingRSAImpl };

src/crypto/ciphers/NodeRSA.ts

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,14 @@
1-
import { RSA } from './RSA';
2-
3-
4-
class NodeRSA implements RSA {
5-
6-
generateKey(bits: number): Promise<void> {
7-
throw new Error('Method not implemented.');
8-
}
9-
10-
loadKeyPair(format: string, publicKey: string, privateKey?: string): Promise<void> {
11-
throw new Error('Method not implemented.');
12-
}
1+
import { NodeRSASigKP } from 'crypto/sign/NodeRSASigKP';
2+
import { NodeRSAEncKP } from './NodeRSAEncKP';
133

14-
getPublicKey(): string {
15-
throw new Error('Method not implemented.');
16-
}
4+
import { DelegatingRSAImpl } from './DelegatingRSAImpl';
5+
import { RSA } from './RSA';
176

18-
getPrivateKey(): string | undefined {
19-
throw new Error('Method not implemented.');
20-
}
217

22-
sign(text: string): Promise<string> {
23-
throw new Error('Method not implemented.');
24-
}
8+
class NodeRSA extends DelegatingRSAImpl implements RSA {
259

26-
verify(text: string, signature: string): Promise<boolean> {
27-
throw new Error('Method not implemented.');
28-
}
29-
30-
encrypt(plainText: string): Promise<string> {
31-
throw new Error('Method not implemented.');
32-
}
33-
34-
decrypt(cypherText: string): Promise<string> {
35-
throw new Error('Method not implemented.');
10+
constructor() {
11+
super(new NodeRSAEncKP(), new NodeRSASigKP());
3612
}
3713

3814
}

src/crypto/ciphers/NodeRSAEncKP.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import NodeRSA from 'node-rsa';
2-
import { Strings } from 'util/strings';
31
import { EncodingKeyPair } from './EncodingKeyPair';
42

3+
const NodeRSA = require('node-rsa');
4+
55
class NodeRSAEncKP implements EncodingKeyPair {
66

77
publicKeyPEM?: string;
88
privateKeyPEM?: string;
99

10-
keyPair?: NodeRSA;
10+
keyPair?: any;
1111

1212
encoder = new TextEncoder();
1313
decoder = new TextDecoder();
@@ -98,15 +98,16 @@ class NodeRSAEncKP implements EncodingKeyPair {
9898
throw new Error('Attempted to encrypt, but NodeRSA keypair is uninitialized.');
9999
}
100100

101-
return this.keyPair.encrypt(Buffer.from(this.encoder.encode(plainText)), 'base64', 'utf8');
101+
return this.keyPair.encrypt(Buffer.from(plainText), 'base64', 'utf8');
102102
}
103103

104104
async decrypt(cypherText: string): Promise<string> {
105105
if (this.keyPair === undefined) {
106106
throw new Error('Attempted to decrypt, but NodeRSA keypair is uninitialized.');
107107
}
108108

109-
return this.decoder.decode(this.keyPair.decrypt(cypherText));
109+
return this.keyPair.decrypt(cypherText, 'utf8');
110+
110111
}
111112

112113
}

src/crypto/ciphers/RSA.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
import { NodeRSA } from "./NodeRSA";
2+
import { WebCryptoRSA } from "./WebCryptoRSA";
13

24
interface RSA {
35

6+
7+
48
generateKey(bits: number) : Promise<void>;
59
loadKeyPair(format: string, publicKey: string, privateKey?: string) : Promise<void>;
610

@@ -15,4 +19,8 @@ interface RSA {
1519

1620
}
1721

18-
export { RSA };
22+
class RSADefaults {
23+
static impl: new () => RSA = globalThis?.crypto?.subtle !== undefined? WebCryptoRSA : NodeRSA;
24+
}
25+
26+
export { RSA, RSADefaults };

src/crypto/ciphers/WebCryptoRSA.ts

Lines changed: 7 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,16 @@
1-
import { SignatureKeyPair } from 'crypto/sign/SignatureKeyPair';
21
import { WebCryptoRSASigKP } from 'crypto/sign/WebCryptoRSASigKP';
3-
import { EncodingKeyPair } from './EncodingKeyPair';
4-
import { RSA } from './RSA';
52
import { WebCryptoRSAEncKP } from './WebCryptoRSAEncKP';
63

4+
import { DelegatingRSAImpl } from './DelegatingRSAImpl';
5+
import { RSA } from './RSA';
76

8-
class WebCryptoRSA implements RSA {
9-
10-
encKeyPair? : EncodingKeyPair;
11-
signKeyPair? : SignatureKeyPair;
12-
13-
async generateKey(bits: number): Promise<void> {
14-
15-
this.signKeyPair = new WebCryptoRSASigKP();
16-
await this.signKeyPair.generateKey({b: bits});
17-
18-
this.encKeyPair = new WebCryptoRSAEncKP();
19-
await this.encKeyPair.loadKeyPair(this.signKeyPair.getPublicKey(), this.signKeyPair.getPrivateKey());
20-
21-
}
22-
23-
async loadKeyPair(format: string, publicKey: string, privateKey?: string): Promise<void> {
24-
25-
format; // ignore
26-
27-
this.signKeyPair = new WebCryptoRSASigKP();
28-
await this.signKeyPair.loadKeyPair(publicKey, privateKey);
29-
30-
this.encKeyPair = new WebCryptoRSAEncKP();
31-
await this.encKeyPair.loadKeyPair(publicKey, privateKey);
32-
33-
}
34-
35-
getPublicKey(): string {
36-
37-
if (this.signKeyPair === undefined) {
38-
throw new Error('Trying to retrieve public key from uninitialized WebCrypto RSA KeyPair wrapper.')
39-
}
40-
41-
return this.signKeyPair.getPublicKey();
42-
}
43-
44-
getPrivateKey(): string | undefined {
45-
46-
if (this.signKeyPair === undefined) {
47-
throw new Error('Trying to retrieve private key from uninitialized WebCrypto RSA KeyPair wrapper.')
48-
}
49-
50-
51-
return this.signKeyPair.getPrivateKey();
52-
}
53-
54-
async sign(text: string): Promise<string> {
55-
56-
if (this.signKeyPair === undefined) {
57-
throw new Error('Trying to create signature using uninitialized WebCrypto RSA KeyPair wrapper.')
58-
}
59-
60-
return this.signKeyPair?.sign(text);
61-
}
62-
63-
async verify(text: string, signature: string): Promise<boolean> {
64-
65-
if (this.signKeyPair === undefined) {
66-
throw new Error('Trying to verify signature using uninitialized WebCrypto RSA KeyPair wrapper.')
67-
}
68-
69-
return this.signKeyPair.verify(text, signature);
70-
}
71-
72-
async encrypt(plainText: string): Promise<string> {
737

74-
if (this.encKeyPair === undefined) {
75-
throw new Error('Trying to encrypt using uninitialized WebCrypto RSA KeyPair wrapper.')
76-
}
8+
class WebCryptoRSA extends DelegatingRSAImpl implements RSA {
779

78-
return this.encKeyPair.encrypt(plainText);
10+
constructor() {
11+
super(new WebCryptoRSAEncKP(), new WebCryptoRSASigKP);
7912
}
8013

81-
async decrypt(cypherText: string): Promise<string> {
82-
83-
if (this.encKeyPair === undefined) {
84-
throw new Error('Trying to decrypt using uninitialized WebCrypto RSA KeyPair wrapper.')
85-
}
86-
87-
return this.encKeyPair.decrypt(cypherText);
88-
}
14+
}
8915

90-
}
16+
export { WebCryptoRSA };

0 commit comments

Comments
 (0)