npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ssc-hermes/identity

v0.0.6

Published

An identity record

Downloads

10

Readme

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'