From a05b96ac237f7fc7f0c680f6d6d325635b2ceb76 Mon Sep 17 00:00:00 2001 From: Damyan Mitev <damyan.mitev@vereign.com> Date: Tue, 10 Dec 2019 01:13:49 +0200 Subject: [PATCH] add validateVMime, minor changes to signVCard --- javascript/src/iframe/viamapi-iframe.js | 130 +++++++++------------ javascript/src/utilities/emailUtilities.js | 28 +++++ 2 files changed, 80 insertions(+), 78 deletions(-) diff --git a/javascript/src/iframe/viamapi-iframe.js b/javascript/src/iframe/viamapi-iframe.js index 2c94611..48e2ff4 100644 --- a/javascript/src/iframe/viamapi-iframe.js +++ b/javascript/src/iframe/viamapi-iframe.js @@ -1,4 +1,7 @@ -import { parseSMIME } from "../utilities/emailUtilities"; +import { + parseSMIME, + prepareVCardParts +} from "../utilities/emailUtilities"; import { stringToUtf8ByteArray, utf8ByteArrayToString, @@ -1406,17 +1409,17 @@ const connection = Penpal.connectToParent({ return encodeResponse("200", "", "Document signed"); }, - // passportUUID - passport to sign the vCard - // text, html - the text and html part of the email - // related, attachments - array of objects, containing hashes of images/objects, related to the html in format: + // passportUUID - String - passport to sign the vCard + // text, html - String - the text and html part of the email, both optional + // parts - array of objects, representing the MIME structure in format: // { // headers: { - // "Content-Type": "application/hash; algorithm=SHA-256", - // "Original-Content-Type": "image/jpeg", //original content type - // "Content-Disposition": "inline" or "attachment", - // ... //other headers + // "Content-Type": "image/jpeg", + // "Content-Disposition": "inline" or "attachment" with additional attributes, + // ... //other headers from MIME // }, - // body: "base64 encoded hash" + // body: String if it is a text part (Content-Type = "text/...") or Uint8Array otherwise; filled for leaf MIME nodes + // parts: array of instances of the same object; filled for container MIME nodes (Content-Type = "multipart/...") // } signVCard: async (passportUUID, text, html, parts = null) => { const authenticationPublicKey = localStorage.getItem( @@ -1431,6 +1434,13 @@ const connection = Penpal.connectToParent({ return encodeResponse("400", "", "Identity not authenticated"); } + const messageUUID = makeid(); + + const vCardAttribs = { + passportUUID: passportUUID, + messageUUID: messageUUID + }; + let vCardImageData; let vCardImageClaimValue; @@ -1454,7 +1464,8 @@ const connection = Penpal.connectToParent({ vCardImageClaimValue = vCardClaimResponse.data; } - var coordinates = {fromL: -1, fromR:-1, toL: -1, toR: -1} + let qrCodeImageData; + let qrCodeCoordinates = {fromL: -1, fromR:-1, toL: -1, toR: -1}; if (vCardImageClaimValue && "state" in vCardImageClaimValue && vCardImageClaimValue.state === "disabled") { vCardImageData = new ImageData({ @@ -1480,21 +1491,16 @@ const connection = Penpal.connectToParent({ return encodeResponse("400", "", "Content type of vCard mmust be 'image/png'"); } - coordinates = vCardImageResponse.data.QRCodeCoordinates + qrCodeCoordinates = vCardImageResponse.data.QRCodeCoordinates; + const qrCodeBase64Content = await generateQrCode("https://" + location.host + "/check/" + messageUUID); + qrCodeImageData = new ImageData( + { + contentType: "image/png", + content: qrCodeBase64Content + } + ); } - var messageUUID = makeid() - - var qrCodeBase64Content = await generateQrCode("https://" + location.host + "/check/" + messageUUID) - - var qrCode = new ImageData( - { - contentType: "image/png", - content: qrCodeBase64Content, - } - ) - - if (!parts) { parts = []; } @@ -1504,7 +1510,7 @@ const connection = Penpal.connectToParent({ headers: { "Content-Type": "text/html" }, - body: stringToUtf8Base64(html) + body: html }; parts.unshift(htmlPart); } @@ -1514,11 +1520,13 @@ const connection = Penpal.connectToParent({ headers: { "Content-Type": "text/plain" }, - body: stringToUtf8Base64(text) + body: text }; parts.unshift(textPart); } + prepareVCardParts(parts); + const certResponse = await getCertificateForPassport(passportUUID, true); if (certResponse.code !== "200") { @@ -1550,8 +1558,8 @@ const connection = Penpal.connectToParent({ passportChain.reverse(); - console.log(qrCode); - console.log(coordinates); + console.log(qrCodeImageData); + console.log(qrCodeCoordinates); const signVCardResponse = await executeRestfulFunction( "private", @@ -1562,8 +1570,9 @@ const connection = Penpal.connectToParent({ privateKeyOneTime, passportChain, parts, - qrCode, - coordinates, + vCardAttribs, + qrCodeImageData, + qrCodeCoordinates, ); if (signVCardResponse.code !== "200") { return encodeResponse("400", "", signVCardResponse.status); @@ -1572,25 +1581,16 @@ const connection = Penpal.connectToParent({ const signedVCardImageData = new ImageData(signVCardResponse.data); return encodeResponse("200", { image: signedVCardImageData, - messageUUID: messageUUID, + messageUUID: messageUUID }, "vCard signed"); }, - // vCardImageData = { - // contentType: "image/png", - // contentBase64: base 64 encoded image - // }; - // text, html - the text and html part of the email - // related, attachments - array of objects, containing hashes of images/objects, related to the html in format: + // mime - String - the MIME of the email message + // vCardAttribs - optional attributes for the verification procedure in format // { - // headers: { - // "Content-Type": "application/hash; algorithm=SHA-256", - // "Original-Content-Type": "image/jpeg", //original content type - // "Content-Disposition": "inline" or "attachment", - // ... //other headers - // }, - // body: "base64 encoded hash" - // } - validateVCard: async (vCardImageData, text, html, parts = null) => { + // passportUUID: passportUUID, + // messageUUID: messageUUID + // }; + validateVMime: async (mime, vCardAttribs = null) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -1603,47 +1603,21 @@ const connection = Penpal.connectToParent({ return encodeResponse("400", "", "Identity not authenticated"); } - //vCardImageData = new ImageData(vCardImageData); - - if (!parts) { - parts = []; - } - - if (html) { - const htmlPart = { - headers: { - "Content-Type": "text/html" - }, - body: stringToUtf8Base64(html) - }; - parts.unshift(htmlPart); - } - - if (text) { - const textPart = { - headers: { - "Content-Type": "text/plain" - }, - body: stringToUtf8Base64(text) - }; - parts.unshift(textPart); - } - - - const validateVCardResponse = await executeRestfulFunction( + const validateVMimeResponse = await executeRestfulFunction( "private", window.viamApi, - window.viamApi.signValidateVCard, + window.viamApi.signValidateVMime, null, - parts + mime, + vCardAttribs ); - if (validateVCardResponse.code !== "200") { - return encodeResponse("400", "", validateVCardResponse.status); + if (validateVMimeResponse.code !== "200") { + return encodeResponse("400", "", validateVMimeResponse.status); } //TODO - what will be the response? - const signedVCardImageData = new ImageData(validateVCardResponse.data); + const signedVCardImageData = new ImageData(validateVMimeResponse.data); return encodeResponse("200", signedVCardImageData, "vCard signed"); }, generateQrCode, diff --git a/javascript/src/utilities/emailUtilities.js b/javascript/src/utilities/emailUtilities.js index 6cade6b..b1aae25 100644 --- a/javascript/src/utilities/emailUtilities.js +++ b/javascript/src/utilities/emailUtilities.js @@ -15,6 +15,10 @@ import { getCertificateChain, parseSignedData } from "./signingUtilities"; +import { + byteArrayToBase64, + stringToUtf8Base64 +} from "./stringUtilities"; export const SIGNATURE_CONTENT_TYPE = "application/pkcs7-signature"; export const DEFAULT_ATTACHMENT_NAME = "attachment"; @@ -131,3 +135,27 @@ export const extractHtmlBodyFromString = string => { .replace(/<!--[\s\S]*?-->/gm, "") .trim(); }; + +export const prepareVCardParts = parts => { + if (!parts) { + return; + } + for (const part of parts) { + if (part.body) { + if (part.body instanceof String) { + part.body = stringToUtf8Base64(part.body); + } else + if (part.body instanceof Uint8Array) { + part.body = byteArrayToBase64(part.body); + } else + if (part.body instanceof ArrayBuffer) { + part.body = byteArrayToBase64(new Uint8Array(part.body)); + } else { + throw new Error('part body is neither string, nor Uint8Array, nor ArrayBuffer'); + } + } + if (part.parts) { + prepareVCardParts(part.parts); + } + } +}; -- GitLab