0.0.6 • Published 8 months ago

@ssc-hermes/identity v0.0.6

Weekly downloads
-
License
AGPL-3.0-or-later
Repository
github
Last release
8 months ago

identity tests

This is an object representing a user. An Identity object contains a collection of "devices", where each device has several keypairs. This depends on each device having a keystore that stores the private keys.

We can do e2e encryption by creating a symmetric key, then encrypting that key to each device. So the symmetric key is encrypted with the public key of each device.

Each device has a primary keypair used for signing, which is did here, and also an "exchange" keypair, which is used for encrypting & decrypting things. In the Device record there is also an index aes, which is the symmetrical key that has been encrypted to the device's exchange key.

see also, keystore as used in crypto component

Devices are indexed by a sufficiently random key, created by calling createDeviceName with the primary did for the device.


Sending a private messaesge to an identity would mean encrypting a message with a new symmetric key. That means encrypting n versions of the symmetric key, one for each device in the other identity.

So there you can think of it like one conversation = 1 symmetric key. The person initiating the conversation needs to know the exchange keys of the other party.

storage

This is storage agnostic. You would want to save the identity object to a database or something, which is easy to do because keys are encrypted "at rest". Any device record pairs with a keystore instance on the device.


install

npm i -S @ssc-hermes/identity

types

Identity

interface Identity {
    humanName:string,  // a human readble name for the identity
    username:string,  // the random string for the root device. Not human-readable
    rootDid:string  // The DID of the first device to use this identity
    devices:Record<string, Device>  // a map of devices in this identity
}

Device

interface Device {
    name:string,  // the random string for this device
    did:string,  // primary DID for the device. Used to sign things
    aes:string,  /* the symmetric key for this account, encrypted to the
        exchange key for this device */
    exchange:string  // public key used for encrypting & decrypting
}

test

Tests run in node because we are using @ssc-hermes/node-components.

npm test

example

import { test } from '@socketsupply/tapzero'
import { writeKeyToDid } from '@ssc-hermes/util'
import { components, createCryptoComponent } from '@ssc-hermes/node-components'
import { Crypto } from '@oddjs/odd'
import { aesEncrypt, aesDecrypt } from
    '@oddjs/odd/components/crypto/implementation/browser'
import { fromString, toString } from 'uint8arrays'
import {
    create, decryptKey, Identity, ALGORITHM, add,
    createDeviceName, encryptTo, CurriedEncrypt
} from '@ssc-hermes/identity'

create an identity

let identity:Identity
let rootDid:string
let crypto:Crypto.Implementation
let rootDeviceName:string

test('create an identity', async t => {
    crypto = components.crypto
    rootDid = await writeKeyToDid(crypto)

    identity = await create(crypto, {
        humanName: 'alice',
    })

    const deviceName = await createDeviceName(rootDid)
    rootDeviceName = deviceName
    t.ok(identity, 'should return a new identity')
    t.ok(identity.devices[deviceName].aes,
        'should map the symmetric key, indexed by device name')
})

use the keys to encrypt and decrypt

test('can use the keys', async t => {
    // test that you can encrypt & decrypt with the symmetric key
    //   saved in identity

    // first decrypt the key
    const aes = identity.devices[rootDeviceName].aes
    const decryptedKey = await decryptKey(crypto, aes)
    t.ok(decryptedKey instanceof CryptoKey, 'decryptKey should return a CryptoKey')

    // now use it to encrypt a string
    const encryptedString = await aesEncrypt(
        fromString('hello'), decryptedKey, ALGORITHM)

    t.ok(encryptedString instanceof Uint8Array,
        'should return a Uint8Array when you encrypt a string')

    // now decrypt the string
    const decrypted = toString(
        await aesDecrypt(encryptedString, decryptedKey, ALGORITHM)
    )

    t.equal(decrypted, 'hello', 'can decrypt the original string')
})

get your device's name

import { createDeviceName } from '@ssc-hermes/identity'
// create an odd program...
const myDid = await program.agentDID()
const myDeviceName = createDeviceName(myDid)
// => '4k4z2xpgpmmssbcasqanlaxoxtpppl54'
0.0.5

10 months ago

0.0.4

10 months ago

0.0.6

8 months ago

0.0.3

11 months ago

0.0.2

12 months ago

0.0.1

12 months ago

0.0.0

12 months ago