Added certificates saving in constructor and parsing them when signature is being created; changed Manifest to be exported as a Buffer

This commit is contained in:
Alexander Cerutti
2021-10-03 18:14:10 +02:00
parent cd289ef164
commit e0d2db9fc4
4 changed files with 75 additions and 57 deletions

View File

@@ -167,6 +167,8 @@ export default class PKPass extends Bundle {
);
Object.assign(this[propsSymbol], overridesValidation);
this.certificates = certificates;
}
/**
@@ -491,8 +493,8 @@ export default class PKPass extends Bundle {
}
}
private [createManifestSymbol]() {
return Object.entries(this[filesSymbol]).reduce<{
private [createManifestSymbol](): Buffer {
const manifest = Object.entries(this[filesSymbol]).reduce<{
[key: string]: string;
}>((acc, [fileName, buffer]) => {
const hashFlow = forge.md.sha1.create();
@@ -504,6 +506,8 @@ export default class PKPass extends Bundle {
[fileName]: hashFlow.digest().toHex(),
};
}, {});
return Buffer.from(JSON.stringify(manifest));
}
private [closePassSymbol]() {
@@ -576,10 +580,13 @@ export default class PKPass extends Bundle {
}
}
const manifest = this[createManifestSymbol]();
super.addBuffer("manifest.json", Buffer.from(JSON.stringify(manifest)));
const manifestBuffer = this[createManifestSymbol]();
super.addBuffer("manifest.json", manifestBuffer);
const signatureBuffer = Signature.create(manifest, this.certificates);
const signatureBuffer = Signature.create(
manifestBuffer,
this.certificates,
);
super.addBuffer("signature", signatureBuffer);
}

View File

@@ -0,0 +1,18 @@
import type forge from "node-forge";
import Joi from "joi";
export interface CertificatesSchema {
wwdr: string | Buffer;
signerCert: string | Buffer;
signerKey: string | Buffer;
signerKeyPassphrase?: string;
}
export const CertificatesSchema = Joi.object<CertificatesSchema>()
.keys({
wwdr: Joi.alternatives(Joi.binary(), Joi.string()).required(),
signerCert: Joi.alternatives(Joi.binary(), Joi.string()).required(),
signerKey: Joi.alternatives(Joi.binary(), Joi.string()).required(),
signerKeyPassphrase: Joi.string(),
})
.required();

View File

@@ -6,6 +6,7 @@ export * from "./NFC";
export * from "./SemanticTags";
export * from "./PassFields";
export * from "./Personalize";
export * from "./Certificates";
import Joi from "joi";
import debug from "debug";
@@ -18,6 +19,7 @@ import { Field } from "./PassFieldContent";
import { PassFields, TransitType } from "./PassFields";
import { Personalization } from "./Personalize";
import { Semantics } from "./SemanticTags";
import { CertificatesSchema } from "./Certificates";
const schemaDebug = debug("Schema");
@@ -25,33 +27,6 @@ export interface FileBuffers {
[key: string]: Buffer;
}
/* export interface Certificates {
wwdr?: string;
signerCert?: string;
signerKey?:
| {
keyFile: string;
passphrase?: string;
}
| string;
}*/
export interface CertificatesSchema {
wwdr: string | Buffer;
signerCert: string | Buffer;
signerKey: string | Buffer;
signerKeyPassphrase?: string;
}
export const CertificatesSchema = Joi.object<CertificatesSchema>()
.keys({
wwdr: Joi.alternatives(Joi.binary(), Joi.string()).required(),
signerCert: Joi.alternatives(Joi.binary(), Joi.string()).required(),
signerKey: Joi.alternatives(Joi.binary(), Joi.string()).required(),
signerKeyPassphrase: Joi.string(),
})
.required();
export interface PassProps {
serialNumber?: string;
description?: string;
@@ -206,12 +181,6 @@ type AvailableSchemas =
| typeof CertificatesSchema
| typeof OverridablePassProps;
export type ArrayPassSchema = Beacon | Location | Barcode;
/* function resolveSchemaName(name: Schema) {
return schemas[name] || undefined;
}
*/
/**
* Checks if the passed options are compliant with the indicated schema
* @param {any} opts - options to be checks

View File

@@ -5,33 +5,25 @@ import type * as Schemas from "./schemas";
* Generates the PKCS #7 cryptografic signature for the manifest file.
*
* @method create
* @params manifest - Manifest content.
* @params manifest
* @params certificates
* @returns
*/
export function create(
manifest: { [key: string]: string },
manifestBuffer: Buffer,
certificates: Schemas.CertificatesSchema,
): Buffer {
const signature = forge.pkcs7.createSignedData();
signature.content = forge.util.createBuffer(
JSON.stringify(manifest),
"utf8",
signature.content = forge.util.createBuffer(manifestBuffer.buffer, "utf8");
const { wwdr, signerCert, signerKey } = parseCertificates(
getStringCertificates(certificates),
);
const { wwdr, signerCert, signerKey, signerKeyPassphrase } = certificates;
const wwdrString = wwdr instanceof Buffer ? wwdr.toString("utf-8") : wwdr;
const signerCertString =
signerCert instanceof Buffer
? signerCert.toString("utf-8")
: signerCert;
const signerKeyString =
signerKey instanceof Buffer ? signerKey.toString("utf-8") : signerKey;
signature.addCertificate(wwdrString);
signature.addCertificate(signerCertString);
signature.addCertificate(wwdr);
signature.addCertificate(signerCert);
/**
* authenticatedAttributes belong to PKCS#9 standard.
@@ -43,8 +35,8 @@ export function create(
*/
signature.addSigner({
key: signerKeyString,
certificate: signerCertString,
key: signerKey,
certificate: signerCert,
digestAlgorithm: forge.pki.oids.sha1,
authenticatedAttributes: [
{
@@ -86,3 +78,35 @@ export function create(
"binary",
);
}
/**
* Parses the PEM-formatted passed text (certificates)
*
* @param element - Text content of .pem files
* @param passphrase - passphrase for the key
* @returns The parsed certificate or key in node forge format
*/
function parseCertificates(certificates: Schemas.CertificatesSchema) {
const { signerCert, signerKey, wwdr, signerKeyPassphrase } = certificates;
return {
signerCert: forge.pki.certificateFromPem(signerCert.toString("utf-8")),
wwdr: forge.pki.certificateFromPem(wwdr.toString("utf-8")),
signerKey: forge.pki.decryptRsaPrivateKey(
signerKey.toString("utf-8"),
signerKeyPassphrase,
),
};
}
function getStringCertificates(
certificates: Schemas.CertificatesSchema,
): Record<keyof Schemas.CertificatesSchema, string> {
return {
signerKeyPassphrase: certificates.signerKeyPassphrase,
wwdr: Buffer.from(certificates.wwdr).toString("utf-8"),
signerCert: Buffer.from(certificates.wwdr).toString("utf-8"),
signerKey: Buffer.from(certificates.wwdr).toString("utf-8"),
};
}