-
Markin Igor authoredMarkin Igor authored
viamapi-iframe.js 86.33 KiB
const libmime = require('libmime');
const QRCode = require('qrcode');
const pkijs = require('pkijs');
const asn1js = require('asn1js');
const pvutils = require('pvutils');
const Penpal = require('penpal').default;
const penpalMethods = require('../../temp/penpal-methods').default;
const WopiAPI = require('./wopiapi-iframe');
const ViamAPI = require('../../temp/viamapi');
//*********************************************************************************
const CERTIFIATE_Version_1 = 0;
const CERTIFIATE_Version_3 = 2;
//these bit fields are reversed, WTF!
const KEY_USAGE_DigitalSignature = 0x80;//01;
const KEY_USAGE_NonRepudiation = 0x40;//02;
const KEY_USAGE_KeyEncipherment = 0x20;//04;
const KEY_USAGE_DataEncipherment = 0x10;//08;
const KEY_USAGE_KeyAgreement = 0x08;//10;
const KEY_USAGE_KeyCertSign = 0x04;//20;
const KEY_USAGE_CRLSign = 0x02;//40;
//const KEY_USAGE_EncipherOnly = 0x01;//80; // Not used for now. Must be used together with KEY_USAGE_KeyAgreement (maybe should be ORed as a constant directly?)
//const KEY_USAGE_DecipherOnly = 0x80;//0100; // If used, modify "KeyUsage" extension array buffer size and appropriate bit operators to accomodate for extra byte
const KEY_USAGE_LeafCertificate = KEY_USAGE_DigitalSignature | KEY_USAGE_NonRepudiation | KEY_USAGE_KeyEncipherment | KEY_USAGE_DataEncipherment;
const KEY_USAGE_CertificateAuthority= KEY_USAGE_DigitalSignature | KEY_USAGE_KeyCertSign | KEY_USAGE_CRLSign;
const OID_EXT_KEY_USAGE_Any = "2.5.29.37.0";
const OID_ID_PKIX_ServerAuth = "1.3.6.1.5.5.7.3.1";
const OID_ID_PKIX_ClientAuth = "1.3.6.1.5.5.7.3.2";
const OID_ID_PKIX_CodeSigning = "1.3.6.1.5.5.7.3.3";
const OID_ID_PKIX_EmailProtection = "1.3.6.1.5.5.7.3.4";
const OID_ID_PKIX_TimeStamping = "1.3.6.1.5.5.7.3.8";
const OID_ID_PKIX_OCSPSigning = "1.3.6.1.5.5.7.3.9";
// const OID_EXT_KEY_USAGE_MS... = "1.3.6.1.4.1.311.10.3.1"; // Microsoft Certificate Trust List signing
// const OID_EXT_KEY_USAGE_MS... = "1.3.6.1.4.1.311.10.3.4"; // Microsoft Encrypted File System
const OID_PKCS7_Data = "1.2.840.113549.1.7.1";
const OID_PKCS7_SignedData = "1.2.840.113549.1.7.2";
const OID_PKCS7_EnvelopedData = "1.2.840.113549.1.7.3";
const OID_PKCS9_EmailAddress = "1.2.840.113549.1.9.1";
const OID_PKCS9_ContentType = "1.2.840.113549.1.9.3";
const OID_PKCS9_MessageDigest = "1.2.840.113549.1.9.4";
const OID_PKCS9_SigningTime = "1.2.840.113549.1.9.5";
const defaultAlgorithms = {
hashAlg: "SHA-256",
signAlg: "RSASSA-PKCS1-v1_5",
keyLength: 2048
};
const AES_encryptionVariant_Password = 2;
const encryptionAlgorithm = {
name: "AES-CBC",
length: 128
};
//*********************************************************************************
// Returns promise, resolved to keyPair object {publicKey, privateKey}
//*********************************************************************************
function generateKeys(algorithms) {
//region Get a "crypto" extension
const crypto = pkijs.getCrypto();
if (typeof crypto === "undefined") {
return Promise.reject("No WebCrypto extension found");
}
//endregion Get a "crypto" extension
if (!algorithms) {
algorithms = defaultAlgorithms;
} else {
if (!algorithms.hashAlg) {
algorithms.hashAlg = defaultAlgorithms.hashAlg;
}
if (!algorithms.signAlg) {
algorithms.signAlg = defaultAlgorithms.signAlg;
}
if (!algorithms.keyLength) {
algorithms.keyLength = defaultAlgorithms.keyLength;
}
}
//region Get default algorithm parameters for key generation
const algorithm = pkijs.getAlgorithmParameters(algorithms.signAlg, "generatekey");
if("hash" in algorithm.algorithm) {
algorithm.algorithm.hash.name = algorithms.hashAlg;
}
algorithm.algorithm.modulusLength = algorithms.keyLength;
//endregion
return crypto.generateKey(algorithm.algorithm, true, algorithm.usages);
}
//*********************************************************************************
function createCertificate(certData, issuerData = null)
{
if (typeof certData === "undefined") {
return Promise.reject("No Certificate data provided");
}
if (typeof certData.subject === "undefined") {
return Promise.reject("No Certificate subject data provided");
}
//region Get a "crypto" extension
const crypto = pkijs.getCrypto();
if (typeof crypto === "undefined") {
return Promise.reject("No WebCrypto extension found");
}
//endregion Get a "crypto" extension
//region Initial variables
let sequence = Promise.resolve();
const certificate = new pkijs.Certificate();
let publicKey;
let privateKey;
let certificateBuffer;// = new ArrayBuffer(0); // ArrayBuffer with loaded or created CERT
let privateKeyBuffer;// = new ArrayBuffer(0);
let publicKeyBuffer;// = new ArrayBuffer(0);
//endregion Initial variables
if (certData.keyPair) {
//region Create a new key pair
sequence = sequence.then(() =>
{
return certData.keyPair;
});
//endregion Create a new key pair
} else {
//region Create a new key pair
sequence = sequence.then(() =>
{
return generateKeys(certData.algorithms);
});
//endregion Create a new key pair
}
//region Store new key in an interim variables
sequence = sequence.then(keyPair =>
{
publicKey = keyPair.publicKey;
privateKey = keyPair.privateKey;
}, error => Promise.reject(`Error during key generation: ${error}`));
//endregion Store new key in an interim variables
//region Exporting public key into "subjectPublicKeyInfo" value of certificate
sequence = sequence.then(() =>
certificate.subjectPublicKeyInfo.importKey(publicKey)
);
//endregion Exporting public key into "subjectPublicKeyInfo" value of certificate
sequence = sequence.then(
() => crypto.digest({ name: "SHA-1" }, certificate.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex),
error => Promise.reject(`Error during importing public key: ${error}`)
);
//region Fill in cert data
sequence = sequence.then(subjKeyIdBuffer =>
{
//region Put a static values
certificate.version = CERTIFIATE_Version_3;
const serialNumberBuffer = new ArrayBuffer(20);
const serialNumberView = new Uint8Array(serialNumberBuffer);
pkijs.getRandomValues(serialNumberView);
// noinspection JSUnresolvedFunction
certificate.serialNumber = new asn1js.Integer({ valueHex: serialNumberView });
//endregion Put a static values
//region Subject
// For reference http://oidref.com/2.5.4.3
if (certData.subject.commonName) {
// noinspection JSUnresolvedFunction
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.3", // Common name
value: new asn1js.PrintableString({ value: certData.subject.commonName })
}));
}
if (certData.subject.country) {
// noinspection JSUnresolvedFunction
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.6", // Country name
value: new asn1js.PrintableString({ value: certData.subject.country })
}));
}
if (certData.subject.locality) {
// noinspection JSUnresolvedFunction
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.7", // Locality Name
value: new asn1js.PrintableString({ value: certData.subject.locality })
}));
}
if (certData.subject.state) {
// noinspection JSUnresolvedFunction
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.8", // State or Province name
value: new asn1js.PrintableString({ value: certData.subject.state })
}));
}
if (certData.subject.organization) {
// noinspection JSUnresolvedFunction
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.10", // Organization name
value: new asn1js.PrintableString({ value: certData.subject.organization })
}));
}
if (certData.subject.organizationUnit) {
// noinspection JSUnresolvedFunction
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.11", // Organization unit name
value: new asn1js.PrintableString({ value: certData.subject.organizationUnit })
}));
}
if (certData.subject.email) {
// noinspection JSUnresolvedFunction
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: OID_PKCS9_EmailAddress, // Email, deprecated but still widely used
value: new asn1js.IA5String({ value: certData.subject.email })
}));
}
//endregion Subject
//region Issuer
if (issuerData && issuerData.certificate) {
certificate.issuer = issuerData.certificate.subject;
} else {
certificate.issuer = certificate.subject;
}
//endregion Issuer
//region Validity
if (!certData.validity) {
certData.validity = {}
}
if (certData.validity.notBefore) {
certificate.notBefore.value = certData.validity.notBefore; //date
} else {
const tmp = new Date();
certificate.notBefore.value = new Date(tmp.getFullYear(), tmp.getMonth(), tmp.getDate(), 0, 0, 0);
}
if (certData.validity.notAfter) {
certificate.notAfter.value = certData.validity.notAfter; //date
} else {
const tmp = certificate.notBefore.value;
const validYears = certData.validity.validYears || 1;
certificate.notAfter.value = new Date(tmp.getFullYear() + validYears, tmp.getMonth(), tmp.getDate(), 23, 59, 59);
}
//endregion Validity
//region Extensions
certificate.extensions = []; // Extensions are not a part of certificate by default, it's an optional array
//region "BasicConstraints" extension
const basicConstr = new pkijs.BasicConstraints({
cA: !!certData.isCA,
//pathLenConstraint: 0 //TODO add logic for leaf CA
});
certificate.extensions.push(new pkijs.Extension({
extnID: "2.5.29.19",
critical: true,
extnValue: basicConstr.toSchema().toBER(false),
parsedValue: basicConstr // Parsed value for well-known extensions
}));
//endregion "BasicConstraints" extension
//region "KeyUsage" extension
const keyUsageBuffer = new ArrayBuffer(1);
const keyUsageBitView = new Uint8Array(keyUsageBuffer);
keyUsageBitView[0] = !!certData.isCA ? KEY_USAGE_CertificateAuthority : KEY_USAGE_LeafCertificate;
// noinspection JSUnresolvedFunction
const keyUsage = new asn1js.BitString({ valueHex: keyUsageBuffer });
certificate.extensions.push(new pkijs.Extension({
extnID: "2.5.29.15",
critical: true,
extnValue: keyUsage.toBER(false),
parsedValue: keyUsage // Parsed value for well-known extensions
}));
//endregion "KeyUsage" extension
//region "ExtKeyUsage" extension
if (!certData.isCA && certData.subject.email) {
const extKeyUsage = new pkijs.ExtKeyUsage({
keyPurposes: [
OID_ID_PKIX_EmailProtection
]
});
certificate.extensions.push(new pkijs.Extension({
extnID: "2.5.29.37",
critical: false,
extnValue: extKeyUsage.toSchema().toBER(false),
parsedValue: extKeyUsage // Parsed value for well-known extensions
}));
}
//endregion "ExtKeyUsage" extension
//region "SubjAltName" extension
if (certData.subject.email || certData.subject.url) {
const names = [];
if (certData.subject.email) {
names.push(new pkijs.GeneralName({
type: 1, // rfc822Name
value: certData.subject.email
}));
}
if (certData.subject.url) {
names.push(new pkijs.GeneralName({
type: 2, // dNSName
value: certData.subject.url
}));
}
const subjAltNames = new pkijs.GeneralNames({
names: names
});
certificate.extensions.push(new pkijs.Extension({
extnID: "2.5.29.17",
critical: false,
extnValue: subjAltNames.toSchema().toBER(false),
parsedValue: subjAltNames // Parsed value for well-known extensions
}));
}
//endregion "SubjAltName" extension
//region "SubjectKeyIdentifier" extension
const subjKeyId = new asn1js.OctetString({ valueHex: subjKeyIdBuffer });
certificate.extensions.push(new pkijs.Extension({
extnID: "2.5.29.14",
critical: false,
extnValue: subjKeyId.toBER(false),
parsedValue: subjKeyId // Parsed value for well-known extensions
}));
//endregion "SubjectKeyIdentifier" extension
/* COULD NOT GET IT WORKING
//region "AuthorityKeyIdentifier" extension
if (issuerData && issuerData.certificate) {
let issuerSubjKeyExt = null;
let extLength = issuerData.certificate.extensions.length;
for (var i = 0; i < extLength; i++) {
let ext = issuerData.certificate.extensions[i];
if (ext.extnID == "2.5.29.14") {
issuerSubjKeyExt = ext;
break;
}
}
if (issuerSubjKeyExt) {
const asn1 = asn1js.fromBER(issuerSubjKeyExt.extnValue);
const authKeyIdentifier = new AuthorityKeyIdentifier({
keyIdentifier: new asn1js.OctetString({
//isHexOnly: true,
//valueHex: issuerSubjKeyExt.parsedValue.valueBlock.valueHex
value: new asn1js.OctetString({ valueHex: subjKeyIdBuffer })
})
});
// const authKeyIdentifier = new AuthorityKeyIdentifier({
// //keyIdentifier: new asn1js.OctetString({ valueHex: subjKeyIdBuffer })
// });
certificate.extensions.push(new Extension({
extnID: "2.5.29.35",
critical: false,
extnValue: authKeyIdentifier.toSchema().toBER(false),
parsedValue: authKeyIdentifier // Parsed value for well-known extensions
}));
}
}
//endregion "AuthorityKeyIdentifier" extension
*/
//endregion Extensions
});
//region Fill in cert data
//region Signing final certificate
sequence = sequence.then(() => {
let signerKey = (issuerData && issuerData.privateKey) ? issuerData.privateKey : privateKey;
//console.log(signerKey)
return certificate.sign(signerKey, (certData.algorithms && certData.algorithms.hashAlg) ? certData.algorithms.hashAlg : defaultAlgorithms.hashAlg)
},
error => Promise.reject(`Error during exporting public key: ${error}`));
//endregion
//region Encode and store certificate
sequence = sequence.then(() =>
{
//console.log(certificate)
certificateBuffer = certificate.toSchema(true).toBER(false);
}, error => Promise.reject(`Error during signing: ${error}`));
//endregion
//region Exporting public key
sequence = sequence.then(() =>
crypto.exportKey("spki", publicKey)
);
//endregion
//region Store exported public key on Web page
sequence = sequence.then(result =>
{
publicKeyBuffer = result;
}, error => Promise.reject(`Error during exporting of public key: ${error}`));
//endregion
//region Exporting private key
sequence = sequence.then(() =>
crypto.exportKey("pkcs8", privateKey)
);
//endregion
//region Store exported key on Web page
sequence = sequence.then(result =>
{
privateKeyBuffer = result;
}, error => Promise.reject(`Error during exporting of private key: ${error}`));
//endregion
return sequence.then(() => {
const result = {
certificate: certificate,
certificatePEM: encodePEM(certificateBuffer, "CERTIFICATE"),
publicKey: publicKey,
publicKeyPEM: encodePEM(publicKeyBuffer, "PUBLIC KEY"),
privateKey: privateKey,
privateKeyPEM: encodePEM(privateKeyBuffer, "PRIVATE KEY")
};
return result;
});
}
function formatPEM(pemString) {
const lineWidth = 64;
let resultString = "";
let start = 0;
let piece = "";
while ( (piece = pemString.substring(start, start + lineWidth)).length > 0 ) {
start += lineWidth;
resultString += piece + '\r\n'
}
return resultString;
}
function encodePEM(buffer, label) {
const bufferString = String.fromCharCode.apply(null, new Uint8Array(buffer));
const header = `-----BEGIN ${label}-----\r\n`;
const base64formatted = formatPEM(window.btoa(bufferString));
const footer = `-----END ${label}-----\r\n`;
const resultString = header + base64formatted + footer;
return resultString;
}
function decodePEM(pemString) {
const pemStripped = pemString.replace(/(-----(BEGIN|END) [a-zA-Z ]*-----|\r|\n)/g, '');
const pemDecoded = window.atob(pemStripped);
const buffer = pvutils.stringToArrayBuffer(pemDecoded);
return buffer;
}
//*********************************************************************************
function parseCertificate(certificatePEM) {
const certificateBuffer = decodePEM(certificatePEM);
const asn1 = asn1js.fromBER(certificateBuffer);
const certificate = new pkijs.Certificate({ schema: asn1.result });
return certificate;
}
//*********************************************************************************
function parsePublicKey(publicKeyPEM) {
const publicKeyBuffer = decodePEM(publicKeyPEM);
const crypto = pkijs.getCrypto();
const publicKeyPromise = crypto.importKey(
"spki",
publicKeyBuffer,
{ //these are the algorithm options
name: "RSASSA-PKCS1-v1_5",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
true,
["verify"]
);
return publicKeyPromise;
}
//*********************************************************************************
function encryptMessage(message, password, label) {
const buffer = pvutils.stringToArrayBuffer(message);
const secret = pvutils.stringToArrayBuffer(password);
const enveloped = new pkijs.EnvelopedData();
enveloped.addRecipientByPreDefinedData(secret, {}, AES_encryptionVariant_Password);
return enveloped.encrypt(encryptionAlgorithm, buffer).
then(
() => {
const content = new pkijs.ContentInfo();
content.contentType = OID_PKCS7_EnvelopedData;
content.content = enveloped.toSchema();
const ber = content.toSchema().toBER(false);
return encodePEM(ber, label)
},
error => Promise.reject(`encryption error: ${error}`)
)
}
//*********************************************************************************
function decryptMessage(message, password) {
const secret = pvutils.stringToArrayBuffer(password);
const buffer = decodePEM(message);
const asn1 = asn1js.fromBER(buffer);
const content = new pkijs.ContentInfo({schema: asn1.result});
const enveloped = new pkijs.EnvelopedData({schema: content.content});
return enveloped.decrypt(0, {preDefinedData: secret}).then(result => {
return pvutils.arrayBufferToString(result);
}).catch(() => {
throw("Wrong pincode")
})
}
//*********************************************************************************
function parsePrivateKey(privateKeyPEM) {
const privateKeyBuffer = decodePEM(privateKeyPEM);
const crypto = pkijs.getCrypto();
const privateKeyPromise = crypto.importKey(
"pkcs8",
privateKeyBuffer,
{ //these are the algorithm options
name: "RSASSA-PKCS1-v1_5",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
true,
["sign"]
);
return privateKeyPromise;
}
function createPassportCertificate(commonNameArg) {
const certData = {
algorithms: {
hashAlg: "SHA-256",
signAlg: "RSASSA-PKCS1-v1_5",
keyLength: 2048
},
//keyPair: generateKeys(), //optional , if provided must be object or promise that resolves to object {publicKey, prvateKey}. If it is not provided, new ones are generated automatically
subject: {
commonName: commonNameArg + "-userdevice", //optional for leaf, recommended for CA
country: "CH", //optional for leaf, recommended for CA
locality: "Zug", //optional for leaf, recommended for CA
state: "Zug", //optional for leaf, recommended for CA
organization: "Vereign AG", //optional for leaf, recommended for CA
organizationUnit:"Business Dep", //optional for leaf, recommended for CA
//email: "damyan.mitev@vereign.com", // added to DN and Subject Alternative Name extension. Optional for CA. Mandatory for leaf certificate, used for email protection
//url: "www.vereign.com" // optional url, recommended for CA, added to Subject Alternative Name extension
},
validity: {
//notBefore: new Date() // optional, defaults to today at 00:00:00
//notAfter: new Date() // optional, defaults to notBefore + validYears at 23:59:59
validYears: 5 //optional, defaults to 1
},
isCA: true // optional flag denoting if this is CA certificate or leaf certificate, defaults to false
};
return createCertificate(certData, null)
}
function createOneTimePassportCertificate(commonNameArg, emailArg, privateKeyIssuerArg, certicateIssuerArg) {
var certData = null;
if(emailArg != null && emailArg !== "") {
certData = {
algorithms: {
hashAlg: "SHA-256",
signAlg: "RSASSA-PKCS1-v1_5",
keyLength: 2048
},
//keyPair: generateKeys(), //optional , if provided must be object or promise that resolves to object {publicKey, prvateKey}. If it is not provided, new ones are generated automatically
subject: {
commonName: commonNameArg + "-onetime", //optional for leaf, recommended for CA
country: "CH", //optional for leaf, recommended for CA
locality: "Zug", //optional for leaf, recommended for CA
state: "Zug", //optional for leaf, recommended for CA
organization: "Vereign AG", //optional for leaf, recommended for CA
organizationUnit:"Business Dep", //optional for leaf, recommended for CA
email: emailArg, // added to DN and Subject Alternative Name extension. Optional for CA. Mandatory for leaf certificate, used for email protection
//url: "www.vereign.com" // optional url, recommended for CA, added to Subject Alternative Name extension
},
validity: {
//notBefore: new Date() // optional, defaults to today at 00:00:00
//notAfter: new Date() // optional, defaults to notBefore + validYears at 23:59:59
validYears: 5 //optional, defaults to 1
},
isCA: false // optional flag denoting if this is CA certificate or leaf certificate, defaults to false
}
} else {
certData = {
algorithms: {
hashAlg: "SHA-256",
signAlg: "RSASSA-PKCS1-v1_5",
keyLength: 2048
},
//keyPair: generateKeys(), //optional , if provided must be object or promise that resolves to object {publicKey, prvateKey}. If it is not provided, new ones are generated automatically
subject: {
commonName: commonNameArg + "-onetime", //optional for leaf, recommended for CA
country: "CH", //optional for leaf, recommended for CA
locality: "Zug", //optional for leaf, recommended for CA
state: "Zug", //optional for leaf, recommended for CA
organization: "Vereign AG", //optional for leaf, recommended for CA
organizationUnit:"Business Dep", //optional for leaf, recommended for CA
//email: emailArg, // added to DN and Subject Alternative Name extension. Optional for CA. Mandatory for leaf certificate, used for email protection
//url: "www.vereign.com" // optional url, recommended for CA, added to Subject Alternative Name extension
},
validity: {
//notBefore: new Date() // optional, defaults to today at 00:00:00
//notAfter: new Date() // optional, defaults to notBefore + validYears at 23:59:59
validYears: 5 //optional, defaults to 1
},
isCA: false // optional flag denoting if this is CA certificate or leaf certificate, defaults to false
}
}
return parsePrivateKey(privateKeyIssuerArg).then(privateKeyDecoded => {
const issuerData = {
certificate: parseCertificate(certicateIssuerArg),// vereignCACertPEM),
privateKey: privateKeyDecoded
};
return createCertificate(certData, issuerData);
//console.log(vereignIntermediateKey)
});
}
function download(filename, contentType, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:' + contentType + ';charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function arrayBufferToBase64Formatted(buffer) {
const bufferString = String.fromCharCode.apply(null, new Uint8Array(buffer));
const base64formatted = formatPEM(window.btoa(bufferString));
return base64formatted;
}
function arrayBufferToBase64(buffer) {
const bufferString = String.fromCharCode.apply(null, new Uint8Array(buffer));
const base64 = window.btoa(bufferString);
return base64;
}
const newline = /\r\n|\r|\n/g;
function capitalizeFirstLetter(string) {
if(string === "id") {
return "ID"
}
if(string === "mime") {
return "MIME";
}
return string.charAt(0).toUpperCase() + string.slice(1);
}
function capitalizeHeader(string) {
result = "";
tokens = string.split("-");
for(var i = 0; i < tokens.length; i++) {
result += capitalizeFirstLetter(tokens[i]);
if(i !== tokens.length - 1) {
result += "-"
}
}
return result
}
function signEmail(mime, signingCert, certificateChain, privateKey) {
signingCertObj = parseCertificate(signingCert);
certificateChainObj = [];
certificateChainObj[0] = parseCertificate(signingCert);
for(var i = 0; i < certificateChain.length; i++) {
certificateChainObj[i + 1] = parseCertificate(certificateChain[i])
}
//console.log(certificateChainObj)
return parsePrivateKey(privateKey).then(privateKeyDecoded => {
return signEmailObjects(mime, signingCertObj, certificateChainObj, privateKeyDecoded);
//console.log(vereignIntermediateKey)
});
}
function signEmailObjects(mime, signingCert, certificateChain, privateKey) {
//region Get a "crypto" extension
const crypto = pkijs.getCrypto();
if (typeof crypto === "undefined") {
return Promise.reject("No WebCrypto extension found");
}
//endregion Get a "crypto" extension
let template =
`{{headers}}Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="{{boundary}}"
MIME-Version: 1.0
This is a cryptographically signed message in MIME format.
--{{boundary}}
{{mime}}
--{{boundary}}
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Description: S/MIME Cryptographic Signature
{{signature}}
--{{boundary}}--
Vereign - Authentic Communication
`.replace(newline, '\r\n');
const detachedSignature = true;
const addExt = true;
const hashAlg = "SHA-256";
let cmsSignedSimpl;
var mimeHeadersTitles = [
"Content-Type",
"Content-Transfer-Encoding",
"Content-ID",
"Content-Description",
"Content-Disposition",
"Content-Language",
"Content-Location"
];
mime = mime.replace(newline, '\r\n');
let newHeaderLines = "";
let headersEnd = mime.indexOf('\r\n\r\n'); //the first empty line
if (headersEnd < 0 && mime.startsWith('\r\n')) {
mime = mime.substring(2) //should not happen
} else
if (headersEnd >= 0) {
let mimeHeaders = {};
let mimeBody = mime.substring(headersEnd + 4);
let mimeHeadersStr = mime.substring(0, headersEnd);
let headers = libmime.decodeHeaders(mimeHeadersStr);
for (var i = 0; i < mimeHeadersTitles.length; i++) {
let key = mimeHeadersTitles[i].toLowerCase();
if(key in headers) {
mimeHeaders[key] = headers[key];
delete headers[key]
}
}
for(let key in headers) {
if(!(key === "" || key === "MIME-Version".toLowerCase())) { //we have MIME-Version in the template
newHeaderLines += capitalizeHeader(key) + ": " + headers[key] + '\r\n';
}
}
let newMimeHeaderLines = "";
for(let key in mimeHeaders) {
if(!(key === "")) {
newMimeHeaderLines += capitalizeHeader(key) + ": " + mimeHeaders[key] + '\r\n';
}
}
if (newMimeHeaderLines === "") {
newMimeHeaderLines = 'Content-Type: text/plain\r\n' //should not happen
}
mime = newMimeHeaderLines + '\r\n' + mimeBody
}
let dataBuffer = Buffer.from(mime,'utf-8');
let sequence = Promise.resolve();
//region Check if user wants us to include signed extensions
if(addExt)
{
//region Create a message digest
sequence = sequence.then(
() => crypto.digest({ name: hashAlg }, dataBuffer)
);
//endregion
//region Combine all signed extensions
sequence = sequence.then(
messageHash =>
{
const signedAttr = [];
/*
1.2.840.113549.1.9.1 - e-mailAddress
1.2.840.113549.1.9.2 - PKCS-9 unstructuredName
1.2.840.113549.1.9.3 - contentType
1.2.840.113549.1.9.4 - messageDigest
1.2.840.113549.1.9.5 - Signing Time
1.2.840.113549.1.9.6 - counterSignature
*/
signedAttr.push(new pkijs.Attribute({
type: OID_PKCS9_ContentType, //contentType
values: [
new asn1js.ObjectIdentifier({ value: OID_PKCS7_Data}) //data
]
/*
1.2.840.113549.1.7.1 - data
1.2.840.113549.1.7.2 - signedData
1.2.840.113549.1.7.3 - envelopedData
1.2.840.113549.1.7.4 - signedAndEnvelopedData
1.2.840.113549.1.7.5 - digestedData
1.2.840.113549.1.7.6 - encryptedData
*/
})); // contentType
signedAttr.push(new pkijs.Attribute({
type: OID_PKCS9_SigningTime, //Signing Time
values: [
new asn1js.UTCTime({ valueDate: new Date() })
]
})); // signingTime
signedAttr.push(new pkijs.Attribute({
type: OID_PKCS9_MessageDigest, //messageDigest
values: [
new asn1js.OctetString({ valueHex: messageHash })
]
})); // messageDigest
return signedAttr;
}
);
//endregion
}
//endregion
//region Initialize CMS Signed Data structures and sign it
sequence = sequence.then(
signedAttr =>
{
cmsSignedSimpl = new pkijs.SignedData({
version: 1,
encapContentInfo: new pkijs.EncapsulatedContentInfo({
eContentType: OID_PKCS7_Data // "data" content type
}),
signerInfos: [
new pkijs.SignerInfo({
version: 1,
sid: new pkijs.IssuerAndSerialNumber({
issuer: signingCert.issuer,
serialNumber: signingCert.serialNumber
})
})
],
certificates: certificateChain //array
});
if(addExt)
{
cmsSignedSimpl.signerInfos[0].signedAttrs = new pkijs.SignedAndUnsignedAttributes({
type: 0,
attributes: signedAttr
});
}
if(detachedSignature === false)
{
const contentInfo = new pkijs.EncapsulatedContentInfo({
eContent: new asn1js.OctetString({ valueHex: dataBuffer })
});
cmsSignedSimpl.encapContentInfo.eContent = contentInfo.eContent;
return cmsSignedSimpl.sign(privateKey, 0, hashAlg);
}
return cmsSignedSimpl.sign(privateKey, 0, hashAlg, dataBuffer);
}
);
//endregion
//region Create final result
sequence = sequence.then(
(result) =>
{
const cmsSignedSchema = cmsSignedSimpl.toSchema(true);
const cmsContentSimp = new pkijs.ContentInfo({
contentType: OID_PKCS7_SignedData, //signedData
content: cmsSignedSchema
});
const _cmsSignedSchema = cmsContentSimp.toSchema();
//region Make length of some elements in "indefinite form"
_cmsSignedSchema.lenBlock.isIndefiniteForm = true;
const block1 = _cmsSignedSchema.valueBlock.value[1];
block1.lenBlock.isIndefiniteForm = true;
const block2 = block1.valueBlock.value[0];
block2.lenBlock.isIndefiniteForm = true;
if(detachedSignature === false)
{
const block3 = block2.valueBlock.value[2];
block3.lenBlock.isIndefiniteForm = true;
block3.valueBlock.value[1].lenBlock.isIndefiniteForm = true;
block3.valueBlock.value[1].valueBlock.value[0].lenBlock.isIndefiniteForm = true;
}
//endregion
const cmsSignedBuffer = _cmsSignedSchema.toBER(false);
return cmsSignedBuffer;
},
error => Promise.reject(`Erorr during signing of CMS Signed Data: ${error}`)
);
//endregion
sequence = sequence.then(
(cmsSignedBuffer) =>
{
let signature = arrayBufferToBase64Formatted(cmsSignedBuffer);
let boundary = makeBoundary();
template = template.replace(/{{boundary}}/g, boundary);
template = template.replace("{{signature}}", signature);
template = template.replace("{{headers}}", newHeaderLines);
template = template.replace("{{mime}}", mime);
//template = template.replace(newline, '\r\n')
return template
}
);
return sequence;
}
function makeBoundary() {
let len = 20 + Math.random() * 20;
return 'W0RyLiBEYW15YW4gTWl0ZXZd--' + makeid(len)
}
function makeid(len) {
if (typeof len === 'undefined') {
len = 10
}
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < len; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
function CryptoData() {
}
CryptoData.prototype.set = function(obj) {
for(var member in obj) {
this[member] = JSON.parse(JSON.stringify(obj[member]))
}
};
CryptoData.prototype.serialize = function() {
return JSON.stringify(this)
};
CryptoData.prototype.deserialize = function(serialized) {
var obj = JSON.parse(serialized);
this.set(obj)
};
CryptoData.prototype.setPublicKey = function(publicKey) {
this["publicKey"] = publicKey
};
CryptoData.prototype.getPublicKey = function() {
return this["publicKey"]
};
CryptoData.prototype.setPrivateKey = function(privateKey) {
this["privateKey"] = privateKey
};
CryptoData.prototype.getPrivateKey = function() {
return this["privateKey"]
};
CryptoData.prototype.setx509Certificate = function(x509Certificate) {
this["x509Certificate"] = x509Certificate
};
CryptoData.prototype.getx509Certificate = function() {
return this["x509Certificate"]
};
CryptoData.prototype.setKeyUUID = function(keyUUID) {
this["keyUUID"] = keyUUID
};
CryptoData.prototype.getKeyUUID = function() {
return this["keyUUID"]
};
CryptoData.prototype.setChain = function(chain) {
this["chain"] = chain
};
CryptoData.prototype.getChain = function() {
return this["chain"]
};
function Identity() {
}
Identity.prototype.set = function(obj) {
for(var member in obj) {
this[member] = JSON.parse(JSON.stringify(obj[member]))
}
};
Identity.prototype.serialize = function() {
return JSON.stringify(this)
};
Identity.prototype.deserialize = function(serialized) {
var obj = JSON.parse(serialized);
this.set(obj)
};
Identity.prototype.setAuthentication = function(cryptoData) {
this["authentication"] = cryptoData
};
Identity.prototype.getAuthentication = function() {
return this["authentication"]
};
Identity.prototype.setPinCode = function(pinCode) {
this["pinCode"] = pinCode
};
Identity.prototype.getPinCode = function() {
return this["pinCode"]
};
Identity.prototype.setPassport = function(passportUUID, cryptoData) {
if(this["passports"] === undefined || this["passports"] === null) {
this["passports"] = {}
}
this["passports"][passportUUID] = cryptoData
};
Identity.prototype.getPassport = function(passportUUID) {
if(this["passports"] === undefined || this["passports"] === null) {
this["passports"] = {}
}
return this["passports"][passportUUID]
};
var identityColors = ["#994392", "#cb0767", "#e51d31", "#ec671b", "#fab610"];
function getNextColor() {
var colorIndex = localStorage.getItem("colorIndex");
if (colorIndex == null || colorIndex === "") {
colorIndex = 0
}
var color = identityColors[colorIndex];
colorIndex++;
colorIndex = colorIndex % identityColors.length;
localStorage.setItem("colorIndex", colorIndex);
return color
}
function setKeyForUUID(uuid, key) {
var storedIdentityForUuid = localStorage.getItem("keyperuuid/" + uuid);
if(storedIdentityForUuid !== key && storedIdentityForUuid != null && storedIdentityForUuid !== "") {
destroyIdentityFromLocalStorage(storedIdentityForUuid)
}
localStorage.setItem("keyperuuid/" + uuid, key)
}
function getColorForIdentity(key) {
var storedColor = localStorage.getItem("colors/" + key);
if(storedColor == null || storedColor === "") {
storedColor = getNextColor();
console.log("Setting new color: " + storedColor);
localStorage.setItem("colors/" + key, storedColor)
}
return storedColor
}
function setIdentityInLocalStorage(identityToStore, extendKey = true) {
var pinCode = identityToStore.pinCode;
const serializedIdentity = JSON.stringify(identityToStore);
const key = identityToStore.authentication.publicKey;
if(pinCode == null || pinCode === "") {
pinCode = getPincode(key)
}
if(pinCode == null || pinCode === "") {
console.log("Can not set identity");
return null;
}
return encryptMessage(serializedIdentity, pinCode, "identity").then((encryptedIdentity) => {
var success = true;
if(extendKey === true) {
success = extendPinCodeTtl(key, pinCode)
}
if (success === true) {
localStorage.setItem(key, encryptedIdentity);
let serializedIdentitiesList = localStorage.getItem("identities");
let identities = JSON.parse(serializedIdentitiesList);
identities[key] = true;
localStorage.setItem("identities", JSON.stringify(identities))
} else {
console.log("Can not extend pincode ttl")
}
});
}
function getProfileData(identity) {
return new Penpal.Promise(executeResultUpper => {
executeRestfulFunction("private", viamApi,
viamApi.identityGetIdentityProfileData).then(executeResult => {
if(executeResult.code === "200") {
console.log("In promise");
console.log(executeResult);
var listItem = {};
console.log(identity);
listItem.identityColor = getColorForIdentity(identity.authentication.publicKey);
listItem.initials = executeResult.data.initials;
if(listItem.initials === null || listItem.initials === "") {
listItem.initials = "JD";
}
console.log("Item");
console.log(listItem);
localStorage.setItem("profiles/" + identity.authentication.publicKey, JSON.stringify(listItem));
executeResultUpper(listItem)
} else {
executeResultUpper({})
}
});
});
}
function getIdentityFromLocalStorage(key, pinCode, extendTtl = true) {
const encryptedIdentity = localStorage.getItem(key);
if (encryptedIdentity == null) {
console.log("No such identity for public key");
return Promise.resolve(null)
}
return decryptMessage(encryptedIdentity, pinCode).then((serializedIdentity) => {
var parsedIdentity = JSON.parse(serializedIdentity);
parsedIdentity["pinCode"] = "";
//console.log(parsedIdentity)
if(extendTtl === true) {
var success = extendPinCodeTtl(key, pinCode);
if (success === true) {
return parsedIdentity
} else {
console.log("Can not extend pincode ttl");
return null
}
} else {
return parsedIdentity
}
});
}
function listIdentitiesFromLocalStorage() {
var serializedIdentitiesList = localStorage.getItem("identities");
var identities = JSON.parse(serializedIdentitiesList);
var identitiesResult = {};
for(var key in identities) {
var profile = JSON.parse(JSON.stringify(localStorage.getItem("profiles/" + key)));
console.log("Getting profile");
console.log(profile);
if(profile != null && profile !== "") {
console.log("Setting profile for key: " + key);
//console.log(profile)
identitiesResult[key] = JSON.parse(profile)
//console.log(identitiesResult)
} else {
console.log("Setting empty key for profile: " + key);
identitiesResult[key] = {}
//console.log(identitiesResult)
}
}
console.log("In list identities from local storage");
console.log(identitiesResult);
return identitiesResult
}
function extendPinCodeTtl(key, pinCode) {
//console.log("Extending pincode ttl")
//console.log(getStack())
//console.log("Extending pincode ttl for key: " + key)
//console.log(pinCode)
if(pinCode == null || pinCode == "") {
var now = new Date();
var nowMillis = now.getTime();
var ttl = window.sessionStorage.getItem("pincodettls/" + key);
if (ttl == null || ttl == "" || nowMillis >= parseInt(ttl)) {
clearPinCodeTtl(key);
return false
} else {
var ttl = now.getTime() + 24 * 60 * 60 * 1000;
window.sessionStorage.setItem("pincodettls/" + key, ttl);
}
} else {
var now = new Date();
var ttl = now.getTime() + 24 * 60 * 60 * 1000;
window.sessionStorage.setItem("pincodettls/" + key, ttl);
window.sessionStorage.setItem("pincodes/" + key, pinCode);
}
return true;
}
window.extendPinCodeTtl = extendPinCodeTtl;
function clearPinCodeTtl(key) {
//console.log("Clearing ttl for key: " + key)
window.sessionStorage.removeItem("pincodettls/" + key);
window.sessionStorage.removeItem("pincodes/" + key)
}
function getPincode(key) {
var now = new Date();
var nowMillis = now.getTime();
var ttl = window.sessionStorage.getItem("pincodettls/" + key);
if (ttl == null || ttl === "") {
return null
} else {
if(nowMillis >= parseInt(ttl)) {
clearPinCodeTtl(key);
return null
} else {
return window.sessionStorage.getItem("pincodes/" + key);
}
}
}
function createEvent(actionId, type, payloads) {
return {
"actionID": actionId,
"type": type,
"stamp": new Date().getTime(),
"payloads" : payloads
}
}
function destroyIdentityFromLocalStorage(key) {
localStorage.removeItem(key);
localStorage.removeItem("profiles/" + key);
localStorage.removeItem("colors/" + key);
var serializedIdentitiesList = localStorage.getItem("identities");
var identities = JSON.parse(serializedIdentitiesList);
identities[key] = null;
delete identities[key];
localStorage.setItem("identities", JSON.stringify(identities))
}
window.loadedIdentities = {};
window.wopiAPI = new WopiAPI();
window.viamApi = new ViamAPI();
window.viamAnonymousApi = new ViamAPI();
window.currentlyAuthenticatedIdentity = null;
window.currentlyLoadedIdentity = null;
window.lastTimeGetProfile = 0;
const handleIdentityLogin = (identity, uuid, token) => {
const { loadedIdentities, viamApi } = window;
viamApi.setSessionData(uuid, token);
localStorage.setItem("uuid", uuid);
localStorage.setItem("token", token);
localStorage.setItem("authenticatedIdentity", identity.authentication.publicKey);
window.currentlyAuthenticatedIdentity = loadedIdentities[identity.authentication.publicKey];
window.lastTimeGetProfile = 0;
setKeyForUUID(uuid, identity.authentication.publicKey);
};
function executeRestfulFunction(type, that, fn, ...args) {
const { currentlyAuthenticatedIdentity, viamApi, currentlyLoadedIdentity } = window;
return new Penpal.Promise(executeResult => {
fn.apply(that, args).then((response) => {
const identity = currentlyAuthenticatedIdentity || currentlyLoadedIdentity;
if (type === "private" && identity && response.data.code === "400" && response.data.status === "Bad session") {
viamApi.identityLogin("previousaddeddevice")
.then((response) => {
if (response.data.code === "200") {
const uuid = response.data.data["Uuid"];
const token = response.data.data["Session"];
handleIdentityLogin(identity, uuid, token);
// TODO: Previously there was fn.apply(null, args) where null is probably wrong context for fn.apply()
fn.apply(that, args).then(({data}) => executeResult(data));
} else {
executeResult(response.data);
}
})
.catch(console.warn);
} else {
executeResult(response.data);
}
});
});
}
window.executeRestfulFunction = executeRestfulFunction;
function loadIdentityInternal(identityKey, pinCode) {
return new Penpal.Promise(result => {
console.log("Loading identity with pincode: " + pinCode);
getIdentityFromLocalStorage(identityKey, pinCode).then((loadedIdentity) => {
if (loadedIdentity == null) {
result({
"data": "",
"code": "400",
"status": "Can not load identity"
})
}
var copiedIdentity = JSON.parse(JSON.stringify(loadedIdentity));
loadedIdentities[identityKey] = loadedIdentity;
if (identityKey === localStorage.getItem("authenticatedIdentity")) {
currentlyAuthenticatedIdentity = copiedIdentity;
viamApi.setIdentity(identityKey);
var uuid = localStorage.getItem("uuid");
var token = localStorage.getItem("token");
//console.log("Loading " + uuid + " " + token)
viamApi.setSessionData(uuid, token)
}
//console.log("Set loaded identity in load identity")
currentlyLoadedIdentity = copiedIdentity;
viamAnonymousApi.setIdentity(currentlyLoadedIdentity.authentication.publicKey);
copiedIdentity.pinCode = "";
copiedIdentity.authentication.privateKey = "";
result({
"data": copiedIdentity,
"code": "200",
"status": "Identity loaded"
})
}).catch((e) => {
result({
"data": "",
"code": "400",
"status": "Can not load entity:" + e
})
})
});
}
function changeIdentityPinCodeInternal(key, oldPinCode, newPinCode) {
return new Penpal.Promise(result => {
getIdentityFromLocalStorage(key, oldPinCode, false).then((identity) => {
identity.pinCode = newPinCode;
console.log("Storing identity with pincode: " + identity.pinCode);
setIdentityInLocalStorage(identity).then(() => {
result({
"data": "",
"code": "200",
"status": "Successfully changed pincode"
});
}).catch((e) => {
result({
"data": "",
"code": "400",
"status": "Cannot store identity " + e
});
});
}).catch((e) => {
result({
"data": "",
"code": "400",
"status": "Cannot get identity " + e
});
});
});
}
function getCertificateForPassport(passportUUID, internal) {
return new Penpal.Promise(certificateResult => {
if (currentlyAuthenticatedIdentity === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
}
}
var passportIdentity = new Identity();
passportIdentity.set(currentlyAuthenticatedIdentity);
//console.log("Getting: " + passportUUID)
//console.log(identity)
var passport = passportIdentity.getPassport(passportUUID);
if(passport === undefined || passport === null) {
createPassportCertificate(passportUUID).then(function(keys){
var cryptoData = new CryptoData();
//console.log(keys)
cryptoData.setPublicKey(keys["publicKeyPEM"]);
cryptoData.setPrivateKey(keys["privateKeyPEM"]);
var certificate = keys["certificatePEM"];
//download("passportCertificateBeforeSigning.crt", "text/plain", certificate)
//console.log(certificate)
//cryptoData.setx509Certificate(keys["certificate"])
executeRestfulFunction("private", viamApi, viamApi.signSignCertificate, btoa(certificate), passportUUID).then(executeResult => {
if(executeResult.code === "200") {
var signedCertificate = atob(executeResult.data["SignedCertificate"]);
//download("passportCertificateAfterSigning.crt", "text/plain", signedCertificate)
var keyUUID = executeResult.data["CertificateUUID"];
var encodedChain = executeResult.data["Chain"];
//download("rootCertificate.crt", "text/plain", atob(encodedChain[0]))
var chain = [];
for(var i = 0; i < encodedChain.length; i++) {
chain.push(atob(encodedChain[i]))
}
//console.log("Chain from server")
//console.log(chain)
//console.log(signedCertificate)
//console.log(certificate)
//console.log(keyUUID)
cryptoData.setx509Certificate(signedCertificate);
cryptoData.setKeyUUID(keyUUID);
cryptoData.setChain(chain);
passportIdentity.setPassport(passportUUID, cryptoData);
getProfileData(passportIdentity).then(executeResult1 => {
console.log("Profile updated in set identity");
setIdentityInLocalStorage(passportIdentity).then(() => {
currentlyAuthenticatedIdentity = passportIdentity;
lastTimeGetProfile = 0;
//console.log("Set loaded identity in passport");
currentlyLoadedIdentity = passportIdentity;
var copyOfCryptoData = JSON.parse(JSON.stringify(cryptoData));
if (internal === false) {
copyOfCryptoData["privateKey"] = ""
}
certificateResult({
"data": copyOfCryptoData,
"code": "200",
"status": "Certificate got"
});
}).catch((e) => {
certificateResult({
"data": "",
"code": "400",
"status": "Can not store certificate " + e
});
});
});
} else {
certificateResult(executeResult)
}
});
});
} else {
//console.log(passport)
var copyOfCryptoData = JSON.parse(JSON.stringify(passport));
if(internal === false) {
copyOfCryptoData["privateKey"] = ""
}
certificateResult({"data" : copyOfCryptoData,
"code" : "200",
"status" : "Certificate got"
});
}
});
}
const connection = Penpal.connectToParent({
// Methods child is exposing to parent
methods: {
initializeApiHost: (apiUrl) => {
window.API_HOST = apiUrl.charAt(apiUrl.length - 1) === "/" ? apiUrl : apiUrl + "/";
},
createIdentity(pinCode) {
return new Penpal.Promise(result => {
createPassportCertificate(makeid()).then(function(keys){
var newIdentity = new Identity();
var cryptoData = new CryptoData();
cryptoData.setPublicKey(keys["publicKeyPEM"]);
cryptoData.setPrivateKey(keys["privateKeyPEM"]);
cryptoData.setx509Certificate(keys["certificatePEM"]);
newIdentity.setAuthentication(cryptoData);
newIdentity.setPinCode(pinCode);
//console.log("Set loaded identity in createIdentity")
currentlyLoadedIdentity = newIdentity;
loadedIdentities[newIdentity.authentication.publicKey] = newIdentity;
extendPinCodeTtl(newIdentity.authentication.publicKey, pinCode);
viamAnonymousApi.setIdentity(newIdentity.authentication.publicKey);
result({"data" : newIdentity,
"code" : "200",
"status" : "Identity created"
})
});
})
},
listIdentities() {
return new Penpal.Promise(result => {
var identities = listIdentitiesFromLocalStorage();
console.log("Before return of identities");
console.log(identities);
result({"data" : identities,
"code" : "200",
"status" : "Identities listed"
})
});
},
loadIdentity(identityKey, pinCode) {
return loadIdentityInternal(identityKey, pinCode)
},
changeIdentityPinCode(key, oldPinCode, newPinCode) {
return changeIdentityPinCodeInternal(key, oldPinCode, newPinCode)
},
getIdentityProfile(identityKey) {
return new Penpal.Promise(result => {
serializedProfile = localStorage.getItem("profiles/" + identityKey);
if(serializedProfile == null || serializedProfile === "") {
result({"data" : "",
"code" : "400",
"status" : "Profile is empty"
});
} else {
result({"data" : JSON.parse(serializedProfile),
"code" : "200",
"status" : "Identities cleared"
})
}
});
},
clearIdentities() {
return new Penpal.Promise(result => {
var identitiesTemp = listIdentitiesFromLocalStorage();
//console.log(identitiesTemp.length)
for(var i in identitiesTemp) {
destroyIdentityFromLocalStorage(i)
}
result({"data" : "",
"code" : "200",
"status" : "Identities cleared"
})
});
},
confirmIdentificator(identity, confirmationCodeArg) {
return new Penpal.Promise(result => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityConfirmIdentificator,confirmationCodeArg).then(executeResult => {
result(executeResult);
});
});
},
identityGetIdentificatorByRegisterToken(identity, tokenArg) {
return new Penpal.Promise(result => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityGetIdentificatorByRegisterToken,tokenArg).then(executeResult => {
result(executeResult);
});
});
},
submitIdentificator(identity, identificatorArg, registerToken) {
return new Penpal.Promise(result => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identitySubmitIdentificator,identificatorArg, registerToken).then(executeResult => {
result(executeResult);
});
});
},
submitRegisterClaims(identity, givennameArg,familynameArg,emailArg,phonenumberArg) {
return new Penpal.Promise(result => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identitySubmitRegisterClaims,givennameArg,familynameArg,emailArg,phonenumberArg).then(executeResult => {
result(executeResult);
});
});
},
agreeOnRegistration(registerIdentity) {
return new Penpal.Promise(result => {
viamApi.setIdentity(registerIdentity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityAgreeOnRegistration).then(executeResult => {
console.log("Profile updated in set identity");
let sequence = Promise.resolve();
if (executeResult.code === "200") {
sequence = sequence.then(() => {
setIdentityInLocalStorage(registerIdentity)
}
)
}
sequence.then(() => {
result(executeResult);
}).catch((e) => {
result({
"data": "",
"code": "400",
"status": "Can not store identity: " + e
})
})
});
});
},
resendConfirmationCode(identity, identificatorArg) {
return new Penpal.Promise(result => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityResendConfirmationCode,identificatorArg).then(executeResult => {
result(executeResult);
});
});
},
login(loginIdentity, mode, code, actionID) {
return new Penpal.Promise(result => {
if (loadedIdentities[loginIdentity.authentication.publicKey] === null) {
result({"data" : "",
"code" : "400",
"status" : "Identity not loaded"
})
}
//console.log("After loaded check")
viamApi.setIdentity(loginIdentity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityLogin, mode, code, actionID).then(executeResult => {
// console.log(executeResult)
//console.log(mode)
switch (mode) {
case "sms" : {
if (executeResult.code === "200") {
const uuid = executeResult.data["Uuid"];
const token = executeResult.data["Session"];
handleIdentityLogin(loginIdentity, uuid, token);
delete executeResult.data["Uuid"];
delete executeResult.data["Session"];
getProfileData(loginIdentity).then(executeResult1 => {
result(executeResult);
});
} else {
result(executeResult);
}
break;
}
case "previousaddeddevice" : {
if (executeResult.code === "200") {
const uuid = executeResult.data["Uuid"];
const token = executeResult.data["Session"];
handleIdentityLogin(loginIdentity, uuid, token);
delete executeResult.data["Uuid"];
delete executeResult.data["Session"];
getProfileData(loginIdentity).then(executeResult1 => {
result(executeResult);
});
} else {
result(executeResult);
}
break;
}
case "newdevice" : {
if (executeResult.code === "200") {
//console.log(executeResult)
var actionID = executeResult.data["ActionID"];
var QrCode = executeResult.data["QrCode"];
//console.log(uuid + " " + token)
QRCode.toDataURL(actionID + "," + QrCode, function (err, url) {
executeResult.data["image"] = url;
//console.log(executeResult)
result(executeResult);
})
} else {
//console.log(executeResult)
result(executeResult);
}
break;
}
default : {
result(executeResult);
break;
}
}
});
});
},
identityAddNewDevice() {
return new Penpal.Promise(result => {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
if (loadedIdentities[authenticationPublicKey] === null) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
var success = extendPinCodeTtl(authenticationPublicKey);
if(success === false) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
executeRestfulFunction("private", viamApi, viamApi.identityAddNewDevice).then(executeResult => {
if (executeResult.code === "200") {
//console.log(response.data.data)
var actionID = executeResult.data["ActionID"];
var QrCode = executeResult.data["QrCode"];
//console.log(uuid + " " + token)
QRCode.toDataURL(actionID + "," + QrCode, function (err, url) {
executeResult.data["image"] = url;
result(executeResult);
})
} else {
result(executeResult);
}
});
});
},
identityDestroyKeysForDevice(authenticationPublicKeyArg) {
return new Penpal.Promise(result => {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
if (loadedIdentities[authenticationPublicKey] === null) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
var success = extendPinCodeTtl(authenticationPublicKey);
if(success === false) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
executeRestfulFunction("private", viamApi, viamApi.identityDestroyKeysForDevice, btoa(authenticationPublicKeyArg)).then(executeResult => {
result(executeResult);
});
});
},
logout() {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
if (loadedIdentities[authenticationPublicKey] === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
return new Penpal.Promise(result => {
executeRestfulFunction("private", viamApi, viamApi.identityLogout).then(executeResult => {
viamApi.setIdentity("");
viamApi.setSessionData("", "");
clearPinCodeTtl(authenticationPublicKey);
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
localStorage.removeItem("uuid");
localStorage.removeItem("token");
localStorage.removeItem("authenticatedIdentity");
delete loadedIdentities[authenticationPublicKey];
//console.log("Set loaded identity in logout")
currentlyLoadedIdentity = null;
currentlyAuthenticatedIdentity = null;
lastTimeGetProfile = 0;
result(executeResult);
});
});
},
identityRestoreAccess(restoreAccessIdentity, identificator) {
return new Penpal.Promise(result => {
viamApi.setIdentity(restoreAccessIdentity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityRestoreAccess, identificator).then(executeResult => {
if (executeResult.code === "200") {
setIdentityInLocalStorage(restoreAccessIdentity);
result(executeResult);
} else {
result(executeResult);
}
});
});
},
getCurrentlyLoggedInUUID() {
return new Penpal.Promise(result => {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
if (loadedIdentities[authenticationPublicKey] === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
var success = extendPinCodeTtl(authenticationPublicKey);
if(success === false) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
if(localStorage.getItem("uuid") === null) {
result({"data" : "",
"code" : "400",
"status" : "Not logged in UUID"
})
}
result({"data" : localStorage.getItem("uuid"),
"code" : "200",
"status" : "UUID loaded"
})
});
},
getCertificateByPassport(passportUUID) {
return new Penpal.Promise(result => {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
if (loadedIdentities[authenticationPublicKey] === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
var success = extendPinCodeTtl(authenticationPublicKey);
if(success === false) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
getCertificateForPassport(passportUUID, false).then(certificateResult => {
//console.log(certificateResult)
result(certificateResult)
})
});
},
getOneTimeCertificateByPassport(passportUUID, emailArg) {
return new Penpal.Promise(result => {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
if (loadedIdentities[authenticationPublicKey] === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not loaded"
}
}
var success = extendPinCodeTtl(authenticationPublicKey);
if(success === false) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
getCertificateForPassport(passportUUID, true).then(certificateResult => {
//console.log(certificateResult)
if(certificateResult.code === "200") {
var passportCertificate = certificateResult.data["x509Certificate"];
var passportPrivateKey = certificateResult.data["privateKey"];
var passportChain = certificateResult.data["chain"];
createOneTimePassportCertificate(makeid() + "-" + passportUUID, emailArg, passportPrivateKey, passportCertificate).then(function(keys){
var publicKeyOneTime = keys["publicKeyPEM"];
var privateKeyOneTime = keys["privateKeyPEM"];
var certificateOneTime = keys["certificatePEM"];
passportChain.push(passportCertificate);
var oneTimeCryptoData = new CryptoData();
oneTimeCryptoData.setx509Certificate(certificateOneTime);
oneTimeCryptoData.setPrivateKey(privateKeyOneTime);
oneTimeCryptoData.setPublicKey(publicKeyOneTime);
oneTimeCryptoData.setChain(passportChain);
result({"data" : oneTimeCryptoData,
"code" : "200",
"status" : "One time certificate generated"
})
// Prints PEM formatted signed certificate
// -----BEGIN CERTIFICATE-----MIID....7Hyg==-----END CERTIFICATE-----
});
} else {
result({"data" : "",
"code" : "400",
"status" : "Can not generate one time certificate"
})
}
})
});
},
signEmail(passportUUID, emailArg, emailMessage) {
return new Penpal.Promise(result => {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
}
}
if (loadedIdentities[authenticationPublicKey] === null) {
return {"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
}
}
var success = extendPinCodeTtl(authenticationPublicKey);
if(success === false) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
getCertificateForPassport(passportUUID, true).then(certificateResult => {
console.log("Certificate for passport");
console.log(certificateResult);
if(certificateResult.code === "200") {
var passportCertificate = certificateResult.data["x509Certificate"];
var passportPrivateKey = certificateResult.data["privateKey"];
var passportChain = certificateResult.data["chain"];
createOneTimePassportCertificate(makeid() + "-" + passportUUID, emailArg, passportPrivateKey, passportCertificate).then(function(keys){
var publicKeyOneTime = keys["publicKeyPEM"];
var privateKeyOneTime = keys["privateKeyPEM"];
var certificateOneTime = keys["certificatePEM"];
//download("certificateOneTime.crt", "text/plain", certificateOneTime)
passportChain.push(passportCertificate);
//console.log("Before sign email")
//console.log(certificateOneTime)
//console.log(passportChain)
//console.log(privateKeyOneTime)
executeRestfulFunction("private", viamApi, viamApi.passportGetEmailWithHeaderByPassport,
passportUUID, emailMessage).then(executeResult2 => {
var emailWithHeader = executeResult2.data;
//console.log(emailWithHeader)
//download("withheader.eml", "message/rfc822", emailWithHeader)
var signedEmailPromise = signEmail(emailWithHeader,
certificateOneTime,
passportChain,
privateKeyOneTime);
signedEmailPromise.then(signedEmail => {
executeRestfulFunction("private", viamApi, viamApi.signResignEmail,
passportUUID, signedEmail).then(executeResult => {
result({"data" : executeResult.data,
"code" : "200",
"status" : "Email signed"
})
});
/*result({"data" : signedEmail,
"code" : "200",
"status" : "Email signed"
})*/
});
});
// Prints PEM formatted signed certificate
// -----BEGIN CERTIFICATE-----MIID....7Hyg==-----END CERTIFICATE-----
});
} else {
result({"data" : "",
"code" : "400",
"status" : "Can not sign email"
})
}
})
});
},
hasSession() {
return new Penpal.Promise(result => {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey === null) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
});
}
if (loadedIdentities[authenticationPublicKey] === null) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
});
}
var success = extendPinCodeTtl(authenticationPublicKey);
if(success === false) {
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
executeRestfulFunction("private", viamApi, viamApi.identityHasSession).then(executeResult => {
result(executeResult);
});
});
},
marketingSignUpIdentificator(identificator, reference) {
return new Penpal.Promise(result => {
viamApi.setIdentity("marketingapppublickey");
executeRestfulFunction("public", viamApi, viamApi.marketingSignUpIdentificator, identificator, reference).then(executeResult => {
viamApi.setIdentity("");
viamApi.setSessionData("", "");
result(executeResult);
});
});
},
marketingGetIdentificatorProfile(identificator, pincode) {
return new Penpal.Promise(result => {
viamApi.setIdentity("marketingapppublickey");
executeRestfulFunction("public", viamApi, viamApi.marketingGetIdentificatorProfile, identificator, pincode).then(executeResult => {
viamApi.setIdentity("");
viamApi.setSessionData("", "");
result(executeResult);
});
});
},
marketingExecuteEventForIdentificator(identificator, pincode, event) {
return new Penpal.Promise(result => {
viamApi.setIdentity("marketingapppublickey");
executeRestfulFunction("public", viamApi, viamApi.marketingExecuteEventForIdentificator, identificator, pincode, event).then(executeResult => {
viamApi.setIdentity("");
viamApi.setSessionData("", "");
result(executeResult);
});
});
},
getCurrentlyAuthenticatedIdentity() {
return new Penpal.Promise(result => {
result({"data" : currentlyAuthenticatedIdentity,
"code" : "200",
"status" : "Currently authenticated identity"
})
});
},
stringToUtf8ByteArray(str) {
if (typeof str !== 'string') {
str = str.toString()
}
let res = Buffer.from(str,'utf-8');
return new Penpal.Promise(result => {
result(res)
})
},
utf8ByteArrayToString(ba) {
if (!Buffer.isBuffer(ba)) {
ba = Buffer.from(ba)
}
let res = ba.toString('utf-8');
return new Penpal.Promise(result => {
result(res)
})
},
stringToUtf8Base64(str) {
if (!Buffer.isBuffer(str)) {
if (typeof str !== 'string') {
str = str.toString()
}
str = Buffer.from(str, 'utf-8')
}
let res = str.toString('base64');
return new Penpal.Promise(result => {
result(res)
})
},
utf8Base64ToString(strBase64) {
if (!Buffer.isBuffer(strBase64)) {
if (typeof strBase64 !== 'string') {
strBase64 = strBase64.toString()
}
strBase64 = Buffer.from(strBase64, 'base64')
}
let res = strBase64.toString('utf-8');
return new Penpal.Promise(result => {
result(res)
})
},
base64ToByteArray(strBase64) {
if (typeof strBase64 !== 'string') {
strBase64 = strBase64.toString()
}
let res = Buffer.from(strBase64, 'base64');
return new Penpal.Promise(result => {
result(res)
})
},
byteArrayToBase64(ba) {
if (!Buffer.isBuffer(ba)) {
ba = Buffer.from(ba)
}
let res = ba.toString('base64');
return new Penpal.Promise(result => {
result(res)
})
},
...penpalMethods
}
});
connection.promise.then(parent => {
window.addEventListener('storage', event => {
if (event.key === "authenticatedIdentity" && event.newValue === null) {
var publicKey = currentlyAuthenticatedIdentity.authentication.publicKey;
currentlyLoadedIdentity = null;
currentlyAuthenticatedIdentity = null;
var event = createEvent("LogoutFromAnotherTab", "Logout", [publicKey]);
parent.onEvent(event)
}
});
var identities = localStorage.getItem("identities");
console.log("Library loaded at: " + new Date().toISOString());
if (identities === "" || identities === null) {
//console.log("Setting up empty version")
localStorage.setItem("identities", JSON.stringify({}))
}
if (localStorage.getItem("uuid") === null || localStorage.getItem("token") === null
|| localStorage.getItem("authenticatedIdentity") === null) {
localStorage.removeItem("uuid");
localStorage.removeItem("token");
localStorage.removeItem("authenticatedIdentity")
} else {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
var pinCode = getPincode(authenticationPublicKey);
if(pinCode === "" || pinCode == null) {
loadIdentityInternal(authenticationPublicKey, "00000000").then(result => {
if(result.code !== "200") {
console.log(result);
//var event = createEvent("CanNotLoadIdentity", "ErrorDuringLoadingIdentity", [authenticationPublicKey])
//parent.onEvent(event)
var event = createEvent("CanNotGetPincodeForAuthenticatedIdentity", "IdentityNotLoaded", [authenticationPublicKey]);
parent.onEvent(event)
}
});
//var event = createEvent("CanNotGetPincodeForAuthenticatedIdentity", "IdentityNotLoaded", [authenticationPublicKey])
//parent.onEvent(event)
} else {
loadIdentityInternal(authenticationPublicKey, pinCode).then(result => {
if(result.code !== "200") {
var event = createEvent("CanNotLoadIdentity", "ErrorDuringLoadingIdentity", [authenticationPublicKey]);
parent.onEvent(event)
}
});
}
}
var anynomousDeviceKeyEventsProcessing = false;
var maxDeviceKeyAnonymousEventTime = 0;
var eventsDeviceEventsProcessing = false;
var maxDeviceKeyEventTime = 0;
var eventsEntityEventsProcessing = false;
var maxEntityEventTime = 0;
var identityLoadedEvent = false;
var identityAuthenticatedEvent = false;
setInterval(function() {
if(currentlyAuthenticatedIdentity != null) {
var pinCode = getPincode(currentlyAuthenticatedIdentity.authentication.publicKey);
if(pinCode != null && pinCode != "") {
getIdentityFromLocalStorage(currentlyAuthenticatedIdentity.authentication.publicKey,
pinCode, false).then((gotIdentity) => {
currentlyAuthenticatedIdentity = gotIdentity;
//console.log("Set loaded identity in pincode check interval")
currentlyLoadedIdentity = gotIdentity;
if(identityAuthenticatedEvent === false && gotIdentity != null) {
var event = createEvent("IdentityAuthenticated", "Authenticated", [gotIdentity.authentication.publicKey]);
parent.onEvent(event);
identityAuthenticatedEvent = true
}
})
} else {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if(authenticationPublicKey != null && authenticationPublicKey != "") {
/*var event = createEvent("CanNotLoadPincodeForAuthenticatedIdentity", "IdentityNotLoaded", [currentlyAuthenticatedIdentity.authentication.publicKey])
parent.onEvent(event)
clearPinCodeTtl(authenticationPublicKey)
currentlyAuthenticatedIdentity = null*/
loadIdentityInternal(authenticationPublicKey, "00000000").then(result => {
if(result.code != "200") {
console.log(result);
var event = createEvent("CanNotGetPincodeForAuthenticatedIdentity", "IdentityNotLoaded", [authenticationPublicKey]);
parent.onEvent(event);
clearPinCodeTtl(authenticationPublicKey);
currentlyAuthenticatedIdentity = null
}
});
}
identityAuthenticatedEvent = false;
//console.log("Set loaded identity in cycle for not authenticated value")
currentlyLoadedIdentity = null
}
}
if(currentlyLoadedIdentity != null) {
var pinCode = getPincode(currentlyLoadedIdentity.authentication.publicKey);
if(pinCode == "" || pinCode == null) {
if(identityLoadedEvent === false) {
/*var event = createEvent("CanNotLoadPincodeForLoadedIdentity", "IdentityNotLoaded", [currentlyLoadedIdentity.authentication.publicKey])
parent.onEvent(event)
identityLoadedEvent = true*/
loadIdentityInternal(currentlyLoadedIdentity.authentication.publicKey, "00000000").then(result => {
if(result.code != "200") {
var event = createEvent("CanNotLoadPincodeForLoadedIdentity", "IdentityNotLoaded", [currentlyLoadedIdentity.authentication.publicKey]);
parent.onEvent(event);
identityLoadedEvent = true
}
});
}
} else {
identityLoadedEvent = false
}
}
if (currentlyAuthenticatedIdentity != null) {
var now = new Date().getTime();
if(now - lastTimeGetProfile > 30000) {
var identityToStore = currentlyAuthenticatedIdentity;
getProfileData(identityToStore).then(executeResult => {
console.log("Profile updated in cycle");
console.log(executeResult)
});
lastTimeGetProfile = now
}
}
}, 50);
setInterval(function() {
if (currentlyLoadedIdentity != null && anynomousDeviceKeyEventsProcessing === false) {
anynomousDeviceKeyEventsProcessing = true;
executeRestfulFunction("public", viamAnonymousApi, viamAnonymousApi.eventGetNewEventsWithoutSession, "devicekey").then(executeResult => {
if(executeResult.code === "200") {
var eventsLen = executeResult.data.length;
changedMaxDeviceKeyAnonymousEventTime = false;
for (var i = 0; i < eventsLen; i++) {
var event = executeResult.data[i];
//console.log("Received event anynomous: " + event)
switch (event.type) {
case "Authenticated" : {
console.log("Sending authenticated event");
const uuid = event.payloads[0];
const token = event.payloads[1];
handleIdentityLogin(currentlyLoadedIdentity, uuid, token);
const identityToStore = currentlyAuthenticatedIdentity;
event.payloads = [{fromQRCode: true}];
console.log(identityToStore);
setIdentityInLocalStorage(identityToStore).then(() => {
console.log(identityToStore);
getProfileData(identityToStore).then(executeResult2 => {
console.log("Profile updated in setInterval function");
console.log(executeResult2);
parent.onEvent(event)
});
});
break;
}
case "QRCodeUpdated" : {
var actionID = event["actionID"];
var QrCode = event["payloads"][1];
var eventCopy = JSON.parse(JSON.stringify(event));
QRCode.toDataURL(actionID + "," + QrCode, function (err, url) {
eventCopy["payloads"].push(url);
parent.onEvent(eventCopy)
});
break
}
case "KeyDeleted" : {
authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
clearPinCodeTtl(authenticationPublicKey);
localStorage.removeItem("uuid");
localStorage.removeItem("token");
localStorage.removeItem("authenticatedIdentity");
delete loadedIdentities[authenticationPublicKey];
//console.log("Set loaded identity in key deleted")
currentlyLoadedIdentity = null;
currentlyAuthenticatedIdentity = null;
lastTimeGetProfile = 0;
destroyIdentityFromLocalStorage(authenticationPublicKey);
break
}
default : {
parent.onEvent(event)
}
}
changedMaxDeviceKeyAnonymousEventTime = true;
maxDeviceKeyAnonymousEventTime = Math.max(maxDeviceKeyAnonymousEventTime, event.stamp)
}
if(changedMaxDeviceKeyAnonymousEventTime) {
//console.log("Updating max time anonymous device with " + maxDeviceKeyAnonymousEventTime )
executeRestfulFunction("public", viamAnonymousApi, viamAnonymousApi.eventUpdateLastViewedWithoutSession,
"devicekey", maxDeviceKeyAnonymousEventTime.toString()).then(executeResult1 => {
anynomousDeviceKeyEventsProcessing = false
})
} else {
anynomousDeviceKeyEventsProcessing = false
}
} else {
anynomousDeviceKeyEventsProcessing = false
//console.log("Error during query anynomous device")
}
});
}
/*if(currentlyAuthenticatedIdentity === null) {
console.log("Currently authenticated identity is null")
}*/
if (currentlyAuthenticatedIdentity != null && eventsDeviceEventsProcessing === false) {
eventsDeviceEventsProcessing = true;
executeRestfulFunction("private", viamApi, viamApi.eventGetNewEvents, "devicekey").then(executeResult => {
if(executeResult.code === "200") {
var eventsLen = executeResult.data.length;
changedMaxDeviceKeyEventTime = false;
for(var i = 0; i < eventsLen; i++) {
var event = executeResult.data[i];
//console.log("Received event device key: " + event)
if(event.type === "QRCodeUpdated") {
var actionID = event["actionID"];
var QrCode = event["payloads"][1];
var eventCopy = JSON.parse(JSON.stringify(event));
QRCode.toDataURL(actionID + "," + QrCode, function (err, url) {
eventCopy["payloads"].push(url);
parent.onEvent(eventCopy)
})
} else {
parent.onEvent(event)
}
maxDeviceKeyEventTime = Math.max(maxDeviceKeyEventTime, event.stamp)
}
if(changedMaxDeviceKeyEventTime) {
//console.log("Updating max time authenticated device")
executeRestfulFunction("private", viamApi, viamApi.eventUpdateLastViewed, "devicekey",
maxDeviceKeyEventTime.toString()).then(executeResult1 => {
eventsDeviceEventsProcessing = false
})
} else {
eventsDeviceEventsProcessing = false
}
} else {
//console.log("Error during query device")
eventsDeviceEventsProcessing = false
}
});
}
if (currentlyAuthenticatedIdentity != null && eventsEntityEventsProcessing === false) {
eventsEntityEventsProcessing = true;
executeRestfulFunction("private", viamApi, viamApi.eventGetNewEvents, "entity").then(executeResult => {
if(executeResult.code === "200") {
var eventsLen = executeResult.data.length;
changedMaxEntityEventTime = false;
for(var i = 0; i < eventsLen; i++) {
event = executeResult.data[i];
if(event.type === "QRCodeUpdated") {
var actionID = event["actionID"];
var QrCode = event["payloads"][1];
var eventCopy = JSON.parse(JSON.stringify(event));
QRCode.toDataURL(actionID + "," + QrCode, function (err, url) {
eventCopy["payloads"].push(url);
parent.onEvent(eventCopy)
});
continue
}
//console.log("Received event entity: " + event)
parent.onEvent(event);
changedMaxEntityEventTime = true;
//console.log(maxEntityEventTime + " " + event.stamp)
maxEntityEventTime = Math.max(maxEntityEventTime, event.stamp)
}
if(changedMaxEntityEventTime) {
//console.log("Updating max time entity" + maxEntityEventTime)
executeRestfulFunction("private", viamApi, viamApi.eventUpdateLastViewed, "entity",
maxEntityEventTime.toString()).then(executeResult1 => {
eventsEntityEventsProcessing = false
})
} else {
eventsEntityEventsProcessing = false
}
} else {
//console.log("Error during query entity")
eventsEntityEventsProcessing = false
}
});
}
}, 1000);
});