Skip to content

Commit d1d7747

Browse files
authored
Merge pull request #87 from PeculiarVentures/rsaes-pkcs1
Implement RSAES-PKCS1-v1_5 provider and improve linting
2 parents bdb50bd + a89da03 commit d1d7747

24 files changed

+1105
-759
lines changed

.eslintrc

Lines changed: 0 additions & 32 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ jobs:
4646
- name: Install dependencies
4747
run: yarn
4848

49+
- name: Run lint
50+
run: yarn lint
51+
4952
- name: Run test with coverage
5053
run: npm run coverage
5154
env:

README.md

Lines changed: 100 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
We wanted to be able to write Javascript that used crypto on both the client and the server but we did not want to rely on Javascript implementations of crypto. The only native cryptography availible in browser is [Web Crypto](caniuse.com/#search=cryptography), this resulted in us creating a [native polyfil for WebCrypto based on Openssl](https://github.com/PeculiarVentures/node-webcrypto-ossl).
1111

12-
Our project also required us to utilize Hardware Security Modules and smart cards on the server side so we made a [library called Graphene that made it possible to use PKCS#11 devices from within Nodejs](https://github.com/PeculiarVentures/graphene).
12+
Our project also required us to utilize Hardware Security Modules and smart cards on the server side so we made a [library called Graphene that made it possible to use PKCS#11 devices from within Nodejs](https://github.com/PeculiarVentures/graphene).
1313

1414
We then thought that in most cases others did not care about interacting with the token directly and would prefer a higher level API they were already familiar with. We hope that library is `node-webcrypto-p11`, if you have code based on WebCrypto (for example the excelent [js-jose](https://github.com/square/js-jose)) with only a change in a constructor you can work with PKCS#11 devices.
1515

@@ -18,23 +18,25 @@ For example to generate a key you this is all it takes:
1818
```js
1919
const { Crypto } = require("node-webcrypto-p11");
2020
const config = {
21-
library: "/usr/local/lib/softhsm/libsofthsm2.so",
22-
name: "SoftHSM v2.0",
23-
slot: 0,
24-
readWrite: true,
25-
pin: "12345"
21+
library: "/usr/local/lib/softhsm/libsofthsm2.so",
22+
name: "SoftHSM v2.0",
23+
slot: 0,
24+
readWrite: true,
25+
pin: "12345",
2626
};
2727

2828
const crypto = new Crypto(config);
2929

30-
const keys = await crypto.subtle.generateKey({
31-
name:"RSASSA-PKCS1-v1_5",
32-
modulusLength: 1024,
33-
publicExponent: new Uint8Array([1, 0, 1]),
34-
hash: {
35-
name: "SHA-1"
36-
}},
37-
true,
30+
const keys = await crypto.subtle.generateKey(
31+
{
32+
name: "RSASSA-PKCS1-v1_5",
33+
modulusLength: 1024,
34+
publicExponent: new Uint8Array([1, 0, 1]),
35+
hash: {
36+
name: "SHA-1",
37+
},
38+
},
39+
true,
3840
["sign", "verify"]
3941
);
4042
```
@@ -47,21 +49,22 @@ const keys = await crypto.subtle.generateKey({
4749

4850
## Supported algorithms
4951

50-
| Algorithm name | generateKey | digest | export/import | sign/verify | encrypt/decrypt | wrapKey/unwrapKey | derive |
51-
|-------------------|-------------|---------|---------------|-------------|-----------------|-------------------|---------|
52-
| SHA-1 | | X | | | | | |
53-
| SHA-256 | | X | | | | | |
54-
| SHA-384 | | X | | | | | |
55-
| SHA-512 | | X | | | | | |
56-
| RSASSA-PKCS1-v1_5 | X | | X | X | | | |
57-
| RSA-PSS | X | | X | X | | | |
58-
| RSA-OAEP | X | | X | | X | X | |
59-
| AES-CBC | X | | X | | X | X | |
60-
| AES-ECB <sub>2</sub>| X | | X | | X | X | |
61-
| AES-GCM | X | | X | | X | X | |
62-
| ECDSA <sub>1</sub>| X | | X | X | | | |
63-
| ECDH <sub>2</sub> | X | | X | | | | X |
64-
| HMAC | X | | X | X | | | |
52+
| Algorithm name | generateKey | digest | export/import | sign/verify | encrypt/decrypt | wrapKey/unwrapKey | derive |
53+
| ----------------------------- | ----------- | ------ | ------------- | ----------- | --------------- | ----------------- | ------ |
54+
| SHA-1 | | X | | | | | |
55+
| SHA-256 | | X | | | | | |
56+
| SHA-384 | | X | | | | | |
57+
| SHA-512 | | X | | | | | |
58+
| RSASSA-PKCS1-v1_5 | X | | X | X | | | |
59+
| RSAES-PKCS1-v1_5 <sub>2</sub> | X | | X | | X | X | |
60+
| RSA-PSS | X | | X | X | | | |
61+
| RSA-OAEP | X | | X | | X | X | |
62+
| AES-CBC | X | | X | | X | X | |
63+
| AES-ECB <sub>2</sub> | X | | X | | X | X | |
64+
| AES-GCM | X | | X | | X | X | |
65+
| ECDSA <sub>1</sub> | X | | X | X | | | |
66+
| ECDH <sub>2</sub> | X | | X | | | | X |
67+
| HMAC | X | | X | X | | | |
6568

6669
<sup>1</sup> Mechanism supports extended list of named curves `P-256`, `P-384`, `P-521`, and `K-256`
6770

@@ -87,10 +90,9 @@ cd node-webcrypto-p11
8790
- For OSX see the [instructions here](https://github.com/opendnssec/SoftHSMv2/blob/develop/OSX-NOTES.md)
8891
- For linux [instructions here](https://github.com/opendnssec/SoftHSMv2/blob/develop/README.md)
8992

90-
91-
### Install
93+
### Install
9294

93-
```
95+
```
9496
npm install
9597
```
9698

@@ -116,30 +118,38 @@ module.exports = {
116118
```
117119

118120
## Threats
121+
119122
The threat model is defined in terms of what each possible attacker can achieve. The list is intended to be exhaustive.
120123

121124
### Assumptions
125+
122126
TODO: ADD ASSUMPTIONS
123127

124128
### Threats From A node-webcrypto-p11 Defect
129+
125130
`node-webcrypto-p11` handles ciphertext, cleartext, and sessions. A defect in this library could result in these values being exposed to an attacker. Examples of such defects include:
131+
126132
- Buffer, Integer or other overflow related defects,
127133
- Parsing errors,
128134
- Logic errors,
129135
- Weak user seperation or permissions.
130136

131137
### Threats From A PKCS#11 defect
138+
132139
PKCS#11 implementations are often old, poorly maintained and incomplete. This can obviously lead to defects. Defects in the PKCS#11 implementation can result in:
140+
133141
- Weakly implemented or applied cryptographic primitives,
134142
- Leaked sessions or secrets that expose use of the key,
135143
- Leaked cryptographic key material.
136144

137145
### Threats From Weak Cryptography
146+
138147
Secure use of cryptography requires the implementor to understand the security properties of a given algorithm as well as how to use it in a secure construction.
139148

140149
Additionally this library exposes some algorithms that may have known weakneses or are simply too old to be used safely.
141150

142151
### Threats From Improper Use Of Cryptography
152+
143153
It is easy to apply cryptography but hard to apply it correctly. Algorithms each have their own security properties and appropriate constructions. The consumer of this library is responsible for understanding how to use the exposed algorithms securely.
144154

145155
### Generates `ECDSA` key pair with named curve `P-256` and signs/verifies text message.
@@ -148,29 +158,47 @@ It is easy to apply cryptography but hard to apply it correctly. Algorithms each
148158
const { Crypto } = require("node-webcrypto-p11");
149159

150160
const config = {
151-
library: "/usr/local/lib/softhsm/libsofthsm2.so",
152-
name: "SoftHSM v2.0",
153-
slot: 0,
154-
readWrite: true,
155-
pin: "12345"
156-
}
161+
library: "/usr/local/lib/softhsm/libsofthsm2.so",
162+
name: "SoftHSM v2.0",
163+
slot: 0,
164+
readWrite: true,
165+
pin: "12345",
166+
};
157167

158168
const crypto = new Crypto(config);
159169

160-
const keys = await crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, false, ["sign", "verify"]);
161-
const signature = await crypto.subtle.sign({name: "ECDSA", hash: "SHA-256"}, keys.privateKey, Buffer.from("Hello world!"));
170+
const keys = await crypto.subtle.generateKey(
171+
{ name: "ECDSA", namedCurve: "P-256" },
172+
false,
173+
["sign", "verify"]
174+
);
175+
const signature = await crypto.subtle.sign(
176+
{ name: "ECDSA", hash: "SHA-256" },
177+
keys.privateKey,
178+
Buffer.from("Hello world!")
179+
);
162180
console.log(`Signature: ${signature}`);
163-
const ok = await crypto.subtle.verify({name: "ECDSA", hash: "SHA-256"}, keys.publicKey, signature, Buffer.from("Hello world!"));
181+
const ok = await crypto.subtle.verify(
182+
{ name: "ECDSA", hash: "SHA-256" },
183+
keys.publicKey,
184+
signature,
185+
Buffer.from("Hello world!")
186+
);
164187
console.log(`Verification: ${ok}`);
165188
```
166189

167190
## Key Storage
191+
168192
The [CryptoKeyStorage](https://github.com/PeculiarVentures/webcrypto-docs/blob/master/KEY_STORAGE.md#cryptokeystorage) interface enables you to persist and retrieve keys across sessions.
169193

170194
### Generate a cryptographic key and store it
171195

172196
```js
173-
const keys = await crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, false, ["sign", "verify"]);
197+
const keys = await crypto.subtle.generateKey(
198+
{ name: "ECDSA", namedCurve: "P-256" },
199+
false,
200+
["sign", "verify"]
201+
);
174202
// set private key to storage
175203
const privateKeyID = await crypto.keyStorage.setItem(keys.privateKey);
176204
// set public key to storage
@@ -181,36 +209,52 @@ console.log(indexes); // ['private-3239...', 'public-3239...']
181209
// get key by id
182210
const privateKey = await crypto.keyStorage.getItem("private-3239...");
183211
// signing data
184-
const signature = await crypto.subtle.sign({name: "ECDSA", hash: "SHA-256"}, key, Buffer.from("Message here"));
212+
const signature = await crypto.subtle.sign(
213+
{ name: "ECDSA", hash: "SHA-256" },
214+
key,
215+
Buffer.from("Message here")
216+
);
185217
console.log("Signature:", Buffer.from(signature).toString("hex"));
186218
```
187219

188220
## Certificate Storage
221+
189222
The [CryptoCertificateStorage](https://github.com/PeculiarVentures/webcrypto-docs/blob/master/CERT_STORAGE.md#cryptocertstorage) interface enables you to persist and retrieve certificates across sessions.
190223

191224
### Add certificate to storage and use it for verification of signed data
192225

193226
```javascript
194-
const X509_RAW = Buffer.from("308203A830820290A003020...", "hex")
227+
const X509_RAW = Buffer.from("308203A830820290A003020...", "hex");
195228

196-
const x509 = await crypto.certStorage.importCert("raw", X509_RAW, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, ["verify"]);
229+
const x509 = await crypto.certStorage.importCert(
230+
"raw",
231+
X509_RAW,
232+
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
233+
["verify"]
234+
);
197235
console.log(x509.subjectName); // C=name, O=...
198-
const index = await crypto.certStorage.setItem(x509)
236+
const index = await crypto.certStorage.setItem(x509);
199237
console.log(index); // x509-2943...
200-
const ok = await crypto.subtle.verify({name: "RSASSA-PKCS1-v1_5"}, x509.publicKey, SIGNATURE, MESSAGE);
238+
const ok = await crypto.subtle.verify(
239+
{ name: "RSASSA-PKCS1-v1_5" },
240+
x509.publicKey,
241+
SIGNATURE,
242+
MESSAGE
243+
);
201244
console.log("Signature:", ok);
202245
```
203246

204247
## Bug Reporting
248+
205249
Please report bugs either as pull requests or as issues in the issue tracker. Backwater has a full disclosure vulnerability policy. Please do NOT attempt to report any security vulnerability in this code privately to anybody.
206250

251+
## Related
207252

208-
## Related
209-
- [webcrypto](https://github.com/PeculiarVentures/webcrypto)
210-
- [node-webcrypto-ossl](https://github.com/PeculiarVentures/node-webcrypto-ossl)
211-
- [webcrypto-liner](https://github.com/PeculiarVentures/webcrypto-liner)
212-
- [WebCrypto Examples](https://github.com/PeculiarVentures/webcrypto-docs#webcrypto)
213-
- [Graphene](https://github.com/PeculiarVentures/graphene)
214-
- [pkcs11js](https://github.com/PeculiarVentures/pkcs11js)
215-
- [OpenCryptoKi](https://sourceforge.net/projects/opencryptoki/)
216-
- [SoftHSM](https://github.com/opendnssec/SoftHSMv2)
253+
- [webcrypto](https://github.com/PeculiarVentures/webcrypto)
254+
- [node-webcrypto-ossl](https://github.com/PeculiarVentures/node-webcrypto-ossl)
255+
- [webcrypto-liner](https://github.com/PeculiarVentures/webcrypto-liner)
256+
- [WebCrypto Examples](https://github.com/PeculiarVentures/webcrypto-docs#webcrypto)
257+
- [Graphene](https://github.com/PeculiarVentures/graphene)
258+
- [pkcs11js](https://github.com/PeculiarVentures/pkcs11js)
259+
- [OpenCryptoKi](https://sourceforge.net/projects/opencryptoki/)
260+
- [SoftHSM](https://github.com/opendnssec/SoftHSMv2)

eslint.config.mjs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// @ts-check
2+
import eslint from "@eslint/js";
3+
import tseslint from "typescript-eslint";
4+
5+
export default tseslint.config(
6+
eslint.configs.recommended,
7+
tseslint.configs.recommended,
8+
{
9+
ignores: ['node_modules/**/*.js', 'build/**/*.js'],
10+
},
11+
{
12+
rules: {
13+
'@typescript-eslint/no-unused-vars': [
14+
'error',
15+
{
16+
varsIgnorePattern: '^_',
17+
argsIgnorePattern: '^_',
18+
},
19+
]
20+
}
21+
}
22+
);

package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"test:softhsm": "mocha",
1919
"test:nss": "PV_CRYPTO=nss mocha",
2020
"build": "rollup -c",
21-
"lint": "eslint . --ext .ts",
22-
"lint:fix": "eslint --fix . --ext .ts",
21+
"lint": "eslint .",
22+
"lint:fix": "eslint --fix .",
2323
"prepub": "npm run lint && npm run build",
2424
"pub": "npm version patch && git push --follow-tags",
2525
"coverage": "nyc npm test",
@@ -30,14 +30,14 @@
3030
"url": "https://github.com/PeculiarVentures/node-webcrypto-p11.git"
3131
},
3232
"dependencies": {
33-
"@peculiar/asn1-schema": "^2.3.13",
34-
"@peculiar/asn1-x509": "^2.3.13",
33+
"@peculiar/asn1-schema": "^2.3.15",
34+
"@peculiar/asn1-x509": "^2.3.15",
3535
"@peculiar/json-schema": "^1.1.12",
3636
"@peculiar/x509": "^1.12.3",
3737
"graphene-pk11": "^2.3.6",
3838
"pkcs11js": "^2.1.6",
39-
"pvtsutils": "^1.3.5",
40-
"tslib": "^2.7.0",
39+
"pvtsutils": "^1.3.6",
40+
"tslib": "^2.8.1",
4141
"webcrypto-core": "^1.8.1"
4242
},
4343
"keywords": [
@@ -60,19 +60,19 @@
6060
},
6161
"homepage": "https://github.com/PeculiarVentures/node-webcrypto-p11#readme",
6262
"devDependencies": {
63+
"@eslint/js": "^9.18.0",
6364
"@peculiar/webcrypto-test": "^1.0.7",
64-
"@types/mocha": "^10.0.9",
65-
"@types/node": "^22.7.5",
66-
"@typescript-eslint/eslint-plugin": "^8.8.1",
67-
"@typescript-eslint/parser": "^8.8.1",
68-
"eslint": "^8.57.0",
69-
"mocha": "^10.7.3",
65+
"@types/mocha": "^10.0.10",
66+
"@types/node": "^22.10.7",
67+
"eslint": "^9.18.0",
68+
"mocha": "^11.1.0",
7069
"nyc": "^17.1.0",
71-
"rollup": "^4.24.0",
70+
"rollup": "^4.31.0",
7271
"rollup-plugin-dts": "^6.1.1",
7372
"rollup-plugin-typescript2": "^0.36.0",
7473
"ts-node": "^10.9.2",
75-
"typescript": "^5.6.3"
74+
"typescript": "^5.7.3",
75+
"typescript-eslint": "^8.21.0"
7676
},
7777
"funding": {
7878
"type": "github",

0 commit comments

Comments
 (0)