@libp2p/keychain 0.6.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/util.ts CHANGED
@@ -1,69 +1,3 @@
1
- import 'node-forge/lib/x509.js'
2
- // @ts-expect-error types are missing
3
- import forge from 'node-forge/lib/forge.js'
4
-
5
- const pki = forge.pki
6
-
7
- /**
8
- * Gets a self-signed X.509 certificate for the key.
9
- *
10
- * The output Uint8Array contains the PKCS #7 message in DER.
11
- *
12
- * TODO: move to libp2p-crypto package
13
- */
14
- export const certificateForKey = (key: any, privateKey: forge.pki.rsa.PrivateKey) => {
15
- const publicKey = pki.rsa.setPublicKey(privateKey.n, privateKey.e)
16
- const cert = pki.createCertificate()
17
- cert.publicKey = publicKey
18
- cert.serialNumber = '01'
19
- cert.validity.notBefore = new Date()
20
- cert.validity.notAfter = new Date()
21
- cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10) // eslint-disable-line @typescript-eslint/restrict-plus-operands
22
- const attrs = [{
23
- name: 'organizationName',
24
- value: 'ipfs'
25
- }, {
26
- shortName: 'OU',
27
- value: 'keystore'
28
- }, {
29
- name: 'commonName',
30
- value: key.id
31
- }]
32
- cert.setSubject(attrs)
33
- cert.setIssuer(attrs)
34
- cert.setExtensions([{
35
- name: 'basicConstraints',
36
- cA: true
37
- }, {
38
- name: 'keyUsage',
39
- keyCertSign: true,
40
- digitalSignature: true,
41
- nonRepudiation: true,
42
- keyEncipherment: true,
43
- dataEncipherment: true
44
- }, {
45
- name: 'extKeyUsage',
46
- serverAuth: true,
47
- clientAuth: true,
48
- codeSigning: true,
49
- emailProtection: true,
50
- timeStamping: true
51
- }, {
52
- name: 'nsCertType',
53
- client: true,
54
- server: true,
55
- email: true,
56
- objsign: true,
57
- sslCA: true,
58
- emailCA: true,
59
- objCA: true
60
- }])
61
- // self-sign certificate
62
- cert.sign(privateKey)
63
-
64
- return cert
65
- }
66
-
67
1
  /**
68
2
  * Finds the first item in a collection that is matched in the
69
3
  * `asyncCompare` function.
@@ -74,7 +8,7 @@ export const certificateForKey = (key: any, privateKey: forge.pki.rsa.PrivateKey
74
8
  * @param {Array} array
75
9
  * @param {function(*)} asyncCompare - An async function that returns a boolean
76
10
  */
