Skip to content

Commit

Permalink
Keychain layer 1 draft 2
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminpreiss committed Oct 8, 2023
1 parent c45d329 commit 1cfaa37
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 23 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ IMPORTANT: Peerbit uses yarn.
3. Build: `yarn build`
4. Run tests: `yarn test`

You might possibly need to CMD + Shift + P and then enter to restart the typescript server after the build step.

To create a new package, follow the following steps:

1. Clone the time folder within /packages/utils/time to the desired destination and rename it
Expand Down
6 changes: 5 additions & 1 deletion packages/utils/crypto/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export * from "./key.js";
export * from "./ed25519.js";
export * from "./signature.js";
export * from "./key.js";
export * from "./sepc256k1.js";
export * from "./x25519.js";
export * from "./encryption.js";
Expand All @@ -11,6 +10,11 @@ export * from "./hash.js";
export * from "./random.js";
export * from "./prehash.js";
export * from "./signer.js";
<<<<<<< Updated upstream
=======
export * from "./keychain.js";
export * from "./xsalsa20poly1305.js";
>>>>>>> Stashed changes
import libsodium from "libsodium-wrappers";
const ready = libsodium.ready; // TODO can we export ready directly ?
export { ready };
25 changes: 24 additions & 1 deletion packages/utils/crypto/src/key.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { serialize } from "@dao-xyz/borsh";
import { field, serialize } from "@dao-xyz/borsh";
import { sha256Base64Sync } from "./hash.js";
import { PeerId } from "@libp2p/interface/peer-id";
import { compare } from "@peerbit/uint8arrays";
import { toHexString } from "./utils";

interface Key {
equals(other: Key): boolean;
Expand All @@ -20,6 +22,8 @@ export abstract class Keypair {
toPeerId(): Promise<PeerId> {
throw new Error("Not implemented");
}

// TODO: Should we add not implemented errors for .create and and .from as well?
}

// ---- SIGNATURE KEYS -----
Expand Down Expand Up @@ -78,3 +82,22 @@ export abstract class PlainKey implements Key {
return this._hashcode || (this._hashcode = sha256Base64Sync(this.bytes));
}
}

export class ByteKey extends PlainKey {
@field({ type: Uint8Array })
key: Uint8Array;

constructor(properties: { key: Uint8Array }) {
super();
this.key = properties.key;
}

equals(other: ByteKey) {
return compare(this.key, other.key) === 0;
}

// TODO: What should be preprended to this string here?
toString(): string {
return "bytekey/" + toHexString(this.key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { toHexString } from "./utils";
import sodium from "libsodium-wrappers";

@variant(0)
export class Aes256Key extends PlainKey {
export class XSalsa20Poly1305 extends PlainKey {
@field({ type: fixedArray("u8", 32) })
key: Uint8Array;

Expand All @@ -18,23 +18,23 @@ export class Aes256Key extends PlainKey {
this.key = properties.key;
}

static async create(): Promise<Aes256Key> {
static async create(): Promise<XSalsa20Poly1305> {
await sodium.ready;
const generated = sodium.crypto_secretbox_keygen();
const kp = new Aes256Key({
const kp = new XSalsa20Poly1305({
key: generated
});

return kp;
}

equals(other: Aes256Key): boolean {
if (other instanceof Aes256Key) {
equals(other: PlainKey): boolean {
if (other instanceof XSalsa20Poly1305) {
return compare(this.key, other.key) === 0;
}
return false;
}
toString(): string {
return "aes256/" + toHexString(this.key);
return "xsalsa20poly1305/" + toHexString(this.key);
}
}
56 changes: 41 additions & 15 deletions packages/utils/keychain/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,73 @@
import {
Ed25519Keypair,
X25519Keypair,
Aes256Key,
Keypair,
XSalsa20Poly1305,
Ed25519PublicKey,
X25519PublicKey
X25519PublicKey,
ByteKey,
Secp256k1Keypair,
Secp256k1PublicKey,
PublicKeyEncryptionKey,
PublicSignKey
} from "@peerbit/crypto";

export type KeypairFromPublicKey<T> = T extends X25519PublicKey
? X25519PublicKey extends T
? X25519Keypair
: Ed25519Keypair
: Ed25519Keypair;
? X25519Keypair
: T extends Ed25519PublicKey
? Ed25519Keypair
: T extends Secp256k1PublicKey
? Secp256k1Keypair
: T extends PublicSignKey | PublicKeyEncryptionKey
? Keypair
: never;

export interface Keychain {
// Add a key to the keychain.
// Represents keys internally as X25519 and Aes256.
// Transforms Ed25519 keys to X25519 keys internally?
import(
parameters: (
| { keypair: Ed25519Keypair | X25519Keypair }
| { key: Aes256Key }
| { keypair: Ed25519Keypair | X25519Keypair | Secp256k1Keypair | Keypair }
| { key: XSalsa20Poly1305 | ByteKey }
) & { id: Uint8Array }
): Promise<void>;

// This is only really relevant for asymmetric keys? -> No changes
exportByKey<
T extends Ed25519PublicKey | X25519PublicKey,
T extends
| Ed25519PublicKey
| X25519PublicKey
| Secp256k1PublicKey
| PublicSignKey
| PublicKeyEncryptionKey,
Q = KeypairFromPublicKey<T>
>(
publicKey: T
): Promise<Q | undefined>;

// ID's are the sha256 hashes of the public key (or the symmetric key itself)
// ID's are the sha256base hashes of the public key (or the symmetric key itself)
// Throws if no key can be found of type `type` with id `id`?
// If type is undefined, just return any bytekey.
exportById<
T = "ed25519" | "x25519" | "aes256",
T =
| "ed25519"
| "x25519"
| "secp256k1"
| "xsalsa20poly1305"
| "bytekey"
| "keypair",
Q = T extends "ed25519"
? Ed25519Keypair
: T extends "x25519"
? X25519Keypair
: Aes256Key
: T extends "secp256k1"
? Secp256k1Keypair
: T extends "keypair"
? Keypair
: T extends "xsalsa20poly1305"
? XSalsa20Poly1305
: ByteKey
>(
id: Uint8Array,
id: string,
type: T
): Promise<Q | undefined>;
}

0 comments on commit 1cfaa37

Please sign in to comment.