Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
clshortfuse committed Feb 27, 2023
0 parents commit 25b4b66
Show file tree
Hide file tree
Showing 50 changed files with 5,712 additions and 0 deletions.
190 changes: 190 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
{
"extends": [
"airbnb-base",
"plugin:@typescript-eslint/recommended",
"plugin:jsdoc/recommended",
"plugin:n/recommended",
"plugin:unicorn/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"impliedStrict": true
},
"ecmaVersion": 2020,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": [
"@typescript-eslint",
"jsdoc",
"unicorn"
],
"root": true,
"rules": {
"object-curly-newline": ["error", {
"ObjectExpression": { "multiline": true, "consistent": true },
"ObjectPattern": { "multiline": true, "consistent": true },
"ImportDeclaration": { "multiline": true, "consistent": true },
"ExportDeclaration": { "multiline": true, "consistent": true }
}],
"no-param-reassign": 0,
"no-continue": 0,
"no-restricted-syntax": 0,
"require-await": 0,
"no-return-await": 0,
"eslint-comments/no-use": 0,
"filenames/match-regex": 0,
"prettier/prettier": 0,
"i18n-text/no-en": 0,
"import/no-namespace": 0,
"no-unused-vars": 0,
"import/namespace": 0,
"no-constructor-return": 0,
"default-case-last": 0,
"no-undef": 0,
"import/named": 0,
"no-empty": ["error", {"allowEmptyCatch": true}],
"no-promise-executor-return": 0,
"@typescript-eslint/ban-ts-comment": ["warn", {
"ts-ignore": "allow-with-description"
}],
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/require-await": "error",
"no-void": "off",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/return-await": ["error", "always"],

"import/no-unresolved": "off",
"import/extensions": ["error", "always", {
"js": "always",
"mjs": "never"
}],
"import/no-useless-path-segments": ["error", {
"noUselessIndex": false
}],
"import/order": ["error", {
"alphabetize": {
"caseInsensitive": false,
"order": "asc"
},
"groups": [
"builtin",
"external",
"parent",
"sibling",
"index"
],
"newlines-between": "always",
"pathGroups": [{
"group": "external",
"pattern": "@dataprocs/**",
"position": "after"
}],
"pathGroupsExcludedImportTypes": ["builtin"]
}],
"import/prefer-default-export": 0,
"unicorn/switch-case-braces": 0,
"unicorn/no-useless-undefined": 0,
"unicorn/no-array-for-each": 0,
"unicorn/prefer-spread": 0,
"unicorn/no-null": 0,
"unicorn/filename-case": 0,
"unicorn/prefer-dom-node-append": 0,
"unicorn/prevent-abbreviations": 0,
"unicorn/explicit-length-check": 0,
"unicorn/catch-error-name": 0,
"unicorn/prefer-dom-node-dataset": 0,
"unicorn/no-array-reduce": 0,
"unicorn/no-this-assignment": 0,
"unicorn/prefer-ternary": ["error", "only-single-line"],
"unicorn/no-empty-file": 0,
"unicorn/prefer-query-selector": 0,
"unicorn/prefer-dom-node-remove": 0,
"unicorn/no-for-loop": 0,
"jsdoc/newline-after-description": [
"warn",
"never"
],
"jsdoc/no-undefined-types": 0,
"jsdoc/require-param-description": 0,
"jsdoc/require-property-description": 0,
"jsdoc/require-returns": 0,
"jsdoc/require-returns-description": 0,
"jsdoc/valid-types": 0,
"max-len": ["error", 120, 2, {
"ignoreComments": true,
"ignoreRegExpLiterals": true,
"ignoreStrings": true,
"ignoreTemplateLiterals": true,
"ignoreUrls": true
}],
"consistent-return": "warn",
"no-console": ["error", {
"allow": [
"warn",
"error",
"time",
"timeEnd"
]
}],
"no-plusplus": ["off"],
"node/no-unsupported-features/es-syntax": ["off", {
"ignores": [],
"version": ">=14.0.0"
}],
"prefer-destructuring": ["error", {
"AssignmentExpression": {
"array": false,
"object": false
},
"VariableDeclarator": {
"array": false,
"object": true
}
}, {
"enforceForRenamedProperties": false
}],
"sort-imports": ["error", {
"ignoreDeclarationSort": true
}],
"spaced-comment": ["error", "always", {
"block": {
"balanced": true,
"exceptions": ["-", "+"],
"markers": ["=", "!", ":", "::"]
},
"line": {
"exceptions": ["-", "+"],
"markers": ["=", "!", "/"]
}
}]
},
"settings": {
"jsdoc": {
"preferredTypes": {
"array": "Array",
"object": "Object",
"object.": "Object<>",
"object<>": "Object<>",
"symbol": "Symbol"
},
"tagNamePreference": {
"augment": "extends",
"constant": "const",
"property": "prop",
"returns": "return"
}
}
},
"overrides": [
{
"files": [ "*.cjs"],
"rules": {
"import/no-nodejs-modules": 0,
"@typescript-eslint/no-var-requires": 0
}
}
]

}
35 changes: 35 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug AVA",
"request": "launch",
"runtimeArgs": [
"run-script",
"debug-test"
],
"runtimeExecutable": "npm",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node"
},
{
"type": "node",
"request": "launch",
"name": "Debug AVA test file",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/ava",
"runtimeArgs": [
"--serial",
"${file}"
],
"outputCapture": "std",
"skipFiles": [
"<node_internals>/**/*.js"
]
},
]
}
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"javascript.preferences.importModuleSpecifier": "relative",
"javascript.preferences.importModuleSpecifierEnding": "js",
"javascript.preferences.quoteStyle": "single"
}
118 changes: 118 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# acmejs

