New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mailauth

Package Overview
Dependencies
Maintainers
1
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mailauth - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

LICENSE.txt

7

examples/sign-and-verify.js

@@ -14,6 +14,5 @@ 'use strict';

let algo = process.argv[3] || 'rsa-sha256'; // or 'ed25519-sha256'
let algo = process.argv[3] || false; // allowed: 'rsa-sha256', 'rsa-sha1', 'ed25519-sha256'
dkimSign(eml, {
algorithm: algo,
canonicalization: 'simple/simple',

@@ -23,2 +22,3 @@ signTime: Date.now(),

{
algorithm: algo,
signingDomain: 'tahvel.info',

@@ -29,2 +29,3 @@ selector: 'test.invalid',

{
algorithm: algo,
signingDomain: 'tahvel.info',

@@ -35,2 +36,3 @@ selector: 'test.rsa',

{
algorithm: algo,
signingDomain: 'tahvel.info',

@@ -42,2 +44,3 @@ selector: 'test.small',

{
algorithm: algo,
signingDomain: 'tahvel.info',

@@ -44,0 +47,0 @@ selector: 'test.ed25519',

@@ -13,8 +13,4 @@ 'use strict';

let { algorithm, canonicalization, signTime, headerList, signatureData } = options || {};
let { canonicalization, signTime, headerList, signatureData } = options || {};
this.algorithm = algorithm || 'rsa-sha256';
this.signAlgo = this.algorithm.split('-').shift().toLowerCase().trim();
this.hashAlgo = this.algorithm.split('-').pop().toLowerCase().trim();
this.canonicalization = canonicalization || 'relaxed/relaxed';

@@ -33,20 +29,68 @@ this.headerCanon = this.canonicalization.split('/').shift().toLowerCase().trim();

this.bodyHash = false;
this.bodyHashes = new Map();
this.setupHashes();
}
setupHashes() {
for (let signatureData of this.signatureData || []) {
if (!signatureData.privateKey) {
continue;
}
let algorithm = (signatureData.algorithm || '').toLowerCase().trim();
let hashAlgo = algorithm.split('-').pop().toLowerCase().trim() || 'sha256';
if (!this.bodyHashes.has(hashAlgo)) {
this.bodyHashes.set(hashAlgo, { hasher: null, hash: null });
}
}
}
validateAlgorithm(algorithm) {
try {
if (!algorithm || !/^[^-]+-[^-]+$/.test(algorithm)) {
throw new Error('Invalid algorithm format');
}
let [signing, hashing] = algorithm.split('-');
if (!['rsa', 'ed25519'].includes(signing)) {
throw new Error('Unknown signing algorithm: ' + signing);
}
if (!['sha256', 'sha1'].includes(hashing)) {
throw new Error('Unknown hashing algorithm: ' + hashing);
}
} catch (err) {
err.code = 'EINVALIDALGO';
throw err;
}
}
async messageHeaders(headers) {
this.headers = headers;
this.bodyHash = dkimBody(this.bodyCanon, this.hashAlgo);
for (let hashAlgo of this.bodyHashes.keys()) {
this.bodyHashes.get(hashAlgo).hasher = dkimBody(this.bodyCanon, hashAlgo);
}
}
async nextChunk(chunk) {
this.bodyHash.update(chunk);
for (let hashAlgo of this.bodyHashes.keys()) {
if (this.bodyHashes.get(hashAlgo).hasher) {
this.bodyHashes.get(hashAlgo).hasher.update(chunk);
}
}
}
async finalChunk() {
if (!this.headers || !this.bodyHash) {
if (!this.headers) {
return;
}
this.bodyHash = this.bodyHash.digest('base64');
for (let hashAlgo of this.bodyHashes.keys()) {
if (this.bodyHashes.get(hashAlgo).hasher) {
this.bodyHashes.get(hashAlgo).hash = this.bodyHashes.get(hashAlgo).hasher.digest('base64');
}
}

@@ -60,29 +104,29 @@ let signedHeaderLines = getSignedHeaderLines(this.headers.parsed, this.headerList);

let { signingHeaders, dkimHeaderOpts } = dkimHeader(
signedHeaderLines,
Object.assign(
{
algorithm: this.algorithm,
canonicalization: this.canonicalization,
signTime: this.signTime,
bodyHash: this.bodyHash
},
signatureData
)
);
let algorithm = (signatureData.algorithm || '').toLowerCase().trim();
let signAlgo = algorithm.split('-').shift().toLowerCase().trim() || null;
let hashAlgo = algorithm.split('-').pop().toLowerCase().trim() || 'sha256';
try {
let keyType = crypto.createPrivateKey({ key: signatureData.privateKey, format: 'pem' }).asymmetricKeyType;
if (keyType !== this.signAlgo) {
if (signAlgo && keyType !== signAlgo) {
// invalid key type
let err = new Error(`Invalid key type: ${keyType} (expecting ${this.signAlgo})`);
err.code = 'EKEY';
let err = new Error(`Invalid key type: "${keyType}" (expecting "${signAlgo}")`);
err.code = 'EINVALIDTYPE';
throw err;
}
if (!['rsa', 'ed25519'].includes(keyType)) {
let err = new Error(`Unsupported key type: "${keyType}"`);
err.code = 'EINVALIDTYPE';
throw err;
}
if (!signAlgo) {
signAlgo = keyType;
}
algorithm = `${signAlgo}-${hashAlgo}`;
} catch (err) {
this.errors.push({
a: dkimHeaderOpts.a,
c: dkimHeaderOpts.c,
s: dkimHeaderOpts.s,
d: dkimHeaderOpts.d,
selector: signatureData.selector,
signingDomain: signatureData.signingDomain,
err

@@ -94,6 +138,29 @@ });

try {
// throws if invalid
this.validateAlgorithm(algorithm);
} catch (err) {
this.errors.push({
algorithm,
selector: signatureData.selector,
signingDomain: signatureData.signingDomain,
err
});
continue;
}
let { signingHeaders, dkimHeaderOpts } = dkimHeader(
signedHeaderLines,
Object.assign({}, signatureData, {
algorithm,
canonicalization: this.canonicalization,
signTime: this.signTime,
bodyHash: this.bodyHashes.has(hashAlgo) ? this.bodyHashes.get(hashAlgo).hash : null
})
);
try {
let signature = crypto
.sign(
// use `null` as algorithm to detect it from the key file
this.signAlgo === 'rsa' ? this.algorithm : null,
signAlgo === 'rsa' ? algorithm : null,
signingHeaders,

@@ -108,6 +175,5 @@ signatureData.privateKey

this.errors.push({
a: dkimHeaderOpts.a,
c: dkimHeaderOpts.c,
s: dkimHeaderOpts.s,
d: dkimHeaderOpts.d,
algorithm,
selector: signatureData.selector,
signingDomain: signatureData.signingDomain,
err

@@ -114,0 +180,0 @@ });

@@ -18,22 +18,7 @@ 'use strict';

const validateAlgorithm = algorithm => {
let [signing, hashing] = algorithm.split('-');
if (!['rsa', 'ed25519'].includes(signing)) {
throw new Error('Unknown signing algorithm: ' + signing);
}
if (!['sha256', 'sha1'].includes(hashing)) {
throw new Error('Unknown hashing algorithm: ' + hashing);
}
};
const dkimSign = async (input, options) => {
let { algorithm, canonicalization } = options || {};
let { canonicalization } = options || {};
canonicalization = (canonicalization || 'relaxed/relaxed').toLowerCase().trim();
algorithm = (algorithm || 'rsa-sha256').toLowerCase().trim();
validateCanonicalization(canonicalization);
validateAlgorithm(algorithm);

@@ -40,0 +25,0 @@ let dkimSigner = new DkimSigner(options);

{
"name": "mailauth",
"version": "1.0.1",
"version": "1.0.2",
"description": "Email authentication library for Node.js",

@@ -20,3 +20,3 @@ "main": "lib/mailauth.js",

"author": "Andris Reinman",
"license": "MIT",
"license": "AGPL-3.0-or-later",
"bugs": {

@@ -23,0 +23,0 @@ "url": "https://github.com/andris9/mailauth/issues"

@@ -15,4 +15,6 @@ # mailauth

Install from NPM
### Free, AGPL-licensed version
First install the module from npm:
```

@@ -22,2 +24,38 @@ $ npm install mailauth

next import any method you want to use from mailauth package into your script:
```js
const { authenticate } = require('mailauth');
```
### MIT version
MIT-licensed version is available for [Postal Systems subscribers](https://postalsys.com/).
First install the module from Postal Systems private registry:
```
$ npm install @postalsys/mailauth
```
next import any method you want to use from mailauth package into your script:
```js
const { authenticate } = require('@postalsys/mailauth');
```
If you have already built your application using the free version of "mailauth" and do not want to modify require statements in your code, you can install the MIT-licensed version as an alias for "mailauth".
```
$ npm install mailauth@npm:@postalsys/mailauth
```
This way you can keep using the old module name
```js
const { authenticate } = require('mailauth');
```
## Usage
## Authentication

@@ -67,6 +105,13 @@

{
algorithm: 'rsa-sha256', // a= either "rsa-sha256" (the default) or "ed25519-sha256" if you are using EC keys
// optional canonicalization, default is "relaxed/relaxed"
// this option applies to all signatures, so you can't create multiple signatures
// that use different canonicalization
canonicalization: 'relaxed/relaxed', // c=
// optional, default is current time
signTime: new Date(), // t=
// Keys for one or more signatures
// Different signatures can use different algorithms (mostly useful when
// you want to sign a message both with RSA and Ed25519)
signatureData: [

@@ -76,8 +121,12 @@ {

selector: 'test.rsa', // s=
privateKey: fs.readFileSync('./test/fixtures/private-rsa.pem')
// supported key types: RSA, Ed25519
privateKey: fs.readFileSync('./test/fixtures/private-rsa.pem'),
// Optional algorithm, default is derived from the key.
// Mostly useful when you want to use rsa-sha1, otherwise no need to set
algorithm: 'rsa-sha256'
}
]
}
); // -> {String} signature headers using \r\n as the line separator
// show signing errors
); // -> {signatures: String, errors: Array} signature headers using \r\n as the line separator
// show signing errors (if any)
if (signResult.errors.length) {

@@ -144,2 +193,6 @@ console.log(signResult.errors);

**MIT**
© 2020 Andris Reinman
Licensed under GNU Affero General Public License v3.0 or later.
MIT-licensed version of mailauth is available for [Postal Systems subscribers](https://postalsys.com/).
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc