mirror of
https://github.com/therootcompany/keypairs.js.git
synced 2024-11-16 17:29:03 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eab6cf919a | |||
| 97cb6c04b9 | |||
| ac1ff1ad4d | |||
| 2e74219361 | |||
| 11965ca603 | |||
| b696c1dade | |||
| b2fc0ebf35 | |||
| af7ee5426f | |||
| c66e9267aa | |||
| 2f14507693 | |||
| 016d87b839 | |||
| b1df7af626 | |||
| e880ef3f83 |
6
.jshintrc
Normal file
6
.jshintrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"esversion": 11,
|
||||||
|
"node": true,
|
||||||
|
"unused": true,
|
||||||
|
"curly": true
|
||||||
|
}
|
||||||
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"printWidth": 80,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"useTabs": true
|
||||||
|
}
|
||||||
70
README.md
70
README.md
@ -1,4 +1,4 @@
|
|||||||
# @root/keypairs
|
# [@root/keypairs](https://git.rootprojects.org/root/keypairs.js)
|
||||||
|
|
||||||
Lightweight JavaScript RSA and ECDSA utils that work on Windows, Mac, and Linux
|
Lightweight JavaScript RSA and ECDSA utils that work on Windows, Mac, and Linux
|
||||||
using modern node.js APIs (no need for C compiler).
|
using modern node.js APIs (no need for C compiler).
|
||||||
@ -20,6 +20,8 @@ and [Rasha.js (RSA)](https://git.coolaj86.com/coolaj86/rasha.js/).
|
|||||||
- [ ] Auth0
|
- [ ] Auth0
|
||||||
- [ ] CLI
|
- [ ] CLI
|
||||||
- See [keypairs-cli](https://npmjs.com/packages/keypairs-cli/)
|
- See [keypairs-cli](https://npmjs.com/packages/keypairs-cli/)
|
||||||
|
- [x] Node
|
||||||
|
- [x] Browsers (Webpack >=5)
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
@ -86,6 +88,72 @@ return Keypairs.signJwt({
|
|||||||
By default ECDSA keys will be used since they've had native support in node
|
By default ECDSA keys will be used since they've had native support in node
|
||||||
_much_ longer than RSA has, and they're smaller, and faster to generate.
|
_much_ longer than RSA has, and they're smaller, and faster to generate.
|
||||||
|
|
||||||
|
## Webpack 5+ (for Browsers)
|
||||||
|
|
||||||
|
This package includes native browser versions of all special functions.
|
||||||
|
|
||||||
|
Since Webpack 5 now fully supports vanilla JavaScript and exclusive browser builds out-of-the-box,
|
||||||
|
it's pretty easy to create a minimal config to use Keypairs in your browser projects:
|
||||||
|
|
||||||
|
`webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './main.js',
|
||||||
|
mode: 'development',
|
||||||
|
devServer: {
|
||||||
|
contentBase: path.join(__dirname, 'dist'),
|
||||||
|
port: 3001
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
publicPath: 'http://localhost:3001/'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [{}]
|
||||||
|
},
|
||||||
|
plugins: []
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
`main.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Keypairs = require('./keypairs.js');
|
||||||
|
|
||||||
|
Keypairs.generate().then(function (pair) {
|
||||||
|
console.log(pair.private);
|
||||||
|
console.log(pair.public);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
`index.html`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script src="./dist/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev webpack@5
|
||||||
|
# Or, if webpack 5 is still in beta: npm install --save-dev webpack@next
|
||||||
|
|
||||||
|
npm install --save-dev webpack-cli
|
||||||
|
|
||||||
|
npx webpack --mode=production
|
||||||
|
|
||||||
|
ls dist/main.js
|
||||||
|
```
|
||||||
|
|
||||||
## API Overview
|
## API Overview
|
||||||
|
|
||||||
- generate (JWK)
|
- generate (JWK)
|
||||||
|
|||||||
14
keypairs.js
14
keypairs.js
@ -107,7 +107,7 @@ Keypairs.generate = function(opts) {
|
|||||||
} else if (/^RSA$/i.test(opts.kty)) {
|
} else if (/^RSA$/i.test(opts.kty)) {
|
||||||
p = Rasha.generate(opts);
|
p = Rasha.generate(opts);
|
||||||
} else {
|
} else {
|
||||||
return Promise.Reject(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
"'" +
|
"'" +
|
||||||
opts.kty +
|
opts.kty +
|
||||||
@ -218,7 +218,7 @@ Keypairs.signJwt = function(opts) {
|
|||||||
var claims = JSON.parse(JSON.stringify(opts.claims || {}));
|
var claims = JSON.parse(JSON.stringify(opts.claims || {}));
|
||||||
header.typ = 'JWT';
|
header.typ = 'JWT';
|
||||||
|
|
||||||
if (!header.kid && false !== header.kid) {
|
if (!header.kid && !header.jwk && false !== header.kid) {
|
||||||
header.kid = thumb;
|
header.kid = thumb;
|
||||||
}
|
}
|
||||||
if (!header.alg && opts.alg) {
|
if (!header.alg && opts.alg) {
|
||||||
@ -294,19 +294,19 @@ Keypairs.signJws = function(opts) {
|
|||||||
if (!protect.alg) {
|
if (!protect.alg) {
|
||||||
protect.alg = alg();
|
protect.alg = alg();
|
||||||
}
|
}
|
||||||
|
|
||||||
// There's a particular request where ACME / Let's Encrypt explicitly doesn't use a kid
|
// There's a particular request where ACME / Let's Encrypt explicitly doesn't use a kid
|
||||||
|
// There should be a kid unless it's `false` or there's a `jwk` (a self-signed JWS)
|
||||||
|
if (!protect.kid) {
|
||||||
if (false === protect.kid) {
|
if (false === protect.kid) {
|
||||||
protect.kid = undefined;
|
protect.kid = undefined;
|
||||||
} else if (!protect.kid) {
|
} else if (!protect.jwk) {
|
||||||
protect.kid = thumb;
|
protect.kid = thumb;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
protectedHeader = JSON.stringify(protect);
|
protectedHeader = JSON.stringify(protect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not sure how to handle the empty case since ACME POST-as-GET must be empty
|
|
||||||
//if (!payload) {
|
|
||||||
// throw new Error("opts.payload should be JSON, string, or ArrayBuffer (it may be empty, but that must be explicit)");
|
|
||||||
//}
|
|
||||||
// Trying to detect if it's a plain object (not Buffer, ArrayBuffer, Array, Uint8Array, etc)
|
// Trying to detect if it's a plain object (not Buffer, ArrayBuffer, Array, Uint8Array, etc)
|
||||||
if (
|
if (
|
||||||
payload &&
|
payload &&
|
||||||
|
|||||||
@ -9,5 +9,7 @@ sha2.sum = function(alg, str) {
|
|||||||
data = encoder.encode(str);
|
data = encoder.encode(str);
|
||||||
}
|
}
|
||||||
var sha = 'SHA-' + String(alg).replace(/^sha-?/i, '');
|
var sha = 'SHA-' + String(alg).replace(/^sha-?/i, '');
|
||||||
return window.crypto.subtle.digest(sha, data);
|
return window.crypto.subtle.digest(sha, data).then(function (buf) {
|
||||||
|
return new Uint8Array(buf);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,10 +13,7 @@ module.exports = function(bitlen, exp) {
|
|||||||
}
|
}
|
||||||
var keypair = ursa.generatePrivateKey(bitlen, exp);
|
var keypair = ursa.generatePrivateKey(bitlen, exp);
|
||||||
var result = {
|
var result = {
|
||||||
privateKeyPem: keypair
|
privateKeyPem: keypair.toPrivatePem().toString('ascii').trim()
|
||||||
.toPrivatePem()
|
|
||||||
.toString('ascii')
|
|
||||||
.trim()
|
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,10 +10,7 @@ Keypairs._sign = function(opts, payload) {
|
|||||||
// node specifies RSA-SHAxxx even when it's actually ecdsa (it's all encoded x509 shasums anyway)
|
// node specifies RSA-SHAxxx even when it's actually ecdsa (it's all encoded x509 shasums anyway)
|
||||||
// TODO opts.alg = (protect||header).alg
|
// TODO opts.alg = (protect||header).alg
|
||||||
var nodeAlg = 'SHA' + Keypairs._getBits(opts);
|
var nodeAlg = 'SHA' + Keypairs._getBits(opts);
|
||||||
var binsig = crypto
|
var binsig = crypto.createSign(nodeAlg).update(payload).sign(pem);
|
||||||
.createSign(nodeAlg)
|
|
||||||
.update(payload)
|
|
||||||
.sign(pem);
|
|
||||||
|
|
||||||
if ('EC' === opts.jwk.kty && !/x509|asn1/i.test(opts.format)) {
|
if ('EC' === opts.jwk.kty && !/x509|asn1/i.test(opts.format)) {
|
||||||
// ECDSA JWT signatures differ from "normal" ECDSA signatures
|
// ECDSA JWT signatures differ from "normal" ECDSA signatures
|
||||||
|
|||||||
@ -9,9 +9,6 @@ sha2.sum = function(alg, str) {
|
|||||||
var sha = 'sha' + String(alg).replace(/^sha-?/i, '');
|
var sha = 'sha' + String(alg).replace(/^sha-?/i, '');
|
||||||
// utf8 is the default for strings
|
// utf8 is the default for strings
|
||||||
var buf = Buffer.from(str);
|
var buf = Buffer.from(str);
|
||||||
return crypto
|
return crypto.createHash(sha).update(buf).digest();
|
||||||
.createHash(sha)
|
|
||||||
.update(buf)
|
|
||||||
.digest();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@root/keypairs",
|
"name": "@root/keypairs",
|
||||||
"version": "0.9.0",
|
"version": "0.10.2",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@root/keypairs",
|
"name": "@root/keypairs",
|
||||||
"version": "0.9.0",
|
"version": "0.10.2",
|
||||||
"description": "Lightweight, Zero-Dependency RSA and EC/ECDSA crypto for Node.js and Browsers",
|
"description": "Lightweight, Zero-Dependency RSA and EC/ECDSA crypto for Node.js and Browsers",
|
||||||
"main": "keypairs.js",
|
"main": "keypairs.js",
|
||||||
"browser": {
|
"browser": {
|
||||||
@ -20,7 +20,7 @@
|
|||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.rootprojects.org/root/csr.js.git"
|
"url": "https://github.com/therootcompany/keypairs.js.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ASN.1",
|
"ASN.1",
|
||||||
|
|||||||
@ -89,14 +89,14 @@ Keypairs.parseOrGenerate({ key: null })
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
Keypairs.parse({ key: JSON.stringify(pair.private) }).then(function(
|
Keypairs.parse({ key: JSON.stringify(pair.private) }).then(
|
||||||
pair
|
function (pair) {
|
||||||
) {
|
|
||||||
if (!pair.private || !pair.public) {
|
if (!pair.private || !pair.public) {
|
||||||
throw new Error('missing key pairs (stringified jwt)');
|
throw new Error('missing key pairs (stringified jwt)');
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
Keypairs.parse({
|
Keypairs.parse({
|
||||||
key: JSON.stringify(pair.private),
|
key: JSON.stringify(pair.private),
|
||||||
public: true
|
public: true
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user