Zero-dependency ACME Client

# Compatiblity

Uses:

| Feature | Chrome | Firefox | Safari | NodeJS | Deno |
| -------------------------------------------------------------------------------------------------- | -----: | ------: | -----: | -----: | ---: |
| [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) | 37 | 34 | 11 | 15.0.0 | 1.17 |
| [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch) | 42 | 39 | 10.1 | 18.0.0 | 1.0 |
| [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/EventTarget)* | 64 | 59 | 14 | 15.0.0 | 1.0 |
| [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)| 67 | 68 | 14 | 10.4.0 | 1.0 |
| | | | | | |
| Supported | 67 | 68 | 14 | 18.0.0 | 1.17 |

*Used by helper functions
†Used by helper ASN1 operations

*Compatibility may be extended via polyfills (not included)*

# Libraries

* [ACMEClient](./lib/ACMEAgent.js)
* [JOSE Functions](./lib/jose.js)
* [JWA Functions](./lib/jwa.js)
* [JWE Functions](./lib/jwe.js) (incomplete)
* [JWK Functions](./lib/jwk.js)
* [JWS Functions](./lib/jws.js)
* [KeyStore](./lib/KeyStore.js)

# Helpers

* [JWK Import Functions](./helpers/jwkImporter.js)
* [name.com DNS API](./lib/nameDotCom.js)
* [Quick Certificate Order](./lib/quickOrder.js)

# Utilities

* [ASN1 Encoder/Decoder](./utils/asn1.js)
* [Base64 Encoder/Decoder](./utils/base64.js)
* [Bit Functions](./utils/bit.js)
* [SubtleCrypto NodeJS Wrapper](./utils/crypto.js)
* [DNS Resolver](./utils/dns.js)
* [PKCS1, PKCS8, PKCS10 Functions](./utils/pkcs8.js)
* [UTF-8 Decoder](./utils/utf8.js)

# Usage


# Quick Order with name.com (defaults to Lets Encrypt ACME);

````js
import { buildEventTarget } from '@shortfuse/acmejs/helpers/nameDotCom.js';
import { getWildcardCertificate } from '@shortfuse/acmejs/helpers/quickOrder.js';

// as JWK
const ACCOUNT_PRIVATE_KEY = {
alg: 'ES256',
kty: 'EC',
crv: 'P-256',
x: 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
y: 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
d: 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI',
};