77
- export async function findAsync <T> (array: T[], asyncCompare: (val: T) => Promise<any>) {
11
+ export async function findAsync <T> (array: T[], asyncCompare: (val: T) => Promise<any>): Promise<T | undefined> {
78
12
  const promises = array.map(asyncCompare)
79
13
  const results = await Promise.all(promises)
80
14
  const index = results.findIndex(result => result)
package/dist/src/cms.d.ts DELETED
@@ -1,33 +0,0 @@
1
- import 'node-forge/lib/pkcs7.js';
2
- import 'node-forge/lib/pbe.js';
3
- import type { KeyChain } from './index.js';
4
- /**
5
- * Cryptographic Message Syntax (aka PKCS #7)
6
- *
7
- * CMS describes an encapsulation syntax for data protection. It
8
- * is used to digitally sign, digest, authenticate, or encrypt
9
- * arbitrary message content.
10
- *
11
- * See RFC 5652 for all the details.
12
- */
13
- export declare class CMS {
14
- private readonly keychain;
15
- /**
16
- * Creates a new instance with a keychain
17
- */
18
- constructor(keychain: KeyChain, dek: string);
19
- /**
20
- * Creates some protected data.
21
- *
22
- * The output Uint8Array contains the PKCS #7 message in DER.
23
- */
24
- encrypt(name: string, plain: Uint8Array): Promise<Uint8Array>;
25
- /**
26
- * Reads some protected data.
27
- *
28
- * The keychain must contain one of the keys used to encrypt the data. If none of the keys
29
- * exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
30
- */
31
- decrypt(cmsData: Uint8Array): Promise<Uint8Array>;
32
- }
33
- //# sourceMappingURL=cms.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cms.d.ts","sourceRoot":"","sources":["../../src/cms.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,CAAA;AAChC,OAAO,uBAAuB,CAAA;AAS9B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAM1C;;;;;;;;GAQG;AACH,qBAAa,GAAG;IACd,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IAEnC;;OAEG;gBACU,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM;IAS5C;;;;OAIG;IACG,OAAO,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IA4BpE;;;;;OAKG;IACG,OAAO,CAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;CAsEzD"}
package/dist/src/cms.js DELETED
@@ -1,129 +0,0 @@
1
- import 'node-forge/lib/pkcs7.js';
2
- import 'node-forge/lib/pbe.js';
3
- // @ts-expect-error types are missing
4
- import forge from 'node-forge/lib/forge.js';
5
- import { certificateForKey, findAsync } from './util.js';
6
- import errCode from 'err-code';
7
- import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
8
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
9
- import { codes } from './errors.js';
10
- import { logger } from '@libp2p/logger';
11
- const log = logger('libp2p:keychain:cms');
12
- const privates = new WeakMap();
13
- /**
14
- * Cryptographic Message Syntax (aka PKCS #7)
15
- *
16
- * CMS describes an encapsulation syntax for data protection. It
17
- * is used to digitally sign, digest, authenticate, or encrypt
18
- * arbitrary message content.
19
- *
20
- * See RFC 5652 for all the details.
21
- */
22
- export class CMS {
23
- /**
24
- * Creates a new instance with a keychain
25
- */
26
- constructor(keychain, dek) {
27
- if (keychain == null) {
28
- throw errCode(new Error('keychain is required'), codes.ERR_KEYCHAIN_REQUIRED);
29
- }
30
- this.keychain = keychain;
31
- privates.set(this, { dek });
32
- }
33
- /**
34
- * Creates some protected data.
35
- *
36
- * The output Uint8Array contains the PKCS #7 message in DER.
37
- */
38
- async encrypt(name, plain) {
39
- if (!(plain instanceof Uint8Array)) {
40
- throw errCode(new Error('Plain data must be a Uint8Array'), codes.ERR_INVALID_PARAMETERS);
41
- }
42
- const key = await this.keychain.findKeyByName(name);
43
- const pem = await this.keychain.getPrivateKey(name);
44
- const cached = privates.get(this);
45
- if (cached == null) {
46
- throw errCode(new Error('dek missing'), codes.ERR_INVALID_PARAMETERS);
47
- }
48
- const dek = cached.dek;
49
- const privateKey = forge.pki.decryptRsaPrivateKey(pem, dek);
50
- const certificate = await certificateForKey(key, privateKey);
51
- // create a p7 enveloped message
52
- const p7 = forge.pkcs7.createEnvelopedData();
53
- p7.addRecipient(certificate);
54
- p7.content = forge.util.createBuffer(plain);
55
- p7.encrypt();
56
- // convert message to DER
57
- const der = forge.asn1.toDer(p7.toAsn1()).getBytes();
58
- return uint8ArrayFromString(der, 'ascii');
59
- }
60
- /**
61
- * Reads some protected data.
62
- *
63
- * The keychain must contain one of the keys used to encrypt the data. If none of the keys
64
- * exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
65
- */
66
- async decrypt(cmsData) {
67
- if (!(cmsData instanceof Uint8Array)) {
68
- throw errCode(new Error('CMS data is required'), codes.ERR_INVALID_PARAMETERS);
69
- }
70
- let cms;
71
- try {
72
- const buf = forge.util.createBuffer(uint8ArrayToString(cmsData, 'ascii'));
73
- const obj = forge.asn1.fromDer(buf);
74
- cms = forge.pkcs7.messageFromAsn1(obj);
75
- }
76
- catch (err) {
77
- log.error(err);
78
- throw errCode(new Error('Invalid CMS'), codes.ERR_INVALID_CMS);
79
- }
80
- // Find a recipient whose key we hold. We only deal with recipient certs
81
- // issued by ipfs (O=ipfs).
82
- const recipients = cms.recipients
83
- // @ts-expect-error cms types not defined
84
- .filter(r => r.issuer.find(a => a.shortName === 'O' && a.value === 'ipfs'))
85
- // @ts-expect-error cms types not defined
86
- .filter(r => r.issuer.find(a => a.shortName === 'CN'))
87
- // @ts-expect-error cms types not defined
88
- .map(r => {
89
- return {
90
- recipient: r,
91
- // @ts-expect-error cms types not defined
92
- keyId: r.issuer.find(a => a.shortName === 'CN').value
93
- };
94
- });
95
- const r = await findAsync(recipients, async (recipient) => {
96
- try {
97
- const key = await this.keychain.findKeyById(recipient.keyId);
98
- if (key != null) {
99
- return true;
100
- }
101
- }
102
- catch (err) {
103
- return false;
104
- }
105
- return false;
106
- });
107
- if (r == null) {
108
- // @ts-expect-error cms types not defined
109
- const missingKeys = recipients.map(r => r.keyId);
110
- throw errCode(new Error(`Decryption needs one of the key(s): ${missingKeys.join(', ')}`), codes.ERR_MISSING_KEYS, {
111
- missingKeys
112
- });
113
- }
114
- const key = await this.keychain.findKeyById(r.keyId);
115
- if (key == null) {
116
- throw errCode(new Error('No key available to decrypto'), codes.ERR_NO_KEY);
117
- }
118
- const pem = await this.keychain.getPrivateKey(key.name);
119
- const cached = privates.get(this);
120
- if (cached == null) {
121
- throw errCode(new Error('dek missing'), codes.ERR_INVALID_PARAMETERS);
122
- }
123
- const dek = cached.dek;
124
- const privateKey = forge.pki.decryptRsaPrivateKey(pem, dek);
125
- cms.decrypt(r.recipient, privateKey);
126
- return uint8ArrayFromString(cms.content.getBytes(), 'ascii');
127
- }
128
- }
129
- //# sourceMappingURL=cms.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cms.js","sourceRoot":"","sources":["../../src/cms.ts"],"names":[],"mappings":"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"}
package/src/cms.ts DELETED
@@ -1,150 +0,0 @@
1
- import 'node-forge/lib/pkcs7.js'
2
- import 'node-forge/lib/pbe.js'
3
- // @ts-expect-error types are missing
4
- import forge from 'node-forge/lib/forge.js'
5
- import { certificateForKey, findAsync } from './util.js'
6
- import errCode from 'err-code'
7
- import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
8
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
9
- import { codes } from './errors.js'
10
- import { logger } from '@libp2p/logger'
11
- import type { KeyChain } from './index.js'
12
-
13
- const log = logger('libp2p:keychain:cms')
14
-
15
- const privates = new WeakMap<object, { dek: string }>()
16
-
17
- /**
18
- * Cryptographic Message Syntax (aka PKCS #7)
19
- *
20
- * CMS describes an encapsulation syntax for data protection. It
21
- * is used to digitally sign, digest, authenticate, or encrypt
22
- * arbitrary message content.
23
- *
24
- * See RFC 5652 for all the details.
25
- */
26
- export class CMS {
27
- private readonly keychain: KeyChain
28
-
29
- /**
30
- * Creates a new instance with a keychain
31
- */
32
- constructor (keychain: KeyChain, dek: string) {
33
- if (keychain == null) {
34
- throw errCode(new Error('keychain is required'), codes.ERR_KEYCHAIN_REQUIRED)
35
- }
36
-
37
- this.keychain = keychain
38
- privates.set(this, { dek })
39
- }
40
-
41
- /**
42
- * Creates some protected data.
43
- *
44
- * The output Uint8Array contains the PKCS #7 message in DER.
45
- */
46
- async encrypt (name: string, plain: Uint8Array): Promise<Uint8Array> {
47
- if (!(plain instanceof Uint8Array)) {
48
- throw errCode(new Error('Plain data must be a Uint8Array'), codes.ERR_INVALID_PARAMETERS)
49
- }
50
-
51
- const key = await this.keychain.findKeyByName(name)
52
- const pem = await this.keychain.getPrivateKey(name)
53
- const cached = privates.get(this)
54
-
55
- if (cached == null) {
56
- throw errCode(new Error('dek missing'), codes.ERR_INVALID_PARAMETERS)
57
- }
58
-
59
- const dek = cached.dek
60
- const privateKey = forge.pki.decryptRsaPrivateKey(pem, dek)
61
- const certificate = await certificateForKey(key, privateKey)
62
-
63
- // create a p7 enveloped message
64
- const p7 = forge.pkcs7.createEnvelopedData()
65
- p7.addRecipient(certificate)
66
- p7.content = forge.util.createBuffer(plain)
67
- p7.encrypt()
68
-
69
- // convert message to DER
70
- const der = forge.asn1.toDer(p7.toAsn1()).getBytes()
71
- return uint8ArrayFromString(der, 'ascii')
72
- }
73
-
74
- /**
75
- * Reads some protected data.
76
- *
77
- * The keychain must contain one of the keys used to encrypt the data. If none of the keys
78
- * exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
79
- */
80
- async decrypt (cmsData: Uint8Array): Promise<Uint8Array> {
81
- if (!(cmsData instanceof Uint8Array)) {
82
- throw errCode(new Error('CMS data is required'), codes.ERR_INVALID_PARAMETERS)
83
- }
84
-
85
- let cms: any
86
- try {
87
- const buf = forge.util.createBuffer(uint8ArrayToString(cmsData, 'ascii'))
88
- const obj = forge.asn1.fromDer(buf)
89
-
90
- cms = forge.pkcs7.messageFromAsn1(obj)
91
- } catch (err: any) {
92
- log.error(err)
93
- throw errCode(new Error('Invalid CMS'), codes.ERR_INVALID_CMS)
94
- }
95
-
96
- // Find a recipient whose key we hold. We only deal with recipient certs
97
- // issued by ipfs (O=ipfs).
98
- const recipients: any = cms.recipients
99
- // @ts-expect-error cms types not defined
100
- .filter(r => r.issuer.find(a => a.shortName === 'O' && a.value === 'ipfs'))
101
- // @ts-expect-error cms types not defined
102
- .filter(r => r.issuer.find(a => a.shortName === 'CN'))
103
- // @ts-expect-error cms types not defined
104
- .map(r => {
105
- return {
106
- recipient: r,
107
- // @ts-expect-error cms types not defined
108
- keyId: r.issuer.find(a => a.shortName === 'CN').value
109
- }
110
- })
111
-
112
- const r = await findAsync(recipients, async (recipient: any) => {
113
- try {
114
- const key = await this.keychain.findKeyById(recipient.keyId)
115
- if (key != null) {
116
- return true
117
- }
118
- } catch (err: any) {
119
- return false
120
- }
121
- return false
122
- })
123
-
124
- if (r == null) {
125
- // @ts-expect-error cms types not defined
126
- const missingKeys: string[] = recipients.map(r => r.keyId)
127
- throw errCode(new Error(`Decryption needs one of the key(s): ${missingKeys.join(', ')}`), codes.ERR_MISSING_KEYS, {
128
- missingKeys
129
- })
130
- }
131
-
132
- const key = await this.keychain.findKeyById(r.keyId)
133
-
134
- if (key == null) {
135
- throw errCode(new Error('No key available to decrypto'), codes.ERR_NO_KEY)
136
- }
137
-
138
- const pem = await this.keychain.getPrivateKey(key.name)
139
- const cached = privates.get(this)
140
-
141
- if (cached == null) {
142
- throw errCode(new Error('dek missing'), codes.ERR_INVALID_PARAMETERS)
143
- }
144
-
145
- const dek = cached.dek
146
- const privateKey = forge.pki.decryptRsaPrivateKey(pem, dek)
147
- cms.decrypt(r.recipient, privateKey)
148
- return uint8ArrayFromString(cms.content.getBytes(), 'ascii')
149
- }
150
- }