Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 38 additions & 33 deletions lib/pkcs7.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,44 +444,42 @@ p7.createSignedData = function() {
}

function addSignerInfos(mds) {
var content;
var content,
bytes;

if (msg.detachedContent) {
// Signature has been made in detached mode.
content = msg.detachedContent;
} else {
// Note: ContentInfo is a SEQUENCE with 2 values, second value is
// the content field and is optional for a ContentInfo but required here
// since signers are present
// get ContentInfo content
content = msg.contentInfo.value[1];
// skip [0] EXPLICIT content wrapper
content = content.value[0];
}
if (msg.content) {
if (msg.detachedContent) {
// Signature has been made in detached mode.
content = msg.detachedContent;
} else {
// Note: ContentInfo is a SEQUENCE with 2 values, second value is
// the content field and is optional for a ContentInfo but required here
// since signers are present
// get ContentInfo content
content = msg.contentInfo.value[1];
// skip [0] EXPLICIT content wrapper
content = content.value[0];
}

if(!content) {
throw new Error(
'Could not sign PKCS#7 message; there is no content to sign.');
// serialize content
bytes = asn1.toDer(content);

// skip identifier and length per RFC 2315 9.3
// skip identifier (1 byte)
bytes.getByte();
// read and discard length bytes
asn1.getBerValueLength(bytes);
bytes = bytes.getBytes();

// digest content DER value bytes
for(var oid in mds) {
mds[oid].start().update(bytes);
}
}

// get ContentInfo content type
var contentType = asn1.derToOid(msg.contentInfo.value[0].value);

// serialize content
var bytes = asn1.toDer(content);

// skip identifier and length per RFC 2315 9.3
// skip identifier (1 byte)
bytes.getByte();
// read and discard length bytes
asn1.getBerValueLength(bytes);
bytes = bytes.getBytes();

// digest content DER value bytes
for(var oid in mds) {
mds[oid].start().update(bytes);
}

// sign content
var signingTime = new Date();
for(var i = 0; i < msg.signers.length; ++i) {
Expand Down Expand Up @@ -509,8 +507,15 @@ p7.createSignedData = function() {
for(var ai = 0; ai < signer.authenticatedAttributes.length; ++ai) {
var attr = signer.authenticatedAttributes[ai];
if(attr.type === forge.pki.oids.messageDigest) {
// use content message digest as value
attr.value = mds[signer.digestAlgorithm].digest();
// use content message digest as value if not already set
if(!attr.value){
if(!content) {
throw new Error(
'Could not sign PKCS#7 message; there is no content to ' +
'sign or message-digest attribute missing.');
}
attr.value = mds[signer.digestAlgorithm].digest();
}
} else if(attr.type === forge.pki.oids.signingTime) {
// auto-populate signing time if not already set
if(!attr.value) {
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/pkcs7.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var PKCS7 = require('../../lib/pkcs7');
var PKI = require('../../lib/pki');
var AES = require('../../lib/aes');
var DES = require('../../lib/des');
var SHA256 = require('../../lib/sha256');
var UTIL = require('../../lib/util');

(function() {
Expand Down Expand Up @@ -788,5 +789,33 @@ var UTIL = require('../../lib/util');
ASSERT.equal(pem, _pem.signedDataWithAttrs1949GeneralizedTime);
});

it('should create PKCS#7 SignedData with custom message-digest',
function() {
var p7 = PKCS7.createSignedData();
var messageDigest = SHA256.create().update('To be signed.', 'utf8').digest();

p7.addCertificate(_pem.certificate);
p7.addSigner({
key: PKI.privateKeyFromPem(_pem.privateKey),
certificate: _pem.certificate,
digestAlgorithm: PKI.oids.sha256,
authenticatedAttributes: [{
type: forge.pki.oids.contentType,
value: forge.pki.oids.data
}, {
type: forge.pki.oids.messageDigest,
value: messageDigest
}, {
type: forge.pki.oids.signingTime,
// will be encoded as UTC time because it's >= 1950
value: new Date('1950-01-01T00:00:00Z')
}]
});
p7.sign({detached: true});

var pem = PKCS7.messageToPem(p7);
ASSERT.equal(pem, _pem.detachedSignature);
});

});
})();