import { FieldType } from '../../../src/enums/fieldType'; import { OnePassword1PifImporter as Importer } from '../../../src/importers/onepassword1PifImporter'; import { Utils } from '../../../src/misc/utils'; if (Utils.isNode) { // Polyfills // tslint:disable-next-line const jsdom: any = require('jsdom'); (global as any).DOMParser = new jsdom.JSDOM().window.DOMParser; } const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' + JSON.stringify({ uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', updatedAt: 1486071244, securityLevel: 'SL5', contentsHash: 'aaaaaaaa', title: 'Imported Entry', location: 'https://www.google.com', secureContents: { fields: [ { value: 'user@test.net', id: 'email-input', name: 'email', type: 'T', designation: 'username', }, { value: 'myservicepassword', id: 'password-input', name: 'password', type: 'P', designation: 'password', }, ], sections: [ { fields: [ { k: 'concealed', n: 'AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC', v: 'console-password-123', t: 'console password', }, ], title: 'Admin Console', name: 'admin_console', }, ], passwordHistory: [ { value: 'old-password', time: 1447791421, }, ], }, URLs: [ { label: 'website', url: 'https://www.google.com', }, ], txTimestamp: 1508941334, createdAt: 1390426636, typeName: 'webforms.WebForm', }); const WindowsOpVaultTestData = JSON.stringify({ category: '001', created: 1544823719, hmac: 'NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=', k: 'XC/z20QveYCoV8xQ4tCJZZp/uum77xLkMSMEhlUULndryXgSmkG+VBtkW7AfuerfKc8Rtu43a4Sd078j7XfZTcwUCEKtBECUTDNbEgv4+4hoFVk1EzZgEUy/0bW1Ap+jNLmmdSU9h74+REu6pdxsvQ==', tx: 1553395669, updated: 1553395669, uuid: '528AB076FB5F4FBF960884B8E01619AC', overview: { title: 'Google', URLs: [ { u: 'google.com', }, ], url: 'google.com', ps: 26, ainfo: 'googluser', }, details: { passwordHistory: [ { value: 'oldpass1', time: 1553394449, }, { value: 'oldpass2', time: 1553394457, }, { value: 'oldpass3', time: 1553394458, }, { value: 'oldpass4', time: 1553394459, }, { value: 'oldpass5', time: 1553394460, }, { value: 'oldpass6', time: 1553394461, }, ], fields: [ { type: 'T', id: 'username', name: 'username', value: 'googluser', designation: 'username', }, { type: 'P', id: 'password', name: 'password', value: '12345678901', designation: 'password', }, ], notesPlain: 'This is a note\r\n\r\nline1\r\nline2', sections: [ { title: 'test', name: '1214FD88CD30405D9EED14BEB4D61B60', fields: [ { k: 'string', n: '6CC3BD77482D4559A4B8BB2D360F821B', v: 'fgfg', t: 'fgggf', }, { k: 'concealed', n: '5CFE7BCAA1DF4578BBF7EB508959BFF3', v: 'dfgdfgfdg', t: 'pwfield', }, ], }, ], }, }); const IdentityTestData = JSON.stringify({ uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', updatedAt: 1553365894, securityLevel: 'SL5', contentsHash: 'eeeeeeee', title: 'Test Identity', secureContents: { lastname: 'Fritzenberger', zip: '223344', birthdate_dd: '11', homephone: '+49 333 222 111', company: 'Web Inc.', firstname: 'Frank', birthdate_mm: '3', country: 'de', sex: 'male', sections: [ { fields: [ { k: 'string', inputTraits: { autocapitalization: 'Words', }, n: 'firstname', v: 'Frank', a: { guarded: 'yes', }, t: 'first name', }, { k: 'string', inputTraits: { autocapitalization: 'Words', }, n: 'initial', v: 'MD', a: { guarded: 'yes', }, t: 'initial', }, { k: 'string', inputTraits: { autocapitalization: 'Words', }, n: 'lastname', v: 'Fritzenberger', a: { guarded: 'yes', }, t: 'last name', }, { k: 'menu', v: 'male', n: 'sex', a: { guarded: 'yes', }, t: 'sex', }, { k: 'date', v: 1552305660, n: 'birthdate', a: { guarded: 'yes', }, t: 'birth date', }, { k: 'string', inputTraits: { autocapitalization: 'Words', }, n: 'occupation', v: 'Engineer', a: { guarded: 'yes', }, t: 'occupation', }, { k: 'string', inputTraits: { autocapitalization: 'Words', }, n: 'company', v: 'Web Inc.', a: { guarded: 'yes', }, t: 'company', }, { k: 'string', inputTraits: { autocapitalization: 'Words', }, n: 'department', v: 'IT', a: { guarded: 'yes', }, t: 'department', }, { k: 'string', inputTraits: { autocapitalization: 'Words', }, n: 'jobtitle', v: 'Developer', a: { guarded: 'yes', }, t: 'job title', }, ], title: 'Identification', name: 'name', }, { fields: [ { k: 'address', inputTraits: { autocapitalization: 'Sentences', }, n: 'address', v: { street: 'Mainstreet 1', city: 'Berlin', country: 'de', zip: '223344', }, a: { guarded: 'yes', }, t: 'address', }, { k: 'phone', v: '+49 001 222 333 44', n: 'defphone', a: { guarded: 'yes', }, t: 'default phone', }, { k: 'phone', v: '+49 333 222 111', n: 'homephone', a: { guarded: 'yes', }, t: 'home', }, { k: 'phone', n: 'cellphone', a: { guarded: 'yes', }, t: 'mobile', }, { k: 'phone', n: 'busphone', a: { guarded: 'yes', }, t: 'business', }, ], title: 'Address', name: 'address', }, { fields: [ { k: 'string', n: 'username', a: { guarded: 'yes', }, t: 'username', }, { k: 'string', n: 'reminderq', t: 'reminder question', }, { k: 'string', n: 'remindera', t: 'reminder answer', }, { k: 'string', inputTraits: { keyboard: 'EmailAddress', }, n: 'email', v: 'test@web.de', a: { guarded: 'yes', }, t: 'email', }, { k: 'string', n: 'website', inputTraits: { keyboard: 'URL', }, t: 'website', }, { k: 'string', n: 'icq', t: 'ICQ', }, { k: 'string', n: 'skype', t: 'skype', }, { k: 'string', n: 'aim', t: 'AOL/AIM', }, { k: 'string', n: 'yahoo', t: 'Yahoo', }, { k: 'string', n: 'msn', t: 'MSN', }, { k: 'string', n: 'forumsig', t: 'forum signature', }, ], title: 'Internet Details', name: 'internet', }, { title: 'Related Items', name: 'linked items', }, ], initial: 'MD', address1: 'Mainstreet 1', city: 'Berlin', jobtitle: 'Developer', occupation: 'Engineer', department: 'IT', email: 'test@web.de', birthdate_yy: '2019', homephone_local: '+49 333 222 111', defphone_local: '+49 001 222 333 44', defphone: '+49 001 222 333 44', }, txTimestamp: 1553365894, createdAt: 1553364679, typeName: 'identities.Identity', }); describe('1Password 1Pif Importer', () => { it('should parse data', async () => { const importer = new Importer(); const result = importer.parse(TestData); expect(result != null).toBe(true); const cipher = result.ciphers.shift(); expect(cipher.login.username).toEqual('user@test.net'); expect(cipher.login.password).toEqual('myservicepassword'); expect(cipher.login.uris.length).toEqual(1); const uriView = cipher.login.uris.shift(); expect(uriView.uri).toEqual('https://www.google.com'); }); it('should create concealed field as "hidden" type', async () => { const importer = new Importer(); const result = importer.parse(TestData); expect(result != null).toBe(true); const ciphers = result.ciphers; expect(ciphers.length).toEqual(1); const cipher = ciphers.shift(); const fields = cipher.fields; expect(fields.length).toEqual(1); const field = fields.shift(); expect(field.name).toEqual('console password'); expect(field.value).toEqual('console-password-123'); expect(field.type).toEqual(FieldType.Hidden); }); it('should create identity records', async () => { const importer = new Importer(); const result = importer.parse(IdentityTestData); expect(result != null).toBe(true); const cipher = result.ciphers.shift(); expect(cipher.name).toEqual('Test Identity'); const identity = cipher.identity; expect(identity.firstName).toEqual('Frank'); expect(identity.middleName).toEqual('MD'); expect(identity.lastName).toEqual('Fritzenberger'); expect(identity.company).toEqual('Web Inc.'); expect(identity.address1).toEqual('Mainstreet 1'); expect(identity.country).toEqual('DE'); expect(identity.city).toEqual('Berlin'); expect(identity.postalCode).toEqual('223344'); expect(identity.phone).toEqual('+49 001 222 333 44'); expect(identity.email).toEqual('test@web.de'); // remaining fields as custom fields expect(cipher.fields.length).toEqual(6); }); it('should create password history', async () => { const importer = new Importer(); const result = importer.parse(TestData); const cipher = result.ciphers.shift(); expect(cipher.passwordHistory.length).toEqual(1); const ph = cipher.passwordHistory.shift(); expect(ph.password).toEqual('old-password'); expect(ph.lastUsedDate.toISOString()).toEqual('2015-11-17T20:17:01.000Z'); }); it('should create password history from windows opvault 1pif format', async () => { const importer = new Importer(); const result = importer.parse(WindowsOpVaultTestData); const cipher = result.ciphers.shift(); expect(cipher.passwordHistory.length).toEqual(5); let ph = cipher.passwordHistory.shift(); expect(ph.password).toEqual('oldpass6'); expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:41.000Z'); ph = cipher.passwordHistory.shift(); expect(ph.password).toEqual('oldpass5'); expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:40.000Z'); ph = cipher.passwordHistory.shift(); expect(ph.password).toEqual('oldpass4'); expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:39.000Z'); ph = cipher.passwordHistory.shift(); expect(ph.password).toEqual('oldpass3'); expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:38.000Z'); ph = cipher.passwordHistory.shift(); expect(ph.password).toEqual('oldpass2'); expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:37.000Z'); }); });