diff --git a/index.js b/index.js index 797e52e..b3e98f0 100644 --- a/index.js +++ b/index.js @@ -330,10 +330,10 @@ class Pass { return bundleCallback(null); }); } - ], function _composeStream() { + ], () => { archive.append(JSON.stringify(manifest), { name: "manifest.json" }); - let signatureBuffer = createSignature(manifest); + let signatureBuffer = this._sign(manifest); archive.append(signatureBuffer, { name: "signature" }); let passStream = new stream.PassThrough(); @@ -349,6 +349,67 @@ class Pass { }); }); } + + /** + Generates the PKCS #7 cryptografic signature for the manifest file. + + @method _sign + @params {String|Object} manifest - Manifest content. + @returns {Object} Promise + */ + + _sign(manifest) { + let signature = forge.pkcs7.createSignedData(); + + if (typeof manifest === "object") { + signature.content = forge.util.createBuffer(JSON.stringify(manifest), "utf8") + } else if (typeof manifest === "string") { + signature.content = manifest; + } else { + throw new Error(`Manifest content must be a string or an object. Unable to accept manifest of type ${typeof manifest}`); + } + + signature.addCertificate(Certificates.wwdr); + signature.addCertificate(Certificates.signerCert); + + signature.addSigner({ + key: Certificates.signerKey, + certificate: Certificates.signerCert, + digestAlgorithm: forge.pki.oids.sha1, + authenticatedAttributes: [{ + type: forge.pki.oids.contentType, + value: forge.pki.oids.data + }, { + type: forge.pki.oids.messageDigest, + }, { + // the value is autogenerated + type: forge.pki.oids.signingTime, + }] + }); + + signature.sign(); + + /* + * Signing creates in contentInfo a JSON object nested BER/TLV (X.690 standard) structure. + * Each object represents a component of ASN.1 (Abstract Syntax Notation) + * For a more complete reference, refer to: https://en.wikipedia.org/wiki/X.690#BER_encoding + * + * signature.contentInfo.type => SEQUENCE OF (16) + * signature.contentInfo.value[0].type => OBJECT IDENTIFIER (6) + * signature.contantInfo.value[1].type => END OF CONTENT (EOC - 0) + * + * EOC are only present only in constructed indefinite-length methods + * Since `signature.contentInfo.value[1].value` contains an object whose value contains the content we passed, + * we have to pop the whole object away to avoid signature content invalidation. + * + */ + signature.contentInfo.value.pop(); + + // Converting the JSON Structure into a DER (which is a subset of BER), ASN.1 valid structure + // Returning the buffer of the signature + + return Buffer.from(forge.asn1.toDer(signature.toAsn1()).getBytes(), 'binary'); + } } @@ -404,68 +465,6 @@ function loadConfiguration(setup) { }); } -/** - Generates the PKCS #7 cryptografic signature for the manifest file. - - @function createSignature - @params {String} manifestPath - temp dir path created to keep the manifest file. - @returns {Object} Promise -*/ - - -function createSignature(manifest) { - let signature = forge.pkcs7.createSignedData(); - - if (typeof manifest === "object") { - signature.content = forge.util.createBuffer(JSON.stringify(manifest), "utf8") - } else if (typeof manifest === "string") { - signature.content = manifest; - } else { - throw new Error(`Manifest content must be a string or an object. Unable to accept manifest of type ${typeof manifest}`); - } - - signature.addCertificate(Certificates.wwdr); - signature.addCertificate(Certificates.signerCert); - - signature.addSigner({ - key: Certificates.signerKey, - certificate: Certificates.signerCert, - digestAlgorithm: forge.pki.oids.sha1, - authenticatedAttributes: [{ - type: forge.pki.oids.contentType, - value: forge.pki.oids.data - }, { - type: forge.pki.oids.messageDigest, - }, { - // the value is autogenerated - type: forge.pki.oids.signingTime, - }] - }); - - signature.sign(); - - /* - * Signing creates in contentInfo a JSON object nested BER/TLV (X.690 standard) structure. - * Each object represents a component of ASN.1 (Abstract Syntax Notation) - * For a more complete reference, refer to: https://en.wikipedia.org/wiki/X.690#BER_encoding - * - * signature.contentInfo.type => SEQUENCE OF (16) - * signature.contentInfo.value[0].type => OBJECT IDENTIFIER (6) - * signature.contantInfo.value[1].type => END OF CONTENT (EOC - 0) - * - * EOC are only present only in constructed indefinite-length methods - * Since `signature.contentInfo.value[1].value` contains an object whose value contains the content we passed, - * we have to pop the whole object away to avoid signature content invalidation. - * - */ - signature.contentInfo.value.pop(); - - // Converting the JSON Structure into a DER (which is a subset of BER), ASN.1 valid structure - // Returning the buffer of the signature - - return Buffer.from(forge.asn1.toDer(signature.toAsn1()).getBytes(), 'binary'); -} - /** Filters the options received in the query from http request into supported options by Apple and this application, based on the functions that can be provided to keys