// as PEM
const CSR_PRIVATE_KEY = `
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDD0tPV/du2vftjvXj1t/gXTK39
sNBVrOAEb/jKzXae+Xa0H+3LhZaQIQNMfACiBSgIfZUvEGb+7TqXWQpoLoFR/R7MvGWcSk98JyrV
tveD8ZmZYyItSY7m2hcasqAFiKyOouV5vzyRe87/lEyzzBpF3bQQ4IDaQu+K9Hj5fKuU6rrOeOhs
dnJc+VdDQLScHxvMoLZ9Vtt+oK9J4/tOLwr4CG8khDlBURcBY6gPcLo3dPU09SW+6ctX2cX4mkXx
6O/0mmdTmacr/vu50KdRMleFeZYOWPAEhhMfywybTuzBiPVIZVP8WFCSKNMbfi1S9A9PdBqnebww
HhX3/hsEBt2BAgMBAAECggEABEI1P6nf6Zs7mJlyBDv+Pfl5rjL2cOqLy6TovvZVblMkCPpJyFuN
IPDK2tK2i897ZaXfhPDBIKmllM2Hq6jZQKB110OAnTPDg0JxzMiIHPs32S1d/KilHjGff4Hjd4NX
p1l1Dp8BUPOllorR2TYm2x6dcCGFw9lhTr8O03Qp4hjn84VjGIWADYCk83mgS4nRsnHkdiqYnWx1
AjKlY51yEK6RcrDMi0Th2RXrrINoC35sVv+APt2rkoMGi52RwTEseA1KZGFrxjq61ReJif6p2VXE
cvHeX6CWLx014LGk43z6Q28P6HgeEVEfIjyqCUea5Du/mYb/QsRSCosXLxBqwQKBgQD1+fdC9ZiM
rVI+km7Nx2CKBn8rJrDmUh5SbXn2MYJdrUd8bYNnZkCgKMgxVXsvJrbmVOrby2txOiqudZkk5mD3
E5O/QZWPWQLgRu8ueYNpobAX9NRgNfZ7rZD+81vh5MfZiXfuZOuzv29iZhU0oqyZ9y75eHkLdrer
NkwYOe5aUQKBgQDLzapDi1NxkBgsj9iiO4KUa7jvD4JjRqFy4Zhj/jbQvlvM0F/uFp7sxVcHGx4r
11C+6iCbhX4u+Zuu0HGjT4d+hNXmgGyxR8fIUVxOlOtDkVJa5sOBZK73/9/MBeKusdmJPRhalZQf
MUJRWIoEVDMhfg3tW/rBj5RYAtP2dTVUMQKBgDs8yr52dRmT+BWXoFWwaWB0NhYHSFz/c8v4D4Ip
5DJ5M5kUqquxJWksySGQa40sbqnD05fBQovPLU48hfgr/zghn9hUjBcsoZOvoZR4sRw0UztBvA+7
jzOz1hKAOyWIulR6Vca0yUrNlJ6G5R56+sRNkiOETupi2dLCzcqb0PoxAoGAZyNHvTLvIZN4iGSr
jz5qkM4LIwBIThFadxbv1fq6pt0O/BGf2o+cEdq0diYlGK64cEVwBwSBnSg4vzlBqRIAUejLjwED
AJyA4EE8Y5A9l04dzV7nJb5cRak6CrgXxay/mBJRFtaHxVlaZGxYPGSYE6UFS0+3EOmmevvDZQBf
4qECgYEA0ZF6Vavz28+8wLO6SP3w8NmpHk7K9tGEvUfQ30SgDx4G7qPIgfPrbB4OP/E0qCfsIImi
3sCPpjvUMQdVVZyPOIMuB+rV3ZOxkrzxEUOrpOpR48FZbL7RN90yRQsAsrp9e4iv8QwB3VxLe7X0
TDqqnRyqrc/osGzuS2ZcHOKmCU8=
-----END PRIVATE KEY-----
`;

const NAME_DOT_COM_USERNAME = 'foo';
const NAME_DOT_COM_TOKEN = 'bar';

const certificate = await getWildcardCertificate({
tosAgreed: true,
domain: 'foo.com',
jwk: ACCOUNT_PRIVATE_KEY,
email: '[email protected]',
eventTarget: buildEventTarget(NAME_DOT_COM_USERNAME, NAME_DOT_COM_TOKEN),
csr: {
countryName: 'US',
localityName: 'New York',
organizationName: 'Foo Products',
organizationalUnitName: 'IT',
stateOrProvinceName: 'NY',
jwk: CSR_PRIVATE_KEY,
},
});

await store('foo-com.crt', certificate);
````

See [quickOrder.js](./helpers/quickOrder.js) source code for a working example.
40 changes: 40 additions & 0 deletions data/Account.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* @see https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.2
* @typedef {Object} Account
* @prop {'valid'|'deactivated'|'revoked'} status The status of this account.
* The value "deactivated" should be used to indicate client-initiated
* deactivation whereas "revoked" should be used to indicate server-
* initiated deactivation. See Section 7.1.6.
* @prop {string[]} [contact] An array of URLs that the
* server can use to contact the client for issues related to this
* account. For example, the server may wish to notify the client
* about server-initiated revocation or certificate expiration. For
* information on supported URL schemes, see Section 7.3.
* @prop {boolean} [termsOfServiceAgreed] Including this field in a `newAccount`
* request, with a value of true, indicates the client's agreement with the
* terms of service. This field cannot be updated by the client.
* @prop {JWSJSONSerialization} [externalAccountBinding] Including this field in a
* newAccount request indicates approval by the holder of an existing
* non-ACME account to bind that account to this ACME account. This
* field is not updateable by the client (see Section 7.3.4).
* @prop {string} orders A URL from which a list of orders
* submitted by this account can be fetched via a POST-as-GET
* request, as described in Section 7.1.2.1.
*/

/**
* @see https://datatracker.ietf.org/doc/html/rfc8555#section-7.3
* @typedef {Object} AccountNewRequestFields
* @prop {boolean} [onlyReturnExisting] If this field is present
* with the value "true", then the server MUST NOT create a new
* account if one does not already exist. This allows a client to
* look up an account URL based on an account key (see
* Section 7.3.1).
*/

/**
* @see https://datatracker.ietf.org/doc/html/rfc8555#section-7.3
* @typedef {Pick<Account, 'contact'|'termsOfServiceAgreed'|'externalAccountBinding'> & AccountNewRequestFields} AccountNewRequest
*/

/** @typedef {Pick<Account, 'status'|'contact'>} AccountRequest */
Loading

0 comments on commit 25b4b66

Please sign in to comment.