Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: essr support #4

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/keri/app/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ export class Controller {
const signers = [];
for (const prx of prxs) {
const cipher = new Cipher({ qb64: prx });
const dsigner = decrypter.decrypt(null, cipher, true);
const dsigner = decrypter.decrypt(null, cipher, null,true);
signers.push(dsigner);
nprxs.push(encrypter.encrypt(b(dsigner.qb64)).qb64);
}
Expand Down
15 changes: 9 additions & 6 deletions src/keri/core/cipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ export class Cipher extends Matter {
}
super({ raw: raw, code: code, qb64b: qb64b, qb64: qb64, qb2: qb2 });

if (
!Array.from([
MtrDex.X25519_Cipher_Salt,
MtrDex.X25519_Cipher_Seed,
]).includes(this.code)
) {
if (!this.code || ![
MtrDex.X25519_Cipher_Salt, MtrDex.X25519_Cipher_Seed,
MtrDex.X25519_Cipher_L0, MtrDex.X25519_Cipher_L1, MtrDex.X25519_Cipher_L2,
MtrDex.X25519_Cipher_Big_L0, MtrDex.X25519_Cipher_Big_L1, MtrDex.X25519_Cipher_Big_L2,
MtrDex.X25519_Cipher_QB64_L0, MtrDex.X25519_Cipher_QB64_L1, MtrDex.X25519_Cipher_QB64_L2,
MtrDex.X25519_Cipher_QB64_Big_L0, MtrDex.X25519_Cipher_QB64_Big_L1, MtrDex.X25519_Cipher_QB64_Big_L2,
MtrDex.X25519_Cipher_QB2_L0, MtrDex.X25519_Cipher_QB2_L1, MtrDex.X25519_Cipher_QB2_L2,
MtrDex.X25519_Cipher_QB2_Big_L0, MtrDex.X25519_Cipher_QB2_Big_L1, MtrDex.X25519_Cipher_QB2_Big_L2
].includes(this.code)) {
throw new Error(`Unsupported Cipher code == ${this.code}`);
}
}
Expand Down
53 changes: 38 additions & 15 deletions src/keri/core/decrypter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import libsodium from 'libsodium-wrappers-sumo';

import { Matter, MatterArgs, MtrDex } from './matter';
import {ciXAllQB64Dex, ciXVarQB2Dex, ciXVarStrmDex, Matter, MatterArgs, MtrDex} from './matter';
import { Signer } from './signer';
import { Cipher } from './cipher';
import { EmptyMaterialError } from './kering';
import { Salter } from './salter';
import {Streamer} from "./streamer";

export class Decrypter extends Matter {
private readonly _decrypt: any;
Expand Down Expand Up @@ -47,34 +48,56 @@ export class Decrypter extends Matter {
}

decrypt(
ser: Uint8Array | null = null,
ser: Uint8Array | null = null, // qb64b
cipher: Cipher | null = null,
transferable: boolean = false
klas = null,
transferable: boolean = false,
bare: boolean = false
) {
if (ser == null && cipher == null) {
throw new EmptyMaterialError('Neither ser or cipher were provided');
}

if (ser != null) {
cipher = new Cipher({ qb64b: ser });
if (!cipher){
if (ser != null) {
cipher = new Cipher({ qb64b: ser });
} else {
throw new Error(`Need one of cipher or qb64`);
}
}

return this._decrypt(cipher, this.raw, transferable);
return this._decrypt(cipher, this.raw, klas, transferable, bare);
}

_x25519(cipher: Cipher, prikey: Uint8Array, transferable: boolean = false) {
_x25519(cipher: Cipher, prikey: Uint8Array, Klas?: typeof Matter | typeof Streamer, transferable: boolean = false, bare: boolean = false) {
const pubkey = libsodium.crypto_scalarmult_base(prikey);
const plain = libsodium.crypto_box_seal_open(
cipher.raw,
pubkey,
prikey
);
if (cipher.code == MtrDex.X25519_Cipher_Salt) {
return new Salter({ qb64b: plain });
} else if (cipher.code == MtrDex.X25519_Cipher_Seed) {
return new Signer({ qb64b: plain, transferable: transferable });

if (bare) {
return plain
} else {
throw new Error(`Unsupported cipher text code == ${cipher.code}`);
if (!Klas) {
if (cipher.code === MtrDex.X25519_Cipher_Salt){
Klas = Salter;
} else if (cipher.code === MtrDex.X25519_Cipher_Seed) {
Klas = Signer;
} else if (ciXVarStrmDex.includes(cipher.code)){
Klas = Streamer;
} else {
throw new Error(`Unsupported cipher code = ${cipher.code} when klas missing.`);
}
}

if (ciXAllQB64Dex.includes(cipher.code)) {
// @ts-ignore
return new Klas({qb64b: plain, transferable});
} else if (ciXVarStrmDex.includes(cipher.code)){
// @ts-ignore
return new Klas(plain)
} else {
throw new Error(`Unsupported cipher code = ${cipher.code}.`);
}
}
}
}
43 changes: 30 additions & 13 deletions src/keri/core/encrypter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import libsodium from 'libsodium-wrappers-sumo';

import { Matter, MatterArgs, MtrDex } from './matter';
import {ciXAllQB64Dex, ciXVarStrmDex, Matter, MatterArgs, MatterCodex, MtrDex} from './matter';
import { Verfer } from './verfer';
import { Signer } from './signer';
import { Cipher } from './cipher';
import { arrayEquals } from './utils';
import {Streamer} from "./streamer";

export class Encrypter extends Matter {
private _encrypt: any;
Expand Down Expand Up @@ -44,23 +45,39 @@ export class Encrypter extends Matter {
return arrayEquals(pubkey, this.raw);
}

encrypt(ser: Uint8Array | null = null, matter: Matter | null = null) {
if (ser == null && matter == null) {
throw new Error('Neither ser nor matter are provided.');
}
encrypt(ser: Uint8Array | null = null, matter: Matter | Streamer | null = null, code: string | null = null) {

if (!ser) {
if (!matter){
throw new Error('Neither ser nor matter are provided.');
}

if (ser != null) {
matter = new Matter({ qb64b: ser });
if (!code) {
if (!(matter instanceof Matter) || matter.code == MtrDex.Salt_128){
code = MtrDex.X25519_Cipher_Salt;
} else if (matter.code == MtrDex.Ed25519_Seed){
code = MtrDex.X25519_Cipher_Seed;
} else {
throw new Error(`Unsupported primitive with code = ${matter.code} when cipher code is missing`);
}
}

if (ciXAllQB64Dex.includes(code)) {
if (matter instanceof Matter) {
ser = matter.qb64b;
}
} else if (ciXVarStrmDex.includes(code)){
ser = (matter as Streamer).stream;
} else {
throw new Error(`Invalid primitive cipher ${(matter instanceof Matter) ? matter.code : matter.stream} not qb64`);
}
}

let code;
if (matter!.code == MtrDex.Salt_128) {
code = MtrDex.X25519_Cipher_Salt;
} else {
code = MtrDex.X25519_Cipher_Seed;
if (!code) { // assumes default is sniffable stream
code = MtrDex.X25519_Cipher_L0;
}

return this._encrypt(matter!.qb64, this.raw, code);
return this._encrypt(ser, this.raw, code);
}

_x25519(ser: Uint8Array, pubkey: Uint8Array, code: string) {
Expand Down
13 changes: 8 additions & 5 deletions src/keri/core/keeping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,9 @@ export class RandyKeeper implements Keeper {

this.signers = this.prxs.map((prx) =>
this.decrypter.decrypt(
new Cipher({ qb64: prx }).qb64b,
undefined,
null,
new Cipher({ qb64: prx }),
null,
this.transferable
)
);
Expand Down Expand Up @@ -567,8 +568,9 @@ export class RandyKeeper implements Keeper {

const signers = this.nxts!.map((nxt) =>
this.decrypter.decrypt(
undefined,
null,
new Cipher({ qb64: nxt }),
null,
this.transferable
)
);
Expand Down Expand Up @@ -600,8 +602,9 @@ export class RandyKeeper implements Keeper {
): Promise<SignResult> {
const signers = this.prxs!.map((prx) =>
this.decrypter.decrypt(
new Cipher({ qb64: prx }).qb64b,
undefined,
null,
new Cipher({ qb64: prx }),
null,
this.transferable
)
);
Expand Down
4 changes: 2 additions & 2 deletions src/keri/core/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ class Keeper implements KeyStore {
const out = new Array<[string, Signer]>();
this._pris.forEach(function (val, pubKey) {
const verfer = new Verfer({ qb64: pubKey });
const signer = decrypter.decrypt(val, null, verfer.transferable);
const signer = decrypter.decrypt(val, null, null, verfer.transferable);
out.push([pubKey, signer]);
});
return out;
Expand All @@ -1104,7 +1104,7 @@ class Keeper implements KeyStore {
}
const verfer = new Verfer({ qb64: pubKey });

return decrypter.decrypt(val, null, verfer.transferable);
return decrypter.decrypt(val, null, null, verfer.transferable);
}

pinPths(pubKey: string, val: PubPath): boolean {
Expand Down
102 changes: 102 additions & 0 deletions src/keri/core/matter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,64 @@ export class MatterCodex extends Codex {
StrB64_Big_L0: string = '7AAA'; // String Base64 Only Big Lead Size 0
StrB64_Big_L1: string = '8AAA'; // String Base64 Only Big Lead Size 1
StrB64_Big_L2: string = '9AAA'; // String Base64 Only Big Lead Size 2
Bytes_L0: string = '4B'; // Byte String Lead Size 0
Bytes_L1: string = '5B'; // Byte String Lead Size 1
Bytes_L2: string = '6B'; // Byte String Lead Size 2
Bytes_Big_L0: string = '7AAB'; // Byte String Big Lead Size 0
Bytes_Big_L1: string = '8AAB'; // Byte String Big Lead Size 1
Bytes_Big_L2: string = '9AAB'; // Byte String Big Lead Size 2
X25519_Cipher_L0: string = '4C' // X25519 sealed box cipher bytes of sniffable stream plaintext lead size 0
X25519_Cipher_L1: string = '5C' // X25519 sealed box cipher bytes of sniffable stream plaintext lead size 1
X25519_Cipher_L2: string = '6C' // X25519 sealed box cipher bytes of sniffable stream plaintext lead size 2
X25519_Cipher_Big_L0: string = '7AAC' // X25519 sealed box cipher bytes of sniffable stream plaintext big lead size 0
X25519_Cipher_Big_L1: string = '8AAC' // X25519 sealed box cipher bytes of sniffable stream plaintext big lead size 1
X25519_Cipher_Big_L2: string = '9AAC' // X25519 sealed box cipher bytes of sniffable stream plaintext big lead size 2
X25519_Cipher_QB64_L0: string = '4D' // X25519 sealed box cipher bytes of QB64 plaintext lead size 0
X25519_Cipher_QB64_L1: string = '5D' // X25519 sealed box cipher bytes of QB64 plaintext lead size 1
X25519_Cipher_QB64_L2: string = '6D' // X25519 sealed box cipher bytes of QB64 plaintext lead size 2
X25519_Cipher_QB64_Big_L0: string = '7AAD' // X25519 sealed box cipher bytes of QB64 plaintext big lead size 0
X25519_Cipher_QB64_Big_L1: string = '8AAD' // X25519 sealed box cipher bytes of QB64 plaintext big lead size 1
X25519_Cipher_QB64_Big_L2: string = '9AAD' // X25519 sealed box cipher bytes of QB64 plaintext big lead size 2
X25519_Cipher_QB2_L0: string = '4E' // X25519 sealed box cipher bytes of QB2 plaintext lead size 0
X25519_Cipher_QB2_L1: string = '5E' // X25519 sealed box cipher bytes of QB2 plaintext lead size 1
X25519_Cipher_QB2_L2: string = '6E' // X25519 sealed box cipher bytes of QB2 plaintext lead size 2
X25519_Cipher_QB2_Big_L0: string = '7AAE' // X25519 sealed box cipher bytes of QB2 plaintext big lead size 0
X25519_Cipher_QB2_Big_L1: string = '8AAE' // X25519 sealed box cipher bytes of QB2 plaintext big lead size 1
X25519_Cipher_QB2_Big_L2: string = '9AAE' // X25519 sealed box cipher bytes of QB2 plaintext big lead size 2
}

export const MtrDex = new MatterCodex();

export const ciXAllQB64Dex = [
MtrDex.X25519_Cipher_Seed,
MtrDex.X25519_Cipher_Salt,
MtrDex.X25519_Cipher_QB64_L0,
MtrDex.X25519_Cipher_QB64_L1,
MtrDex.X25519_Cipher_QB64_L2,
MtrDex.X25519_Cipher_QB64_Big_L0,
MtrDex.X25519_Cipher_QB64_Big_L1,
MtrDex.X25519_Cipher_QB64_Big_L2
]

export const ciXVarQB2Dex = [
MtrDex.X25519_Cipher_QB2_L0,
MtrDex.X25519_Cipher_QB2_L1,
MtrDex.X25519_Cipher_QB2_L2,
MtrDex.X25519_Cipher_QB2_Big_L0,
MtrDex.X25519_Cipher_QB2_Big_L1,
MtrDex.X25519_Cipher_QB2_Big_L2
]

export const ciXVarStrmDex = [
MtrDex.X25519_Cipher_L0,
MtrDex.X25519_Cipher_L1,
MtrDex.X25519_Cipher_L2,
MtrDex.X25519_Cipher_Big_L0,
MtrDex.X25519_Cipher_Big_L1,
MtrDex.X25519_Cipher_Big_L2
]


export class NonTransCodex extends Codex {
Ed25519N: string = 'B'; // Ed25519 verification key non-transferable, basic derivation.
ECDSA_256k1N: string = '1AAA'; // ECDSA secp256k1 verification key non-transferable, basic derivation.
Expand Down Expand Up @@ -180,6 +234,24 @@ export class Matter {
'7AAB': new Sizage(4, 4, undefined, 0),
'8AAB': new Sizage(4, 4, undefined, 1),
'9AAB': new Sizage(4, 4, undefined, 2),
'4C': new Sizage(2, 2, undefined, 0),
'5C': new Sizage(2, 2, undefined, 1),
'6C': new Sizage(2, 2, undefined, 2),
'7AAC': new Sizage(4, 4, undefined, 0),
'8AAC': new Sizage(4, 4, undefined, 1),
'9AAC': new Sizage(4, 4, undefined, 2),
'4D': new Sizage(2, 2, undefined, 0),
'5D': new Sizage(2, 2, undefined, 1),
'6D': new Sizage(2, 2, undefined, 2),
'7AAD': new Sizage(4, 4, undefined, 0),
'8AAD': new Sizage(4, 4, undefined, 1),
'9AAD': new Sizage(4, 4, undefined, 2),
'4E': new Sizage(2, 2, undefined, 0),
'5E': new Sizage(2, 2, undefined, 1),
'6E': new Sizage(2, 2, undefined, 2),
'7AAE': new Sizage(4, 4, undefined, 0),
'8AAE': new Sizage(4, 4, undefined, 1),
'9AAE': new Sizage(4, 4, undefined, 2)
})
);

Expand Down Expand Up @@ -518,4 +590,34 @@ export class Matter {
private _bexfil(qb2: Uint8Array) {
throw new Error(`qb2 not yet supported: ${qb2}`);
}

static determineMatterCode(length: number, format: string): string {
const isQB64 = format === 'qb64';
const isQB2 = format === 'qb2';

if (length <= Matter._rawSize(MtrDex.X25519_Cipher_L2)) {
if (isQB64) {
return (length % 3 === 0) ? MtrDex.X25519_Cipher_QB64_L0 :
(length % 3 === 1) ? MtrDex.X25519_Cipher_QB64_L1 : MtrDex.X25519_Cipher_QB64_L2;
} else if (isQB2) {
return (length % 3 === 0) ? MtrDex.X25519_Cipher_QB2_L0 :
(length % 3 === 1) ? MtrDex.X25519_Cipher_QB2_L1 : MtrDex.X25519_Cipher_QB2_L2;
} else {
return (length % 3 === 0) ? MtrDex.X25519_Cipher_L0 :
(length % 3 === 1) ? MtrDex.X25519_Cipher_L1 : MtrDex.X25519_Cipher_L2;
}
} else {
if (isQB64) {
return (length % 3 === 0) ? MtrDex.X25519_Cipher_QB64_Big_L0 :
(length % 3 === 1) ? MtrDex.X25519_Cipher_QB64_Big_L1 : MtrDex.X25519_Cipher_QB64_Big_L2;
} else if (isQB2) {
return (length % 3 === 0) ? MtrDex.X25519_Cipher_QB2_Big_L0 :
(length % 3 === 1) ? MtrDex.X25519_Cipher_QB2_Big_L1 : MtrDex.X25519_Cipher_QB2_Big_L2;
} else {
return (length % 3 === 0) ? MtrDex.X25519_Cipher_Big_L0 :
(length % 3 === 1) ? MtrDex.X25519_Cipher_Big_L1 : MtrDex.X25519_Cipher_Big_L2;
}
}
}

}
Loading
Loading