Skip to content

Commit

Permalink
fix(dkim): New class BodyHashStream
Browse files Browse the repository at this point in the history
  • Loading branch information
andris9 committed Oct 2, 2024
1 parent d5e42ed commit 88d2fad
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 3 deletions.
24 changes: 24 additions & 0 deletions examples/dkim-body-hash-stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

// sign and verify:
// $ node sign-and-verify.js /path/to/message.eml

const fs = require('node:fs');
const { BodyHashStream } = require('../lib/dkim/body');

let file = process.argv[2];
let eml = fs.createReadStream(file);

let algo = process.argv[3] || false; // allowed: 'rsa-sha256', 'rsa-sha1', 'ed25519-sha256'

let signer = new BodyHashStream('relaxed/relaxed', algo);

eml.on('error', err => {
console.error(err);
});

signer.once('hash', hash => {
console.error('BODY HASH: ' + hash);
});

eml.pipe(signer).pipe(process.stdout);
76 changes: 73 additions & 3 deletions lib/dkim/body/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
'use strict';

let { SimpleHash } = require('./simple');
let { RelaxedHash } = require('./relaxed');
const { SimpleHash } = require('./simple');
const { RelaxedHash } = require('./relaxed');
const { Transform } = require('node:stream');
const { MessageParser } = require('../message-parser');

const dkimBody = (canonicalization, ...options) => {
canonicalization = (canonicalization || 'simple/simple').toString().split('/').pop().toLowerCase().trim();
Expand All @@ -18,4 +20,72 @@ const dkimBody = (canonicalization, ...options) => {
}
};

module.exports = { dkimBody };
class MessageHasher extends MessageParser {
constructor(canonicalization, ...options) {
super();
this.hasher = dkimBody(canonicalization, ...options);
this.bodyHash = null;
}

async nextChunk(chunk) {
this.hasher.update(chunk);
}

async finalChunk() {
this.bodyHash = this.hasher.digest('base64');
}
}

class BodyHashStream extends Transform {
constructor(canonicalization, ...options) {
super();

this.finished = false;
this.finishCb = null;

this.messageHasher = new MessageHasher(canonicalization, ...options);
this.bodyHash = null;
this.messageHasher.once('finish', () => this.finishHashing());
this.messageHasher.once('end', () => this.finishHashing());
this.messageHasher.once('error', err => this.destroy(err));
}

finishHashing() {
if (this.finished || !this.finishCb) {
return;
}
this.finished = true;
let done = this.finishCb;
this.finishCb = null;

this.bodyHash = this.messageHasher.bodyHash;
this.emit('hash', this.bodyHash);

done();
}

_transform(chunk, encoding, done) {
if (!chunk || !chunk.length) {
return done();
}

if (typeof chunk === 'string') {
chunk = Buffer.from(chunk, encoding);
}

if (this.messageHasher.write(chunk) === false) {
// wait for drain
return this.messageHasher.once('drain', done);
}

this.push(chunk);
done();
}

_flush(done) {
this.finishCb = done;
this.messageHasher.end();
}
}

module.exports = { dkimBody, BodyHashStream };

0 comments on commit 88d2fad

Please sign in to comment.