New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@consento/crypto

Package Overview
Dependencies
Maintainers
3
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@consento/crypto - npm Package Compare versions

Comparing version 0.6.0 to 0.7.0

primitives/SignVector.d.ts

6

blob/index.d.ts
import { IEncryptedBlob, IEncryptedBlobJSON } from '../types';
import { IEncodable } from '../util/types';
import { INamedCodec } from '@consento/codecs';
export declare function isEncryptedBlob(input: any): input is IEncryptedBlob;
export declare function toEncryptedBlob(input: string | Uint8Array | IEncryptedBlob | IEncryptedBlobJSON): IEncryptedBlob;
export declare function encryptBlob(encodable: IEncodable): {
export declare function encryptBlob<TType = any>(encodable: TType, codec?: INamedCodec<string, TType>): {
blob: IEncryptedBlob;
encrypted: Uint8Array;
};
export declare function decryptBlob(secretKey: Uint8Array, encrypted: Uint8Array): IEncodable;
export declare function decryptBlob<TType = any>(secretKey: Uint8Array, encrypted: Uint8Array, codec?: INamedCodec<string, TType>): TType;

@@ -21,2 +21,5 @@ "use strict";

};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -28,2 +31,3 @@ exports.decryptBlob = exports.encryptBlob = exports.toEncryptedBlob = exports.isEncryptedBlob = void 0;

const sodium = __importStar(require("sodium-universal"));
const codecs_1 = __importDefault(require("@consento/codecs"));
const { crypto_kdf_CONTEXTBYTES: CRYPTO_KDF_CONTEXTBYTES, crypto_kdf_BYTES_MAX: CRYPTO_KDF_BYTES_MAX, crypto_kdf_derive_from_key: kdfDeriveFromKey, sodium_malloc: malloc } = sodium.default;

@@ -99,6 +103,6 @@ const deriveContext = types_1.Buffer.from('conotify');

exports.toEncryptedBlob = toEncryptedBlob;
function encryptBlob(encodable) {
function encryptBlob(encodable, codec = codecs_1.default.msgpack) {
const secretKey = secretbox_1.createSecret();
const path = pathForSecretKey(secretKey);
const encrypted = secretbox_1.encrypt(secretKey, encodable);
const encrypted = secretbox_1.encrypt(secretKey, codec.encode(encodable));
return {

@@ -110,6 +114,6 @@ blob: newBlob(secretKey, path, encrypted.length),

exports.encryptBlob = encryptBlob;
function decryptBlob(secretKey, encrypted) {
return secretbox_1.decrypt(secretKey, encrypted);
function decryptBlob(secretKey, encrypted, codec = codecs_1.default.msgpack) {
return codec.decode(secretbox_1.decrypt(secretKey, encrypted));
}
exports.decryptBlob = decryptBlob;
//# sourceMappingURL=index.js.map
import { Buffer } from '../util';
import { IHandshakeInit, IReader, IHandshakeInitOptions, IHandshakeAccept, IHandshakeAcceptMessage, IHandshakeAcceptOptions, IHandshakeConfirmation, IHandshakeAcceptJSON, IHandshakeConfirmationOptions, IHandshakeConfirmationJSON, IConnection, IHandshakeInitJSON } from '../types';
import { Connection } from '../primitives';
import { IHandshakeInit, IReader, IHandshakeInitOptions, IHandshakeAccept, IHandshakeAcceptMessage, IHandshakeAcceptOptions, IHandshakeConfirmation, IHandshakeAcceptJSON, IHandshakeConfirmationOptions, IHandshakeConfirmationJSON, IConnection, IHandshakeInitJSON, MsgPackCodec, IWriter } from '../types';
export declare const HANDSHAKE_MSG_VERSION: Buffer;
export declare class HandshakeInit implements IHandshakeInit {
input: IReader;
input: IReader<MsgPackCodec>;
firstMessage: Uint8Array;

@@ -13,11 +12,16 @@ handshakeSecret: Uint8Array;

}
export declare class HandshakeAccept extends Connection implements IHandshakeAccept {
export declare class HandshakeAccept implements IHandshakeAccept {
acceptMessage: IHandshakeAcceptMessage;
constructor(ops: IHandshakeAcceptOptions);
input: IReader<MsgPackCodec>;
output: IWriter<MsgPackCodec>;
connectionKey: Uint8Array;
_connectionKeyBase64?: string;
constructor(opts: IHandshakeAcceptOptions);
get connectionKeyBase64(): string;
toJSON(): IHandshakeAcceptJSON;
finalize(message: Uint8Array): IConnection;
finalize(message: Uint8Array): IConnection<MsgPackCodec, MsgPackCodec>;
}
export declare class HandshakeConfirmation implements IHandshakeConfirmation {
finalMessage: Uint8Array;
connection: IConnection;
connection: IConnection<MsgPackCodec, MsgPackCodec>;
constructor(opts: IHandshakeConfirmationOptions);

@@ -24,0 +28,0 @@ toJSON(): IHandshakeConfirmationJSON;

@@ -41,13 +41,22 @@ "use strict";

}
function processHandshake(msg) {
if (msg[0] !== exports.HANDSHAKE_MSG_VERSION[0]) {
throw Object.assign(new Error(`Error while processing handshake: Unknown handshake format: ${msg[0]}`), { code: 'unknown-message-format', messageFormat: msg[0] });
const handshakeCodec = {
name: 'handshake',
encode: ({ token, writerKey }) => util_1.Buffer.concat([exports.HANDSHAKE_MSG_VERSION, token, writerKey]),
decode: msg => {
if (msg[0] !== exports.HANDSHAKE_MSG_VERSION[0]) {
throw Object.assign(new Error(`Error while processing handshake: Unknown handshake format: ${msg[0]}`), { code: 'unknown-message-format', messageFormat: msg[0] });
}
if (msg.length !== 161) {
throw Object.assign(new Error(`Error while processing handshake: Invalid handshake size: ${msg.length}`), { code: 'invalid-size', size: msg.length });
}
return {
token: msg.slice(1, 33),
writerKey: msg.slice(33)
};
}
if (msg.length !== 161) {
throw Object.assign(new Error(`Error while processing handshake: Invalid handshake size: ${msg.length}`), { code: 'invalid-size', size: msg.length });
}
return {
token: msg.slice(1, 33),
writerKey: msg.slice(33)
};
};
function remove(input, prop) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete input[prop];
return input;
}

@@ -62,3 +71,3 @@ class HandshakeInit {

return {
input: this.input.toJSON(),
input: remove(this.input.toJSON(), 'codec'),
firstMessage: util_1.bufferToString(this.firstMessage, 'base64'),

@@ -71,11 +80,8 @@ handshakeSecret: util_1.bufferToString(this.handshakeSecret, 'base64')

const backChannel = primitives_1.createChannel();
const sendKey = secretbox_1.decrypt(secretKey, util_1.Buffer.from(accept.secret, 'base64'));
if (!(sendKey instanceof Uint8Array)) {
throw Object.assign(new Error(`Expected buffer in decrypted message, got: ${sendKey.constructor.name}`), { code: 'invalid-message', sendKey });
}
const writerKey = secretbox_1.decrypt(secretKey, util_1.Buffer.from(accept.secret, 'base64'));
return new HandshakeConfirmation({
connection: new primitives_1.Connection({
output: new primitives_1.Writer({ writerKey: sendKey }),
connectionKey: new primitives_1.Connection({
output: new primitives_1.Writer({ writerKey: writerKey }),
input: backChannel.reader
}),
}).connectionKey,
// In case you are wondering why we not just simply return "backChannel" as sender

@@ -90,9 +96,22 @@ // but instead pass it in two messages: the reason is that without this step

exports.HandshakeInit = HandshakeInit;
class HandshakeAccept extends primitives_1.Connection {
constructor(ops) {
super(ops);
this.acceptMessage = ops.acceptMessage;
class HandshakeAccept {
constructor(opts) {
const parts = primitives_1.getIOFromConnectionOptions(opts);
this.input = parts.input;
this.output = parts.output;
this.connectionKey = parts.connectionKey;
this._connectionKeyBase64 = parts.connectionKeyBase64;
this.acceptMessage = opts.acceptMessage;
}
get connectionKeyBase64() {
if (this._connectionKeyBase64 === undefined) {
this._connectionKeyBase64 = util_1.bufferToString(this.connectionKey, 'base64');
}
return this._connectionKeyBase64;
}
toJSON() {
return Object.assign(Object.assign({}, super.toJSON()), { acceptMessage: this.acceptMessage });
return {
connectionKey: this.connectionKeyBase64,
acceptMessage: this.acceptMessage
};
}

@@ -102,3 +121,3 @@ finalize(message) {

input: this.input,
output: new primitives_1.Writer({ writerKey: message })
output: { writerKey: message }
});

@@ -110,3 +129,3 @@ }

constructor(opts) {
this.connection = new primitives_1.Connection(opts.connection);
this.connection = new primitives_1.Connection({ connectionKey: opts.connectionKey });
this.finalMessage = util_1.toBuffer(opts.finalMessage);

@@ -116,3 +135,3 @@ }

return {
connection: this.connection.toJSON(),
connectionKey: this.connection.connectionKeyBase64,
finalMessage: util_1.bufferToString(this.finalMessage, 'base64')

@@ -129,7 +148,3 @@ };

handshakeSecret: handshake.secretKey,
firstMessage: util_1.Buffer.concat([
exports.HANDSHAKE_MSG_VERSION,
handshake.publicKey,
channel.writer.writerKey
])
firstMessage: handshakeCodec.encode({ token: handshake.publicKey, writerKey: channel.writer.writerKey })
});

@@ -139,3 +154,3 @@ }

function acceptHandshake(firstMessage) {
const { token, writerKey } = processHandshake(firstMessage);
const { token, writerKey } = handshakeCodec.decode(firstMessage);
const handshake = createHandshake();

@@ -145,4 +160,4 @@ const secretKey = computeSecret(handshake.secretKey, token);

return new HandshakeAccept({
output: { writerKey },
input: receiver,
output: writerKey,
input: receiver.readerKey,
acceptMessage: {

@@ -149,0 +164,0 @@ token: util_1.bufferToString(handshake.publicKey, 'base64'),

{
"name": "@consento/crypto",
"version": "0.6.0",
"version": "0.7.0",
"description": "Crypto functionality used in Consento",

@@ -10,2 +10,4 @@ "main": "index.js",

"dependencies": {
"@consento/codecs": "^1.0.0",
"@msgpack/msgpack": "^2.3.0",
"abort-controller": "^3.0.0",

@@ -12,0 +14,0 @@ "buffer": "^5.6.0",

import { IVerifier, IReader, IWriter, IChannel, IChannelJSON, IChannelOptions } from '../types';
import { Inspectable } from '../util';
import { InspectOptions } from 'inspect-custom-symbol';
export declare function createChannel(): Channel;
export declare class Channel extends Inspectable implements IChannel {
_reader?: IReader;
_writer?: IWriter;
_channelKey?: Uint8Array;
import { Codec, CodecOption } from '@consento/codecs';
export declare class Channel<TCodec extends CodecOption = undefined> extends Inspectable implements IChannel<Codec<TCodec, 'msgpack'>> {
reader: IReader<Codec<TCodec, 'msgpack'>>;
writer: IWriter<Codec<TCodec, 'msgpack'>>;
channelKey: Uint8Array;
_channelKeyBase64?: string;
constructor({ channelKey }: IChannelOptions);
constructor({ channelKey, inVector, outVector, codec }: IChannelOptions<TCodec>);
recodec<TCodec extends CodecOption = undefined>(codec: TCodec): IChannel<Codec<TCodec, 'msgpack'>>;
get codec(): Codec<TCodec, 'msgpack'>;
get verifyKey(): Uint8Array;
get verifyKeyBase64(): string;
get verifyKeyHex(): string;
get channelKey(): Uint8Array;
get channelKeyBase64(): string;
get reader(): IReader;
get writer(): IWriter;
get verifier(): IVerifier;
_inspect(_: number, { stylize }: InspectOptions): string;
toJSON(): IChannelJSON;
toJSON(): IChannelJSON<Codec<TCodec, 'msgpack'>>;
}
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -25,42 +6,32 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

Object.defineProperty(exports, "__esModule", { value: true });
exports.Channel = exports.createChannel = void 0;
exports.Channel = void 0;
const util_1 = require("../util");
const Reader_1 = require("./Reader");
const Writer_1 = require("./Writer");
const sodium = __importStar(require("sodium-universal"));
const key_1 = require("./key");
const pretty_hash_1 = __importDefault(require("pretty-hash"));
const { sodium_malloc: malloc, crypto_box_PUBLICKEYBYTES: CRYPTO_BOX_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES: CRYPTO_BOX_SECRETKEYBYTES, crypto_box_keypair: boxKeyPair, crypto_sign_PUBLICKEYBYTES: CRYPTO_SIGN_PUBLICKEYBYTES, crypto_sign_SECRETKEYBYTES: CRYPTO_SIGN_SECRETKEYBYTES, crypto_sign_keypair: signKeyPair } = sodium.default;
function createEncryptionKeys() {
const keys = {
publicKey: malloc(CRYPTO_BOX_PUBLICKEYBYTES),
privateKey: malloc(CRYPTO_BOX_SECRETKEYBYTES)
};
boxKeyPair(keys.publicKey, keys.privateKey);
return keys;
}
function createSignKeys() {
const keys = {
publicKey: malloc(CRYPTO_SIGN_PUBLICKEYBYTES),
privateKey: malloc(CRYPTO_SIGN_SECRETKEYBYTES)
};
signKeyPair(keys.publicKey, keys.privateKey);
return keys;
}
function createChannel() {
const encrypt = createEncryptionKeys();
const sign = createSignKeys();
return new Channel({ channelKey: util_1.Buffer.concat([encrypt.publicKey, sign.publicKey, encrypt.privateKey, sign.privateKey]) });
}
exports.createChannel = createChannel;
class Channel extends util_1.Inspectable {
constructor({ channelKey }) {
constructor({ channelKey, inVector, outVector, codec }) {
super();
if (typeof channelKey === 'string') {
this._channelKeyBase64 = channelKey;
this.channelKey = util_1.toBuffer(channelKey);
}
else {
this._channelKey = channelKey;
this.channelKey = channelKey;
}
this.reader = new Reader_1.Reader({ readerKey: key_1.readerKeyFromChannelKey(this.channelKey), inVector, codec });
this.writer = new Writer_1.Writer({ writerKey: key_1.writerKeyFromChannelKey(this.channelKey), outVector, codec });
}
recodec(codec) {
return new Channel({
channelKey: this.channelKey,
inVector: this.reader.inVector,
outVector: this.writer.outVector,
codec
});
}
get codec() {
return this.reader.codec;
}
get verifyKey() {

@@ -75,26 +46,8 @@ return this.reader.verifyKey;

}
get channelKey() {
if (this._channelKey === undefined) {
this._channelKey = util_1.toBuffer(this._channelKeyBase64);
}
return this._channelKey;
}
get channelKeyBase64() {
if (this._channelKeyBase64 === undefined) {
this._channelKeyBase64 = util_1.bufferToString(this._channelKey, 'base64');
this._channelKeyBase64 = util_1.bufferToString(this.channelKey, 'base64');
}
return this._channelKeyBase64;
}
get reader() {
if (this._reader === undefined) {
this._reader = new Reader_1.Reader({ readerKey: key_1.readerKeyFromChannelKey(this.channelKey) });
}
return this._reader;
}
get writer() {
if (this._writer === undefined) {
this._writer = new Writer_1.Writer({ writerKey: key_1.writerKeyFromChannelKey(this.channelKey) });
}
return this._writer;
}
get verifier() {

@@ -105,7 +58,11 @@ return this.reader.verifier;

// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Channel(${stylize(pretty_hash_1.default(this.reader.verifyKey), 'string')})`;
return `Channel(${stylize(this.codec.name, 'special')}|${stylize(pretty_hash_1.default(this.reader.verifyKey), 'string')})`;
}
toJSON() {
var _a, _b;
return {
channelKey: this.channelKeyBase64
channelKey: this.channelKeyBase64,
inVector: (_a = this.reader.inVector) === null || _a === void 0 ? void 0 : _a.toJSON(),
outVector: (_b = this.writer.outVector) === null || _b === void 0 ? void 0 : _b.toJSON(),
codec: this.reader.codec.name
};

@@ -112,0 +69,0 @@ }

import { IConnection, IReader, IWriter, IConnectionJSON, IConnectionOptions } from '../types';
import { Inspectable } from '../util';
import { InspectOptions } from 'inspect-custom-symbol';
export declare class Connection extends Inspectable implements IConnection {
_input?: IReader;
_output?: IWriter;
_connectionKey?: Uint8Array;
import { Codec, CodecOption } from '@consento/codecs';
export declare function getIOFromConnectionOptions<TInputCodec extends CodecOption = undefined, TOutputCodec extends CodecOption = undefined>(opts: IConnectionOptions<TInputCodec, TOutputCodec>): {
connectionKey: Uint8Array;
connectionKeyBase64?: string;
input: IReader<Codec<TInputCodec, 'msgpack'>>;
output: IWriter<Codec<TOutputCodec, 'msgpack'>>;
};
export declare class Connection<TInputCodec extends CodecOption = undefined, TOutputCodec extends CodecOption = undefined> extends Inspectable implements IConnection<Codec<TInputCodec, 'msgpack'>, Codec<TOutputCodec, 'msgpack'>> {
input: IReader<Codec<TInputCodec, 'msgpack'>>;
output: IWriter<Codec<TOutputCodec, 'msgpack'>>;
connectionKey: Uint8Array;
_connectionKeyBase64?: string;
constructor(opts: IConnectionOptions);
get connectionKey(): Uint8Array;
constructor(opts: IConnectionOptions<TInputCodec, TOutputCodec>);
get connectionKeyBase64(): string;
get input(): IReader;
get output(): IWriter;
toJSON(): IConnectionJSON;
toJSON(): IConnectionJSON<Codec<TInputCodec, 'msgpack'>, Codec<TOutputCodec, 'msgpack'>>;
_inspect(_: number, { stylize }: InspectOptions): string;
}

@@ -6,3 +6,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Connection = void 0;
exports.Connection = exports.getIOFromConnectionOptions = void 0;
const Reader_1 = require("./Reader");

@@ -14,18 +14,63 @@ const Writer_1 = require("./Writer");

const pretty_hash_1 = __importDefault(require("pretty-hash"));
function isConnectionOptionsByKey(input) {
return 'connectionKey' in input;
}
function isConnectionOptionsByIO(input) {
return 'input' in input && 'output' in input;
}
function getIOFromConnectionOptions(opts) {
let readerKey;
let writerKey;
let inCodec = opts.inCodec;
let outCodec = opts.outCodec;
let inVector = opts.inVector;
let outVector = opts.outVector;
let connectionKey;
let connectionKeyBase64;
if (isConnectionOptionsByKey(opts)) {
if (typeof opts.connectionKey === 'string') {
connectionKeyBase64 = opts.connectionKey;
}
connectionKey = buffer_1.toBuffer(opts.connectionKey);
readerKey = key_1.inReaderKeyFromConnectionKey(connectionKey);
writerKey = key_1.outWriterKeyFromConnectionKey(connectionKey);
}
else if (isConnectionOptionsByIO(opts)) {
if (buffer_1.isStringOrBuffer(opts.input)) {
readerKey = buffer_1.toBuffer(opts.input);
}
else {
readerKey = buffer_1.toBuffer(opts.input.readerKey);
inVector = inVector !== null && inVector !== void 0 ? inVector : opts.input.inVector;
inCodec = inCodec !== null && inCodec !== void 0 ? inCodec : opts.input.codec;
}
if (buffer_1.isStringOrBuffer(opts.output)) {
writerKey = buffer_1.toBuffer(opts.output);
}
else {
writerKey = buffer_1.toBuffer(opts.output.writerKey);
outVector = outVector !== null && outVector !== void 0 ? outVector : opts.output.outVector;
outCodec = outCodec !== null && outCodec !== void 0 ? outCodec : opts.output.codec;
}
connectionKey = util_1.Buffer.concat([readerKey, writerKey]);
}
else {
throw new Error('Options for connection invalid, either connectionKey or input/output must be given.');
}
return {
connectionKey,
connectionKeyBase64,
input: new Reader_1.Reader({ readerKey, inVector, codec: inCodec }),
output: new Writer_1.Writer({ writerKey, outVector, codec: outCodec })
};
}
exports.getIOFromConnectionOptions = getIOFromConnectionOptions;
class Connection extends util_1.Inspectable {
constructor(opts) {
super();
if ('connectionKey' in opts) {
if (typeof opts.connectionKey === 'string') {
this._connectionKeyBase64 = opts.connectionKey;
}
else {
this._connectionKey = opts.connectionKey;
}
}
else {
this._input = buffer_1.isStringOrBuffer(opts.input) ? new Reader_1.Reader({ readerKey: opts.input }) : 'readerKey' in opts.input ? new Reader_1.Reader(opts.input) : opts.input;
this._output = buffer_1.isStringOrBuffer(opts.output) ? new Writer_1.Writer({ writerKey: opts.output }) : 'writerKey' in opts.output ? new Writer_1.Writer(opts.output) : opts.output;
this._connectionKey = util_1.Buffer.concat([this._input.readerKey, this._output.writerKey]);
}
const parts = getIOFromConnectionOptions(opts);
this.input = parts.input;
this.output = parts.output;
this.connectionKey = parts.connectionKey;
this._connectionKeyBase64 = parts.connectionKeyBase64;
if (buffer_1.bufferEquals(this.input.verifyKey, this.output.verifyKey)) {

@@ -35,29 +80,16 @@ throw new Error('Can not create a connection with both the writer and the reader have the same id! Did you mean to restore a channel?');

}
get connectionKey() {
if (this._connectionKey === undefined) {
this._connectionKey = buffer_1.toBuffer(this._connectionKeyBase64);
}
return this._connectionKey;
}
get connectionKeyBase64() {
if (this._connectionKeyBase64 === undefined) {
this._connectionKeyBase64 = buffer_1.bufferToString(this._connectionKey, 'base64');
this._connectionKeyBase64 = buffer_1.bufferToString(this.connectionKey, 'base64');
}
return this._connectionKeyBase64;
}
get input() {
if (this._input === undefined) {
this._input = new Reader_1.Reader({ readerKey: key_1.inReaderKeyFromConnectionKey(this.connectionKey) });
}
return this._input;
}
get output() {
if (this._output === undefined) {
this._output = new Writer_1.Writer({ writerKey: key_1.outWriterKeyFromConnectionKey(this.connectionKey) });
}
return this._output;
}
toJSON() {
var _a, _b;
return {
connectionKey: this.connectionKeyBase64
connectionKey: this.connectionKeyBase64,
inCodec: this.input.codec.name,
outCodec: this.output.codec.name,
inVector: (_a = this.input.inVector) === null || _a === void 0 ? void 0 : _a.toJSON(),
outVector: (_b = this.output.outVector) === null || _b === void 0 ? void 0 : _b.toJSON()
};

@@ -67,3 +99,12 @@ }

// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Connection(input=${stylize(pretty_hash_1.default(this.input.verifyKey), 'string')}, output=${stylize(pretty_hash_1.default(this.output.verifyKey), 'string')})`;
let input = `input=${stylize(this.input.codec.name, 'special')}|${stylize(pretty_hash_1.default(this.input.verifyKey), 'string')}`;
if (this.input.inVector !== undefined) {
input += `#${this.input.inVector.index}`;
}
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
let output = `output=${stylize(this.output.codec.name, 'special')}|${stylize(pretty_hash_1.default(this.output.verifyKey), 'string')}`;
if (this.output.outVector !== undefined) {
output += `#${this.output.outVector.index}`;
}
return `Connection(${input}, ${output})`;
}

@@ -70,0 +111,0 @@ }

@@ -1,7 +0,15 @@

import { IEncryptedMessage } from '../types';
import { IEncodable } from '../util/types';
export declare function encryptMessage(writeKey: Uint8Array, message: IEncodable): Uint8Array;
import { IChannelOptions, IEncryptedMessage, IEncryptionKeys, ISignKeys, ISignVector } from '../types';
import { Channel } from './Channel';
import { CodecOption } from '@consento/codecs';
export declare function createEncryptionKeys(): IEncryptionKeys;
export declare function createSignKeys(): ISignKeys;
export declare function encryptMessage(writeKey: Uint8Array, message: any): Uint8Array;
export declare function verify(verifyKey: Uint8Array, signature: Uint8Array, body: Uint8Array): boolean;
export declare function verifyMessage(verifyKey: Uint8Array, message: IEncryptedMessage): boolean;
export declare function decryptMessage(verifyKey: Uint8Array, writeKey: Uint8Array, readKey: Uint8Array, message: IEncryptedMessage | Uint8Array): IEncodable;
export declare function decryptMessage(verifyKey: Uint8Array, writeKey: Uint8Array, readKey: Uint8Array, message: IEncryptedMessage | Uint8Array): any;
export declare function sign(signKey: Uint8Array, body: Uint8Array): Uint8Array;
export declare function createSignVectors(): {
inVector: ISignVector;
outVector: ISignVector;
};
export declare function createChannel<TCodec extends CodecOption = undefined>(opts?: Omit<IChannelOptions<TCodec>, 'channelKey'>): Channel<TCodec>;

@@ -22,9 +22,30 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.sign = exports.decryptMessage = exports.verifyMessage = exports.verify = exports.encryptMessage = void 0;
exports.createChannel = exports.createSignVectors = exports.sign = exports.decryptMessage = exports.verifyMessage = exports.verify = exports.encryptMessage = exports.createSignKeys = exports.createEncryptionKeys = void 0;
const types_1 = require("../types");
const sodium = __importStar(require("sodium-universal"));
const buffer_1 = require("../util/buffer");
const { crypto_box_SEALBYTES: CRYPTO_BOX_SEALBYTES, crypto_sign_BYTES: CRYPTO_SIGN_BYTES, crypto_box_seal_open: boxSealOpen, crypto_box_seal: boxSeal, crypto_sign_verify_detached: _verify, crypto_sign_detached: signDetached, sodium_malloc: malloc } = sodium.default;
const msgpack_1 = require("@msgpack/msgpack");
const Channel_1 = require("./Channel");
const buffer_1 = require("buffer");
const SignVector_1 = require("./SignVector");
const { crypto_box_PUBLICKEYBYTES: CRYPTO_BOX_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES: CRYPTO_BOX_SECRETKEYBYTES, crypto_box_SEALBYTES: CRYPTO_BOX_SEALBYTES, crypto_box_seal: boxSeal, crypto_box_seal_open: boxSealOpen, crypto_box_keypair: boxKeyPair, crypto_sign_BYTES: CRYPTO_SIGN_BYTES, crypto_sign_PUBLICKEYBYTES: CRYPTO_SIGN_PUBLICKEYBYTES, crypto_sign_SECRETKEYBYTES: CRYPTO_SIGN_SECRETKEYBYTES, crypto_sign_keypair: signKeyPair, crypto_sign_detached: signDetached, crypto_sign_verify_detached: _verify, sodium_malloc: malloc } = sodium.default;
function createEncryptionKeys() {
const keys = {
encryptKey: malloc(CRYPTO_BOX_PUBLICKEYBYTES),
decryptKey: malloc(CRYPTO_BOX_SECRETKEYBYTES)
};
boxKeyPair(keys.encryptKey, keys.decryptKey);
return keys;
}
exports.createEncryptionKeys = createEncryptionKeys;
function createSignKeys() {
const keys = {
verifyKey: malloc(CRYPTO_SIGN_PUBLICKEYBYTES),
signKey: malloc(CRYPTO_SIGN_SECRETKEYBYTES)
};
signKeyPair(keys.verifyKey, keys.signKey);
return keys;
}
exports.createSignKeys = createSignKeys;
function encryptMessage(writeKey, message) {
const msgBuffer = buffer_1.anyToBuffer(message);
const msgBuffer = msgpack_1.encode(message);
const body = malloc(msgBuffer.length + CRYPTO_BOX_SEALBYTES);

@@ -59,3 +80,3 @@ boxSeal(body, msgBuffer, writeKey);

}
return buffer_1.bufferToAny(messageDecrypted);
return msgpack_1.decode(messageDecrypted);
}

@@ -69,2 +90,16 @@ exports.decryptMessage = decryptMessage;

exports.sign = sign;
function createSignVectors() {
const keys = createSignKeys();
return {
inVector: new SignVector_1.SignVector({ next: keys.verifyKey }),
outVector: new SignVector_1.SignVector({ next: keys.signKey })
};
}
exports.createSignVectors = createSignVectors;
function createChannel(opts) {
const encrypt = createEncryptionKeys();
const sign = createSignKeys();
return new Channel_1.Channel(Object.assign({ channelKey: buffer_1.Buffer.concat([encrypt.encryptKey, sign.verifyKey, encrypt.decryptKey, sign.signKey]) }, opts));
}
exports.createChannel = createChannel;
//# sourceMappingURL=fn.js.map

@@ -1,5 +0,6 @@

import { IVerifier, IReader, IReaderJSON, IEncryptedMessage, IReaderOptions } from '../types';
import { IEncodable, Inspectable } from '../util';
import { IVerifier, IReader, IReaderJSON, IEncryptedMessage, IReaderOptions, ISignVector } from '../types';
import { Inspectable } from '../util';
import { InspectOptions } from 'inspect-custom-symbol';
export declare class Reader extends Inspectable implements IReader {
import { Codec, CodecOption } from '@consento/codecs';
export declare class Reader<TCodec extends CodecOption = undefined> extends Inspectable implements IReader<Codec<TCodec, 'msgpack'>> {
_receiveKey?: Uint8Array;

@@ -10,3 +11,6 @@ _receiveKeyBase64?: string;

_verifier?: IVerifier;
constructor({ readerKey: receiveKey }: IReaderOptions);
inVector?: ISignVector;
codec: Codec<TCodec, 'msgpack'>;
constructor({ readerKey, inVector, codec }: IReaderOptions<TCodec>);
recodec<TCodec extends CodecOption = undefined>(codec: TCodec): IReader<Codec<TCodec, 'msgpack'>>;
get verifyKey(): Uint8Array;

@@ -20,6 +24,7 @@ get verifyKeyHex(): string;

get readerKeyBase64(): string;
toJSON(): IReaderJSON;
toJSON(): IReaderJSON<Codec<TCodec, 'msgpack'>>;
_inspect(_: number, { stylize }: InspectOptions): string;
encryptOnly(message: IEncodable): Uint8Array;
decrypt(encrypted: IEncryptedMessage): IEncodable;
encryptOnly(message: any): Uint8Array;
decrypt(encrypted: IEncryptedMessage): any;
decryptNext(encrypted: IEncryptedMessage): any;
}

@@ -7,2 +7,3 @@ "use strict";

exports.Reader = void 0;
const types_1 = require("../types");
const Verifier_1 = require("./Verifier");

@@ -13,12 +14,33 @@ const key_1 = require("./key");

const pretty_hash_1 = __importDefault(require("pretty-hash"));
const msgpack_1 = require("@msgpack/msgpack");
const SignVector_1 = require("./SignVector");
const codecs_1 = __importDefault(require("@consento/codecs"));
function assertVectoredMessage(input) {
if (!Array.isArray(input)) {
throw Object.assign(new Error('Message needs to be an array'), { code: types_1.EDecryptionError.invalidMessage });
}
if (input.length === 0) {
throw Object.assign(new Error('The next structure needs to have a body.'), { code: types_1.EDecryptionError.missingBody });
}
if (input.length === 1) {
throw Object.assign(new Error('The next structure needs to have a signature.'), { code: types_1.EDecryptionError.missingSignature });
}
}
class Reader extends util_1.Inspectable {
constructor({ readerKey: receiveKey }) {
constructor({ readerKey, inVector, codec }) {
super();
if (typeof receiveKey === 'string') {
this._receiveKeyBase64 = receiveKey;
if (typeof readerKey === 'string') {
this._receiveKeyBase64 = readerKey;
}
else {
this._receiveKey = receiveKey;
this._receiveKey = readerKey;
}
if (util_1.exists(inVector)) {
this.inVector = new SignVector_1.SignVector(inVector);
}
this.codec = codecs_1.default(codec, 'msgpack');
}
recodec(codec) {
return new Reader({ readerKey: this.readerKey, inVector: this.inVector, codec });
}
get verifyKey() {

@@ -64,7 +86,13 @@ return this.verifier.verifyKey;

toJSON() {
return { readerKey: this.readerKeyBase64 };
var _a;
return {
readerKey: this.readerKeyBase64,
inVector: (_a = this.inVector) === null || _a === void 0 ? void 0 : _a.toJSON(),
codec: this.codec.name
};
}
_inspect(_, { stylize }) {
const vector = this.inVector !== undefined ? `#${this.inVector.index}` : '';
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Reader(${stylize(pretty_hash_1.default(this.verifyKey), 'string')})`;
return `Reader(${stylize(this.codec.name, 'special')}|${stylize(pretty_hash_1.default(this.verifyKey), 'string')}${vector})`;
}

@@ -77,4 +105,14 @@ encryptOnly(message) {

}
decryptNext(encrypted) {
if (this.inVector === undefined) {
return this.decrypt(encrypted);
}
const raw = msgpack_1.decode(this.decrypt(encrypted));
assertVectoredMessage(raw);
const [body, signature] = raw;
this.inVector.verify(body, signature);
return msgpack_1.decode(body);
}
}
exports.Reader = Reader;
//# sourceMappingURL=Reader.js.map

@@ -1,11 +0,15 @@

import { IVerifier, IWriter, IWriterJSON, IEncryptedMessage, IWriterOptions } from '../types';
import { IEncodable, Inspectable } from '../util';
import { IVerifier, IWriter, IWriterJSON, IEncryptedMessage, IWriterOptions, ISignVector } from '../types';
import { Inspectable } from '../util';
import { InspectOptions } from 'inspect-custom-symbol';
export declare class Writer extends Inspectable implements IWriter {
_sendKey?: Uint8Array;
_sendKeyBase64?: string;
import { Codec, CodecOption } from '@consento/codecs';
export declare class Writer<TCodec extends CodecOption = undefined> extends Inspectable implements IWriter<Codec<TCodec, 'msgpack'>> {
_writerKey?: Uint8Array;
_writerKeyBase64?: string;
_annonymous?: IVerifier;
_signKey?: Uint8Array;
_encryptKey?: Uint8Array;
constructor({ writerKey: sendKey }: IWriterOptions);
outVector?: ISignVector;
codec: Codec<TCodec, 'msgpack'>;
constructor({ writerKey, outVector, codec }: IWriterOptions<TCodec>);
recodec<TCodec extends CodecOption = undefined>(codec: TCodec): IWriter<Codec<TCodec, 'msgpack'>>;
get signKey(): Uint8Array;

@@ -19,7 +23,9 @@ get encryptKey(): Uint8Array;

get verifier(): IVerifier;
toJSON(): IWriterJSON;
toJSON(): IWriterJSON<Codec<TCodec, 'msgpack'>>;
_inspect(_: number, { stylize }: InspectOptions): string;
sign(data: Uint8Array): Uint8Array;
encryptOnly(message: IEncodable): Uint8Array;
encrypt(message: IEncodable): IEncryptedMessage;
encryptOnly(message: any): Uint8Array;
encrypt(message: any): IEncryptedMessage;
encryptNext(message: any): IEncryptedMessage;
encryptOnlyNext(message: any): Uint8Array;
}

@@ -12,12 +12,22 @@ "use strict";

const pretty_hash_1 = __importDefault(require("pretty-hash"));
const SignVector_1 = require("./SignVector");
const msgpack_1 = require("@msgpack/msgpack");
const codecs_1 = __importDefault(require("@consento/codecs"));
class Writer extends util_1.Inspectable {
constructor({ writerKey: sendKey }) {
constructor({ writerKey, outVector, codec }) {
super();
if (typeof sendKey === 'string') {
this._sendKeyBase64 = sendKey;
if (typeof writerKey === 'string') {
this._writerKeyBase64 = writerKey;
}
else {
this._sendKey = sendKey;
this._writerKey = writerKey;
}
if (util_1.exists(outVector)) {
this.outVector = new SignVector_1.SignVector(outVector);
}
this.codec = codecs_1.default(codec, 'msgpack');
}
recodec(codec) {
return new Writer({ writerKey: this.writerKey, outVector: this.outVector, codec });
}
get signKey() {

@@ -36,12 +46,12 @@ if (this._signKey === undefined) {

get writerKey() {
if (this._sendKey === undefined) {
this._sendKey = util_1.toBuffer(this._sendKeyBase64);
if (this._writerKey === undefined) {
this._writerKey = util_1.toBuffer(this._writerKeyBase64);
}
return this._sendKey;
return this._writerKey;
}
get writerKeyBase64() {
if (this._sendKeyBase64 === undefined) {
this._sendKeyBase64 = util_1.bufferToString(this._sendKey, 'base64');
if (this._writerKeyBase64 === undefined) {
this._writerKeyBase64 = util_1.bufferToString(this._writerKey, 'base64');
}
return this._sendKeyBase64;
return this._writerKeyBase64;
}

@@ -64,7 +74,13 @@ get verifyKey() {

toJSON() {
return { writerKey: this.writerKeyBase64 };
var _a;
return {
writerKey: this.writerKeyBase64,
outVector: (_a = this.outVector) === null || _a === void 0 ? void 0 : _a.toJSON(),
codec: this.codec.name
};
}
_inspect(_, { stylize }) {
const vector = this.outVector !== undefined ? `#${this.outVector.index}` : '';
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Writer(${stylize(pretty_hash_1.default(this.verifyKey), 'string')})`;
return `Writer(${stylize(this.codec.name, 'special')}|${stylize(pretty_hash_1.default(this.verifyKey), 'string')}${vector})`;
}

@@ -84,4 +100,21 @@ sign(data) {

}
encryptNext(message) {
const body = this.encryptOnlyNext(message);
return {
signature: this.sign(body),
body
};
}
encryptOnlyNext(message) {
if (this.outVector === undefined) {
return this.encryptOnly(message);
}
const body = msgpack_1.encode(message);
return this.encryptOnly(msgpack_1.encode([
body,
this.outVector.sign(body)
]));
}
}
exports.Writer = Writer;
//# sourceMappingURL=Writer.js.map

@@ -25,2 +25,6 @@ # @consento/crypto

- `Handshake` - the process to connect two separate processes/devices resulting in a `Connection` for each process.
- `SignVector` - operations on a `Channel` **may** be `vectored` with means that there is a new sign/verify keypair for every new message.
The `SignVector` holds the `index` and current `sign` or `verify` key.
- `Codec` - Data written by a reader or read by a writer will be transported binary (`Uint8Array`), a `Codec` specifies how an object read
or written will be translated from/to binary data.

@@ -58,2 +62,26 @@ ## Sending/Receiving encrypted messages

To make sure that the order of the encrypted messages is maintained you can use `SignVector`s that will rotate the signing
key for each message.
```javascript
const { createSignVectors } = require('@consento/crypto')
const { inVector, outVector } = createSignVectors()
const message = Buffer.from('hello world')
const sigA = outVector.sign(message)
const sigB = outVector.sign(message) // Both signatures are different!j
inVector.verify(message, sigA)
inVector.verify(message, sigB) // The signatures need to be verified in order, else an exception will be thrown
// Using the in-/outVector in combination with readers and writers will affect the `encryptNext`, `decryptNext` operation
const { reader, writer } = createChannel()
reader.inVector = inVector
writer.outVector = outVector
const encrypted = writer.encryptNext('hello world') // With the inVector and outVector set, the order is maintained
const message = reader.decryptNext(encrypted) // This would thrown an error if the signature can't be verified
```
All objects created using `createChannel` are well de-/serializable:

@@ -72,2 +100,17 @@

## Codecs
Any data sent out through `Writer`s or `Reader`s is encoded using mechanism, by default it will be using `msgpack`
but you can specify any codec supported by [`@consento/codecs`](https://github.com/consento-org/codecs).
```js
const { createChannel } = require('@consento/crypto')
const { writer } = createChannel({ codec: 'json' }) //
writer.encrypt({ foo: 'hello' }) // Changes the binary format to be utf-8 encoded JSON data.
const differentCodec = new Writer({ ...writer.toJSON(), codec: 'msgpack' })
writer.encrypt({ foo: 'hello' }) // Looks same but the binary data is now encoded using msgpack
```
### .verifier

@@ -86,3 +129,3 @@

Encrypt and sign a given input with the sender key.
Encrypt and sign a given input with the `encryptKey` and `signKey`.

@@ -109,2 +152,51 @@ - `body` - what you like to encrypt, any serializable object is possible

#### signVector.sign(message)
- `message` - an `Uint8Array` that should be signed.
```javascript
const { outVector } = createSignVectors()
inVector.verify('hello world')
```
#### signVector.verify(message, signature)
- `message` - an `Uint8Array` with the message for the signature
- `signature` - an `Uint8Array` that contains the signature
```javascript
const { inVector } = createSignVectors()
inVector.verify(message, signature)
```
#### writer.outVector, reader.inVector
An optional property which enables vectored encryption in `writer.encryptNext` and
`writer.encryptNextOnly` and `reader.decryptNext` respectively.
#### writer.encryptNext(body)
If an `.outVector` is present, this method will add a signature from the `outVector` to
the data before encrypting and signing the data, else behaves same as `writer.encrypt`.
- `body` - what you like to encrypt, any serializable object is possible
```javascript
const encrypted = writer.encryptNext('secret message')
encrypted.signature // Uint8Array
encrypted.body // Uint8Array
```
#### writer.encryptNextOnly(body)
If an `.outVector` is present, this method will add a signature from the `outVector` to
the data before encrypting the data, else it behaves same as `writer.encryptOnly`.
- `body` - what you like to encrypt, any serializable object is possible
```javascript
const encrypted = writer.encryptNextOnly('secret message')
encrypted // Uint8Array with an encrypted message
```
#### writer.sign(data)

@@ -154,2 +246,9 @@

#### reader.decryptNext(encrypted)
If an `.inVector` is present, this method will verify the signature using the `inVector` to
the data after decrypting the data, else it behaves same as `writer.decrypt`.
- `encrypted` - `{ signature: Uint8Array, body: Uint8Array }` as created by `writer.encryptNext` or `Uint8Array` created with `writer.encryptNextOnly`
## Creating a handshake

@@ -156,0 +255,0 @@

import { IEncryptedBlob, IEncryptedBlobJSON } from '../types'
import { bufferToString } from '../util/buffer'
import { Buffer, IEncodable } from '../util/types'
import { Buffer } from '../util/types'
import { encrypt, decrypt, createSecret } from '../util/secretbox'
import * as sodium from 'sodium-universal'
import codecs, { INamedCodec } from '@consento/codecs'

@@ -89,6 +90,6 @@ const {

export function encryptBlob (encodable: IEncodable): { blob: IEncryptedBlob, encrypted: Uint8Array } {
export function encryptBlob <TType = any> (encodable: TType, codec: INamedCodec<string, TType> = codecs.msgpack): { blob: IEncryptedBlob, encrypted: Uint8Array } {
const secretKey = createSecret()
const path = pathForSecretKey(secretKey)
const encrypted = encrypt(secretKey, encodable)
const encrypted = encrypt(secretKey, codec.encode(encodable))
return {

@@ -100,4 +101,4 @@ blob: newBlob(secretKey, path, encrypted.length),

export function decryptBlob (secretKey: Uint8Array, encrypted: Uint8Array): IEncodable {
return decrypt(secretKey, encrypted)
export function decryptBlob <TType = any> (secretKey: Uint8Array, encrypted: Uint8Array, codec: INamedCodec<string, TType> = codecs.msgpack): TType {
return codec.decode(decrypt(secretKey, encrypted))
}
import { Buffer, toBuffer, bufferToString, isStringOrBuffer } from '../util'
import { IHandshakeInit, IReader, IHandshakeInitOptions, IHandshakeAccept, IHandshakeAcceptMessage, IHandshakeAcceptOptions, IHandshakeConfirmation, IHandshakeAcceptJSON, IHandshakeConfirmationOptions, IHandshakeConfirmationJSON, IConnection, IHandshakeInitJSON } from '../types'
import { createChannel, Reader, Writer, Connection } from '../primitives'
import { IHandshakeInit, IReader, IHandshakeInitOptions, IHandshakeAccept, IHandshakeAcceptMessage, IHandshakeAcceptOptions, IHandshakeConfirmation, IHandshakeAcceptJSON, IHandshakeConfirmationOptions, IHandshakeConfirmationJSON, IConnection, IHandshakeInitJSON, MsgPackCodec, IWriter } from '../types'
import { createChannel, Reader, Writer, Connection, getIOFromConnectionOptions } from '../primitives'
import { randomBuffer } from '../util/randomBuffer'
import { decrypt, encrypt } from '../util/secretbox'
import * as sodium from 'sodium-universal'
import { INamedCodec } from '@consento/codecs'

@@ -29,20 +30,28 @@ const {

}
function processHandshake (msg: Uint8Array): {
token: Uint8Array
writerKey: Uint8Array
} {
if (msg[0] !== HANDSHAKE_MSG_VERSION[0]) {
throw Object.assign(new Error(`Error while processing handshake: Unknown handshake format: ${msg[0]}`), { code: 'unknown-message-format', messageFormat: msg[0] })
const handshakeCodec: INamedCodec<'handshake', { token: Uint8Array, writerKey: Uint8Array }> = {
name: 'handshake',
encode: ({ token, writerKey }) => Buffer.concat([HANDSHAKE_MSG_VERSION, token, writerKey]),
decode: msg => {
if (msg[0] !== HANDSHAKE_MSG_VERSION[0]) {
throw Object.assign(new Error(`Error while processing handshake: Unknown handshake format: ${msg[0]}`), { code: 'unknown-message-format', messageFormat: msg[0] })
}
if (msg.length !== 161) {
throw Object.assign(new Error(`Error while processing handshake: Invalid handshake size: ${msg.length}`), { code: 'invalid-size', size: msg.length })
}
return {
token: msg.slice(1, 33),
writerKey: msg.slice(33)
}
}
if (msg.length !== 161) {
throw Object.assign(new Error(`Error while processing handshake: Invalid handshake size: ${msg.length}`), { code: 'invalid-size', size: msg.length })
}
return {
token: msg.slice(1, 33),
writerKey: msg.slice(33)
}
}
function remove <T, TProp extends keyof T> (input: T, prop: TProp): Omit<T, TProp> {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete input[prop]
return input
}
export class HandshakeInit implements IHandshakeInit {
input: IReader
input: IReader<MsgPackCodec>
firstMessage: Uint8Array

@@ -59,3 +68,3 @@ handshakeSecret: Uint8Array

return {
input: this.input.toJSON(),
input: remove(this.input.toJSON(), 'codec'),
firstMessage: bufferToString(this.firstMessage, 'base64'),

@@ -69,11 +78,8 @@ handshakeSecret: bufferToString(this.handshakeSecret, 'base64')

const backChannel = createChannel()
const sendKey = decrypt(secretKey, Buffer.from(accept.secret, 'base64'))
if (!(sendKey instanceof Uint8Array)) {
throw Object.assign(new Error(`Expected buffer in decrypted message, got: ${sendKey.constructor.name}`), { code: 'invalid-message', sendKey })
}
const writerKey = decrypt(secretKey, Buffer.from(accept.secret, 'base64'))
return new HandshakeConfirmation({
connection: new Connection({
output: new Writer({ writerKey: sendKey }),
connectionKey: new Connection({
output: new Writer({ writerKey: writerKey }),
input: backChannel.reader
}),
}).connectionKey,
// In case you are wondering why we not just simply return "backChannel" as sender

@@ -88,13 +94,29 @@ // but instead pass it in two messages: the reason is that without this step

export class HandshakeAccept extends Connection implements IHandshakeAccept {
export class HandshakeAccept implements IHandshakeAccept {
acceptMessage: IHandshakeAcceptMessage
constructor (ops: IHandshakeAcceptOptions) {
super(ops)
this.acceptMessage = ops.acceptMessage
input: IReader<MsgPackCodec>
output: IWriter<MsgPackCodec>
connectionKey: Uint8Array
_connectionKeyBase64?: string
constructor (opts: IHandshakeAcceptOptions) {
const parts = getIOFromConnectionOptions(opts)
this.input = parts.input
this.output = parts.output
this.connectionKey = parts.connectionKey
this._connectionKeyBase64 = parts.connectionKeyBase64
this.acceptMessage = opts.acceptMessage
}
get connectionKeyBase64 (): string {
if (this._connectionKeyBase64 === undefined) {
this._connectionKeyBase64 = bufferToString(this.connectionKey, 'base64')
}
return this._connectionKeyBase64
}
toJSON (): IHandshakeAcceptJSON {
return {
...super.toJSON(),
connectionKey: this.connectionKeyBase64,
acceptMessage: this.acceptMessage

@@ -104,6 +126,6 @@ }

finalize (message: Uint8Array): IConnection {
finalize (message: Uint8Array): IConnection<MsgPackCodec, MsgPackCodec> {
return new Connection({
input: this.input,
output: new Writer({ writerKey: message })
output: { writerKey: message }
})

@@ -115,6 +137,6 @@ }

finalMessage: Uint8Array
connection: IConnection
connection: IConnection<MsgPackCodec, MsgPackCodec>
constructor (opts: IHandshakeConfirmationOptions) {
this.connection = new Connection(opts.connection)
this.connection = new Connection({ connectionKey: opts.connectionKey })
this.finalMessage = toBuffer(opts.finalMessage)

@@ -125,3 +147,3 @@ }

return {
connection: this.connection.toJSON(),
connectionKey: this.connection.connectionKeyBase64,
finalMessage: bufferToString(this.finalMessage, 'base64')

@@ -138,7 +160,3 @@ }

handshakeSecret: handshake.secretKey,
firstMessage: Buffer.concat([
HANDSHAKE_MSG_VERSION,
handshake.publicKey,
channel.writer.writerKey
])
firstMessage: handshakeCodec.encode({ token: handshake.publicKey, writerKey: channel.writer.writerKey })
})

@@ -151,3 +169,3 @@ }

writerKey
} = processHandshake(firstMessage)
} = handshakeCodec.decode(firstMessage)
const handshake = createHandshake()

@@ -157,4 +175,4 @@ const secretKey = computeSecret(handshake.secretKey, token)

return new HandshakeAccept({
output: { writerKey },
input: receiver,
output: writerKey,
input: receiver.readerKey,
acceptMessage: {

@@ -161,0 +179,0 @@ token: bufferToString(handshake.publicKey, 'base64'),

@@ -9,64 +9,41 @@ import {

} from '../types'
import { Buffer, bufferToString, toBuffer, Inspectable } from '../util'
import { bufferToString, toBuffer, Inspectable } from '../util'
import { Reader } from './Reader'
import { Writer } from './Writer'
import * as sodium from 'sodium-universal'
import { readerKeyFromChannelKey, writerKeyFromChannelKey } from './key'
import { InspectOptions } from 'inspect-custom-symbol'
import prettyHash from 'pretty-hash'
import { Codec, CodecOption } from '@consento/codecs'
const {
sodium_malloc: malloc,
crypto_box_PUBLICKEYBYTES: CRYPTO_BOX_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES: CRYPTO_BOX_SECRETKEYBYTES,
crypto_box_keypair: boxKeyPair,
crypto_sign_PUBLICKEYBYTES: CRYPTO_SIGN_PUBLICKEYBYTES,
crypto_sign_SECRETKEYBYTES: CRYPTO_SIGN_SECRETKEYBYTES,
crypto_sign_keypair: signKeyPair
} = sodium.default
interface IRawKeys {
publicKey: Uint8Array
privateKey: Uint8Array
}
function createEncryptionKeys (): IRawKeys {
const keys = {
publicKey: malloc(CRYPTO_BOX_PUBLICKEYBYTES),
privateKey: malloc(CRYPTO_BOX_SECRETKEYBYTES)
}
boxKeyPair(keys.publicKey, keys.privateKey)
return keys
}
function createSignKeys (): IRawKeys {
const keys = {
publicKey: malloc(CRYPTO_SIGN_PUBLICKEYBYTES),
privateKey: malloc(CRYPTO_SIGN_SECRETKEYBYTES)
}
signKeyPair(keys.publicKey, keys.privateKey)
return keys
}
export function createChannel (): Channel {
const encrypt = createEncryptionKeys()
const sign = createSignKeys()
return new Channel({ channelKey: Buffer.concat([encrypt.publicKey, sign.publicKey, encrypt.privateKey, sign.privateKey]) })
}
export class Channel extends Inspectable implements IChannel {
_reader?: IReader
_writer?: IWriter
_channelKey?: Uint8Array
export class Channel <TCodec extends CodecOption = undefined> extends Inspectable implements IChannel<Codec<TCodec, 'msgpack'>> {
reader: IReader<Codec<TCodec, 'msgpack'>>
writer: IWriter<Codec<TCodec, 'msgpack'>>
channelKey: Uint8Array
_channelKeyBase64?: string
constructor ({ channelKey }: IChannelOptions) {
constructor ({ channelKey, inVector, outVector, codec }: IChannelOptions<TCodec>) {
super()
if (typeof channelKey === 'string') {
this._channelKeyBase64 = channelKey
this.channelKey = toBuffer(channelKey)
} else {
this._channelKey = channelKey
this.channelKey = channelKey
}
this.reader = new Reader({ readerKey: readerKeyFromChannelKey(this.channelKey), inVector, codec })
this.writer = new Writer({ writerKey: writerKeyFromChannelKey(this.channelKey), outVector, codec })
}
recodec <TCodec extends CodecOption = undefined> (codec: TCodec): IChannel<Codec<TCodec, 'msgpack'>> {
return new Channel({
channelKey: this.channelKey,
inVector: this.reader.inVector,
outVector: this.writer.outVector,
codec
})
}
get codec (): Codec<TCodec, 'msgpack'> {
return this.reader.codec
}
get verifyKey (): Uint8Array {

@@ -84,12 +61,5 @@ return this.reader.verifyKey

get channelKey (): Uint8Array {
if (this._channelKey === undefined) {
this._channelKey = toBuffer(this._channelKeyBase64 as unknown as string)
}
return this._channelKey
}
get channelKeyBase64 (): string {
if (this._channelKeyBase64 === undefined) {
this._channelKeyBase64 = bufferToString(this._channelKey as unknown as Uint8Array, 'base64')
this._channelKeyBase64 = bufferToString(this.channelKey as unknown as Uint8Array, 'base64')
}

@@ -99,16 +69,2 @@ return this._channelKeyBase64

get reader (): IReader {
if (this._reader === undefined) {
this._reader = new Reader({ readerKey: readerKeyFromChannelKey(this.channelKey) })
}
return this._reader
}
get writer (): IWriter {
if (this._writer === undefined) {
this._writer = new Writer({ writerKey: writerKeyFromChannelKey(this.channelKey) })
}
return this._writer
}
get verifier (): IVerifier {

@@ -120,10 +76,13 @@ return this.reader.verifier

// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Channel(${stylize(prettyHash(this.reader.verifyKey), 'string')})`
return `Channel(${stylize(this.codec.name, 'special')}|${stylize(prettyHash(this.reader.verifyKey), 'string')})`
}
toJSON (): IChannelJSON {
toJSON (): IChannelJSON<Codec<TCodec, 'msgpack'>> {
return {
channelKey: this.channelKeyBase64
channelKey: this.channelKeyBase64,
inVector: this.reader.inVector?.toJSON(),
outVector: this.writer.outVector?.toJSON(),
codec: this.reader.codec.name
}
}
}

@@ -1,2 +0,2 @@

import { IConnection, IReader, IWriter, IConnectionJSON, IConnectionOptions } from '../types'
import { IConnection, IReader, IWriter, IConnectionJSON, IConnectionOptions, IConnectionOptionsByKey, IConnectionOptionsByIO } from '../types'
import { Reader } from './Reader'

@@ -9,32 +9,76 @@ import { Writer } from './Writer'

import prettyHash from 'pretty-hash'
import { Codec, CodecOption } from '@consento/codecs'
export class Connection extends Inspectable implements IConnection {
_input?: IReader
_output?: IWriter
_connectionKey?: Uint8Array
_connectionKeyBase64?: string
function isConnectionOptionsByKey (input: IConnectionOptions<any, any>): input is IConnectionOptionsByKey {
return 'connectionKey' in input
}
constructor (opts: IConnectionOptions) {
super()
if ('connectionKey' in opts) {
if (typeof opts.connectionKey === 'string') {
this._connectionKeyBase64 = opts.connectionKey
} else {
this._connectionKey = opts.connectionKey
}
function isConnectionOptionsByIO (input: IConnectionOptions<any, any>): input is IConnectionOptionsByIO {
return 'input' in input && 'output' in input
}
export function getIOFromConnectionOptions <TInputCodec extends CodecOption = undefined, TOutputCodec extends CodecOption = undefined> (opts: IConnectionOptions<TInputCodec, TOutputCodec>): {
connectionKey: Uint8Array
connectionKeyBase64?: string
input: IReader<Codec<TInputCodec, 'msgpack'>>
output: IWriter<Codec<TOutputCodec, 'msgpack'>>
} {
let readerKey: Uint8Array
let writerKey: Uint8Array
let inCodec = opts.inCodec
let outCodec = opts.outCodec
let inVector = opts.inVector
let outVector = opts.outVector
let connectionKey: Uint8Array
let connectionKeyBase64: string | undefined
if (isConnectionOptionsByKey(opts)) {
if (typeof opts.connectionKey === 'string') {
connectionKeyBase64 = opts.connectionKey
}
connectionKey = toBuffer(opts.connectionKey)
readerKey = inReaderKeyFromConnectionKey(connectionKey)
writerKey = outWriterKeyFromConnectionKey(connectionKey)
} else if (isConnectionOptionsByIO(opts)) {
if (isStringOrBuffer(opts.input)) {
readerKey = toBuffer(opts.input)
} else {
this._input = isStringOrBuffer(opts.input) ? new Reader({ readerKey: opts.input }) : 'readerKey' in opts.input ? new Reader(opts.input) : opts.input
this._output = isStringOrBuffer(opts.output) ? new Writer({ writerKey: opts.output }) : 'writerKey' in opts.output ? new Writer(opts.output) : opts.output
this._connectionKey = Buffer.concat([this._input.readerKey, this._output.writerKey])
readerKey = toBuffer(opts.input.readerKey)
inVector = inVector ?? opts.input.inVector
inCodec = inCodec ?? opts.input.codec as any
}
if (bufferEquals(this.input.verifyKey, this.output.verifyKey)) {
throw new Error('Can not create a connection with both the writer and the reader have the same id! Did you mean to restore a channel?')
if (isStringOrBuffer(opts.output)) {
writerKey = toBuffer(opts.output)
} else {
writerKey = toBuffer(opts.output.writerKey)
outVector = outVector ?? opts.output.outVector
outCodec = outCodec ?? opts.output.codec as any
}
connectionKey = Buffer.concat([readerKey, writerKey])
} else {
throw new Error('Options for connection invalid, either connectionKey or input/output must be given.')
}
return {
connectionKey,
connectionKeyBase64,
input: new Reader({ readerKey, inVector, codec: inCodec }),
output: new Writer({ writerKey, outVector, codec: outCodec })
}
}
get connectionKey (): Uint8Array {
if (this._connectionKey === undefined) {
this._connectionKey = toBuffer(this._connectionKeyBase64 as unknown as string)
export class Connection <TInputCodec extends CodecOption = undefined, TOutputCodec extends CodecOption = undefined> extends Inspectable implements IConnection<Codec<TInputCodec, 'msgpack'>, Codec<TOutputCodec, 'msgpack'>> {
input: IReader<Codec<TInputCodec, 'msgpack'>>
output: IWriter<Codec<TOutputCodec, 'msgpack'>>
connectionKey: Uint8Array
_connectionKeyBase64?: string
constructor (opts: IConnectionOptions<TInputCodec, TOutputCodec>) {
super()
const parts = getIOFromConnectionOptions(opts)
this.input = parts.input
this.output = parts.output
this.connectionKey = parts.connectionKey
this._connectionKeyBase64 = parts.connectionKeyBase64
if (bufferEquals(this.input.verifyKey, this.output.verifyKey)) {
throw new Error('Can not create a connection with both the writer and the reader have the same id! Did you mean to restore a channel?')
}
return this._connectionKey
}

@@ -44,3 +88,3 @@

if (this._connectionKeyBase64 === undefined) {
this._connectionKeyBase64 = bufferToString(this._connectionKey as unknown as Uint8Array, 'base64')
this._connectionKeyBase64 = bufferToString(this.connectionKey as unknown as Uint8Array, 'base64')
}

@@ -50,19 +94,9 @@ return this._connectionKeyBase64

get input (): IReader {
if (this._input === undefined) {
this._input = new Reader({ readerKey: inReaderKeyFromConnectionKey(this.connectionKey) })
}
return this._input
}
get output (): IWriter {
if (this._output === undefined) {
this._output = new Writer({ writerKey: outWriterKeyFromConnectionKey(this.connectionKey) })
}
return this._output
}
toJSON (): IConnectionJSON {
toJSON (): IConnectionJSON<Codec<TInputCodec, 'msgpack'>, Codec<TOutputCodec, 'msgpack'>> {
return {
connectionKey: this.connectionKeyBase64
connectionKey: this.connectionKeyBase64,
inCodec: this.input.codec.name,
outCodec: this.output.codec.name,
inVector: this.input.inVector?.toJSON(),
outVector: this.output.outVector?.toJSON()
}

@@ -73,4 +107,13 @@ }

// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Connection(input=${stylize(prettyHash(this.input.verifyKey), 'string')}, output=${stylize(prettyHash(this.output.verifyKey), 'string')})`
let input: string = `input=${stylize(this.input.codec.name, 'special')}|${stylize(prettyHash(this.input.verifyKey), 'string')}`
if (this.input.inVector !== undefined) {
input += `#${this.input.inVector.index}`
}
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
let output: string = `output=${stylize(this.output.codec.name, 'special')}|${stylize(prettyHash(this.output.verifyKey), 'string')}`
if (this.output.outVector !== undefined) {
output += `#${this.output.outVector.index}`
}
return `Connection(${input}, ${output})`
}
}

@@ -1,18 +0,45 @@

import { EDecryptionError, IEncryptedMessage } from '../types'
import { EDecryptionError, IChannelOptions, IEncryptedMessage, IEncryptionKeys, ISignKeys, ISignVector } from '../types'
import * as sodium from 'sodium-universal'
import { bufferToAny, anyToBuffer } from '../util/buffer'
import { IEncodable } from '../util/types'
import { encode, decode } from '@msgpack/msgpack'
import { Channel } from './Channel'
import { Buffer } from 'buffer'
import { SignVector } from './SignVector'
import { CodecOption } from '@consento/codecs'
const {
crypto_box_PUBLICKEYBYTES: CRYPTO_BOX_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES: CRYPTO_BOX_SECRETKEYBYTES,
crypto_box_SEALBYTES: CRYPTO_BOX_SEALBYTES,
crypto_box_seal: boxSeal,
crypto_box_seal_open: boxSealOpen,
crypto_box_keypair: boxKeyPair,
crypto_sign_BYTES: CRYPTO_SIGN_BYTES,
crypto_box_seal_open: boxSealOpen,
crypto_box_seal: boxSeal,
crypto_sign_PUBLICKEYBYTES: CRYPTO_SIGN_PUBLICKEYBYTES,
crypto_sign_SECRETKEYBYTES: CRYPTO_SIGN_SECRETKEYBYTES,
crypto_sign_keypair: signKeyPair,
crypto_sign_detached: signDetached,
crypto_sign_verify_detached: _verify,
crypto_sign_detached: signDetached,
sodium_malloc: malloc
} = sodium.default
export function encryptMessage (writeKey: Uint8Array, message: IEncodable): Uint8Array {
const msgBuffer = anyToBuffer(message)
export function createEncryptionKeys (): IEncryptionKeys {
const keys = {
encryptKey: malloc(CRYPTO_BOX_PUBLICKEYBYTES),
decryptKey: malloc(CRYPTO_BOX_SECRETKEYBYTES)
}
boxKeyPair(keys.encryptKey, keys.decryptKey)
return keys
}
export function createSignKeys (): ISignKeys {
const keys = {
verifyKey: malloc(CRYPTO_SIGN_PUBLICKEYBYTES),
signKey: malloc(CRYPTO_SIGN_SECRETKEYBYTES)
}
signKeyPair(keys.verifyKey, keys.signKey)
return keys
}
export function encryptMessage (writeKey: Uint8Array, message: any): Uint8Array {
const msgBuffer = encode(message)
const body = malloc(msgBuffer.length + CRYPTO_BOX_SEALBYTES)

@@ -31,3 +58,3 @@ boxSeal(body, msgBuffer, writeKey)

export function decryptMessage (verifyKey: Uint8Array, writeKey: Uint8Array, readKey: Uint8Array, message: IEncryptedMessage | Uint8Array): IEncodable {
export function decryptMessage (verifyKey: Uint8Array, writeKey: Uint8Array, readKey: Uint8Array, message: IEncryptedMessage | Uint8Array): any {
let bodyIn: Uint8Array

@@ -47,3 +74,3 @@ if (message instanceof Uint8Array) {

}
return bufferToAny(messageDecrypted)
return decode(messageDecrypted)
}

@@ -56,1 +83,18 @@

}
export function createSignVectors (): { inVector: ISignVector, outVector: ISignVector } {
const keys = createSignKeys()
return {
inVector: new SignVector({ next: keys.verifyKey }),
outVector: new SignVector({ next: keys.signKey })
}
}
export function createChannel <TCodec extends CodecOption = undefined> (opts?: Omit<IChannelOptions<TCodec>, 'channelKey'>): Channel<TCodec> {
const encrypt = createEncryptionKeys()
const sign = createSignKeys()
return new Channel<TCodec>({
channelKey: Buffer.concat([encrypt.encryptKey, sign.verifyKey, encrypt.decryptKey, sign.signKey]),
...opts
})
}

@@ -1,10 +0,25 @@

import { IVerifier, IReader, IReaderJSON, IEncryptedMessage, IReaderOptions } from '../types'
import { IVerifier, IReader, IReaderJSON, IEncryptedMessage, IReaderOptions, ISignVector, EDecryptionError } from '../types'
import { Verifier } from './Verifier'
import { encryptKeyFromSendOrReceiveKey, decryptKeyFromReceiveKey, verifyKeyFromSendOrReceiveKey } from './key'
import { bufferToString, IEncodable, Inspectable, toBuffer } from '../util'
import { bufferToString, exists, Inspectable, toBuffer } from '../util'
import { encryptMessage, decryptMessage } from './fn'
import { InspectOptions } from 'inspect-custom-symbol'
import prettyHash from 'pretty-hash'
import { decode } from '@msgpack/msgpack'
import { SignVector } from './SignVector'
import codecs, { Codec, CodecOption } from '@consento/codecs'
export class Reader extends Inspectable implements IReader {
function assertVectoredMessage (input: any): asserts input is [ body: Uint8Array, signature: Uint8Array ] {
if (!Array.isArray(input)) {
throw Object.assign(new Error('Message needs to be an array'), { code: EDecryptionError.invalidMessage })
}
if (input.length === 0) {
throw Object.assign(new Error('The next structure needs to have a body.'), { code: EDecryptionError.missingBody })
}
if (input.length === 1) {
throw Object.assign(new Error('The next structure needs to have a signature.'), { code: EDecryptionError.missingSignature })
}
}
export class Reader <TCodec extends CodecOption = undefined> extends Inspectable implements IReader <Codec<TCodec, 'msgpack'>> {
_receiveKey?: Uint8Array

@@ -15,12 +30,22 @@ _receiveKeyBase64?: string

_verifier?: IVerifier
inVector?: ISignVector
codec: Codec<TCodec, 'msgpack'>
constructor ({ readerKey: receiveKey }: IReaderOptions) {
constructor ({ readerKey, inVector, codec }: IReaderOptions<TCodec>) {
super()
if (typeof receiveKey === 'string') {
this._receiveKeyBase64 = receiveKey
if (typeof readerKey === 'string') {
this._receiveKeyBase64 = readerKey
} else {
this._receiveKey = receiveKey
this._receiveKey = readerKey
}
if (exists(inVector)) {
this.inVector = new SignVector(inVector)
}
this.codec = codecs(codec, 'msgpack')
}
recodec <TCodec extends CodecOption = undefined> (codec: TCodec): IReader<Codec<TCodec, 'msgpack'>> {
return new Reader({ readerKey: this.readerKey, inVector: this.inVector, codec })
}
get verifyKey (): Uint8Array {

@@ -73,16 +98,21 @@ return this.verifier.verifyKey

toJSON (): IReaderJSON {
return { readerKey: this.readerKeyBase64 }
toJSON (): IReaderJSON<Codec<TCodec, 'msgpack'>> {
return {
readerKey: this.readerKeyBase64,
inVector: this.inVector?.toJSON(),
codec: this.codec.name
}
}
_inspect (_: number, { stylize }: InspectOptions): string {
const vector = this.inVector !== undefined ? `#${this.inVector.index}` : ''
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Reader(${stylize(prettyHash(this.verifyKey), 'string')})`
return `Reader(${stylize(this.codec.name, 'special')}|${stylize(prettyHash(this.verifyKey), 'string')}${vector})`
}
encryptOnly (message: IEncodable): Uint8Array {
encryptOnly (message: any): Uint8Array {
return encryptMessage(this.encryptKey, message)
}
decrypt (encrypted: IEncryptedMessage): IEncodable {
decrypt (encrypted: IEncryptedMessage): any {
return decryptMessage(

@@ -95,2 +125,13 @@ this.verifier.verifyKey,

}
decryptNext (encrypted: IEncryptedMessage): any {
if (this.inVector === undefined) {
return this.decrypt(encrypted)
}
const raw = decode(this.decrypt(encrypted))
assertVectoredMessage(raw)
const [body, signature] = raw
this.inVector.verify(body, signature)
return decode(body)
}
}

@@ -1,25 +0,38 @@

import { IVerifier, IWriter, IWriterJSON, IEncryptedMessage, IWriterOptions } from '../types'
import { IVerifier, IWriter, IWriterJSON, IEncryptedMessage, IWriterOptions, ISignVector } from '../types'
import { Verifier } from './Verifier'
import { encryptKeyFromSendOrReceiveKey, signKeyFromSendKey, verifyKeyFromSendOrReceiveKey } from './key'
import { bufferToString, toBuffer, IEncodable, Inspectable } from '../util'
import { bufferToString, toBuffer, Inspectable, exists } from '../util'
import { encryptMessage, sign } from './fn'
import { InspectOptions } from 'inspect-custom-symbol'
import prettyHash from 'pretty-hash'
import { SignVector } from './SignVector'
import { encode } from '@msgpack/msgpack'
import codecs, { Codec, CodecOption } from '@consento/codecs'
export class Writer extends Inspectable implements IWriter {
_sendKey?: Uint8Array
_sendKeyBase64?: string
export class Writer <TCodec extends CodecOption = undefined> extends Inspectable implements IWriter<Codec<TCodec, 'msgpack'>> {
_writerKey?: Uint8Array
_writerKeyBase64?: string
_annonymous?: IVerifier
_signKey?: Uint8Array
_encryptKey?: Uint8Array
outVector?: ISignVector
codec: Codec<TCodec, 'msgpack'>
constructor ({ writerKey: sendKey }: IWriterOptions) {
constructor ({ writerKey, outVector, codec }: IWriterOptions<TCodec>) {
super()
if (typeof sendKey === 'string') {
this._sendKeyBase64 = sendKey
if (typeof writerKey === 'string') {
this._writerKeyBase64 = writerKey
} else {
this._sendKey = sendKey
this._writerKey = writerKey
}
if (exists(outVector)) {
this.outVector = new SignVector(outVector)
}
this.codec = codecs(codec, 'msgpack')
}
recodec <TCodec extends CodecOption = undefined> (codec: TCodec): IWriter<Codec<TCodec, 'msgpack'>> {
return new Writer({ writerKey: this.writerKey, outVector: this.outVector, codec })
}
get signKey (): Uint8Array {

@@ -40,13 +53,13 @@ if (this._signKey === undefined) {

get writerKey (): Uint8Array {
if (this._sendKey === undefined) {
this._sendKey = toBuffer(this._sendKeyBase64 as unknown as string)
if (this._writerKey === undefined) {
this._writerKey = toBuffer(this._writerKeyBase64 as unknown as string)
}
return this._sendKey
return this._writerKey
}
get writerKeyBase64 (): string {
if (this._sendKeyBase64 === undefined) {
this._sendKeyBase64 = bufferToString(this._sendKey as unknown as Uint8Array, 'base64')
if (this._writerKeyBase64 === undefined) {
this._writerKeyBase64 = bufferToString(this._writerKey as unknown as Uint8Array, 'base64')
}
return this._sendKeyBase64
return this._writerKeyBase64
}

@@ -73,9 +86,14 @@

toJSON (): IWriterJSON {
return { writerKey: this.writerKeyBase64 }
toJSON (): IWriterJSON<Codec<TCodec, 'msgpack'>> {
return {
writerKey: this.writerKeyBase64,
outVector: this.outVector?.toJSON(),
codec: this.codec.name
}
}
_inspect (_: number, { stylize }: InspectOptions): string {
const vector = this.outVector !== undefined ? `#${this.outVector.index}` : ''
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `Writer(${stylize(prettyHash(this.verifyKey), 'string')})`
return `Writer(${stylize(this.codec.name, 'special')}|${stylize(prettyHash(this.verifyKey), 'string')}${vector})`
}

@@ -87,7 +105,7 @@

encryptOnly (message: IEncodable): Uint8Array {
encryptOnly (message: any): Uint8Array {
return encryptMessage(this.encryptKey, message)
}
encrypt (message: IEncodable): IEncryptedMessage {
encrypt (message: any): IEncryptedMessage {
const body = encryptMessage(this.encryptKey, message)

@@ -99,2 +117,21 @@ return {

}
encryptNext (message: any): IEncryptedMessage {
const body = this.encryptOnlyNext(message)
return {
signature: this.sign(body),
body
}
}
encryptOnlyNext (message: any): Uint8Array {
if (this.outVector === undefined) {
return this.encryptOnly(message)
}
const body = encode(message)
return this.encryptOnly(encode([
body,
this.outVector.sign(body)
]))
}
}
/* eslint-disable @typescript-eslint/method-signature-style */
import { IEncodable, IStringOrBuffer } from './util/types'
import codecs, { Codec, CodecOption, INamedCodec } from '@consento/codecs'
import { IStringOrBuffer } from './util/types'

@@ -9,5 +10,23 @@ export interface IEncryptedMessage {

export interface IEncryptionKeys {
encryptKey: Uint8Array
decryptKey: Uint8Array
}
export interface ISignKeys {
signKey: Uint8Array
verifyKey: Uint8Array
}
export enum EDecryptionError {
invalidEncryption = 'invalid-encryption',
invalidSignature = 'invalid-signature'
invalidSignature = 'invalid-signature',
invalidMessage = 'invalid-message',
missingBody = 'missing-body',
missingSignature = 'missing-signature',
unexpectedIndex = 'unexpected-index',
vectorIntegrity = 'vector-integrity',
vectorPayload = 'vector-payload',
vectorIndex = 'vector-index',
vectorNext = 'vector-next'
}

@@ -35,12 +54,18 @@

export interface IWriterJSON {
type PropType<TObj, TProp extends keyof TObj> = TObj[TProp]
export interface IWriterJSON <TCodec extends INamedCodec> {
writerKey: string
outVector?: ISignVectorJSON
codec: PropType<TCodec, 'name'>
}
export interface IWriterOptions {
export interface IWriterOptions <TCodec extends CodecOption> {
writerKey: IStringOrBuffer
outVector?: ISignVectorOptions
codec?: TCodec
}
export interface IWriter extends IChannelActor {
toJSON(): IWriterJSON
export interface IWriter <TCodec extends INamedCodec> extends IChannelActor {
toJSON(): IWriterJSON<TCodec>
readonly writerKey: Uint8Array

@@ -51,20 +76,30 @@ readonly writerKeyBase64: string

readonly verifier: IVerifier
readonly codec: TCodec
outVector?: ISignVector
sign(data: Uint8Array): Uint8Array
encrypt(message: IEncodable): IEncryptedMessage
encryptOnly(message: IEncodable): Uint8Array
encrypt(message: any): IEncryptedMessage
encryptOnly(message: any): Uint8Array
encryptNext(message: any): IEncryptedMessage
encryptOnlyNext(message: any): Uint8Array
}
export interface IReaderJSON {
export interface IReaderJSON <TCodec extends INamedCodec> {
readerKey: string
inVector?: ISignVectorJSON
codec: PropType<TCodec, 'name'>
}
export interface IReaderOptions {
export interface IReaderOptions <TCodec extends CodecOption> {
readerKey: IStringOrBuffer
inVector?: ISignVectorOptions
codec?: TCodec
}
export interface IReader extends IChannelActor {
export interface IReader <TCodec extends INamedCodec> extends IChannelActor {
readonly readerKey: Uint8Array
readonly readerKeyBase64: string
readonly verifier: IVerifier
toJSON(): IReaderJSON
readonly codec: TCodec
inVector?: ISignVector
toJSON(): IReaderJSON<TCodec>
/**

@@ -75,40 +110,85 @@ * Decrypts a message written by an associated Sender

*/
decrypt(encrypted: IEncryptedMessage | Uint8Array): IEncodable
encryptOnly(message: IEncodable): Uint8Array
decrypt(encrypted: IEncryptedMessage | Uint8Array): any
decryptNext(encrypted: IEncryptedMessage | Uint8Array): any
encryptOnly(message: any): Uint8Array
}
export interface IConnectionJSON {
export interface ISignVector {
next: Uint8Array
nextBase64: string
index: number
increment (next: Uint8Array): Uint8Array
sign (message: Uint8Array): Uint8Array
verify (message: Uint8Array, signature: Uint8Array): void
toJSON (): ISignVectorJSON
}
export interface ISignVectorOptions {
next: IStringOrBuffer
index?: number
}
export interface ISignVectorJSON {
next: string
index: number
}
export interface IConnectionJSON <TInputCodec extends INamedCodec, TOutputCodec extends INamedCodec> {
connectionKey: string
inCodec: PropType<TInputCodec, 'name'>
outCodec: PropType<TOutputCodec, 'name'>
inVector?: ISignVectorJSON
outVector?: ISignVectorJSON
}
export type IConnectionOptions = {
export interface IConnectionOptionsByKey {
connectionKey: IStringOrBuffer
} | {
input: IStringOrBuffer | IReader | IReaderOptions
output: IStringOrBuffer | IWriter | IWriterOptions
}
export interface IChannelJSON {
export interface IConnectionOptionsByIO <TInputCodec extends CodecOption = undefined, TOutputCodec extends CodecOption = undefined> {
input: IStringOrBuffer | IReader<Codec<TInputCodec>> | IReaderOptions<TInputCodec>
output: IStringOrBuffer | IWriter<Codec<TOutputCodec>> | IWriterOptions<TOutputCodec>
}
export type IConnectionOptions <TInputCodec extends CodecOption, TOutputCodec extends CodecOption> = (IConnectionOptionsByKey | IConnectionOptionsByIO<TInputCodec, TOutputCodec>) & {
inCodec?: TInputCodec
outCodec?: TOutputCodec
inVector?: ISignVectorOptions
outVector?: ISignVectorOptions
}
export interface IChannelJSON<TCodec extends INamedCodec> {
channelKey: string
codec: PropType<TCodec, 'name'>
inVector?: ISignVectorJSON
outVector?: ISignVectorJSON
}
export interface IChannelOptions {
export interface IChannelOptions <TCodec extends CodecOption> {
channelKey: IStringOrBuffer
codec?: TCodec
inVector?: ISignVectorOptions
outVector?: ISignVectorOptions
}
export interface IChannel extends IChannelActor {
export interface IChannel <TCodec extends INamedCodec> extends IChannelActor {
verifier: IVerifier
toJSON(): IChannelJSON
codec: TCodec
channelKey: Uint8Array
channelKeyBase64: string
reader: IReader<TCodec>
writer: IWriter<TCodec>
toJSON(): IChannelJSON<TCodec>
}
export interface IConnection {
output: IWriter
input: IReader
export interface IConnection <TInput extends INamedCodec, TOutput extends INamedCodec> {
output: IWriter<TOutput>
input: IReader<TInput>
connectionKey: Uint8Array
connectionKeyBase64: string
toJSON(): IConnectionJSON
toJSON(): IConnectionJSON<TInput, TOutput>
}
export interface IHandshakeInitJSON {
input: IReaderJSON
input: Omit<IReaderJSON<any>, 'codec'>
firstMessage: string

@@ -119,3 +199,3 @@ handshakeSecret: string

export interface IHandshakeInitOptions {
input: IReader | IReaderOptions
input: Omit<IReaderOptions<any>, 'codec'>
firstMessage: IStringOrBuffer

@@ -126,3 +206,3 @@ handshakeSecret: IStringOrBuffer

export interface IHandshakeInit {
input: IReader
input: IReader<MsgPackCodec>
firstMessage: Uint8Array

@@ -139,18 +219,30 @@ handshakeSecret: Uint8Array

export interface IHandshakeAcceptJSON extends IConnectionJSON {
export interface IHandshakeAcceptJSON {
connectionKey: string
acceptMessage: IHandshakeAcceptMessage
}
export type IHandshakeAcceptOptions = IConnectionOptions & {
export type IHandshakeAcceptOptions = ({
connectionKey: IStringOrBuffer
} | {
input: IStringOrBuffer
output: IStringOrBuffer
}) & {
acceptMessage: IHandshakeAcceptMessage
}
export interface IHandshakeAccept extends IConnection {
export type MsgPackCodec = typeof codecs.msgpack
export interface IHandshakeAccept {
connectionKey: Uint8Array
connectionKeyBase64: string
input: IReader<MsgPackCodec>
output: IWriter<MsgPackCodec>
acceptMessage: IHandshakeAcceptMessage
toJSON(): IHandshakeAcceptJSON
finalize(message: Uint8Array): IConnection
finalize(message: Uint8Array): IConnection<MsgPackCodec, MsgPackCodec>
}
export interface IHandshakeConfirmationOptions {
connection: IConnectionOptions
connectionKey: IStringOrBuffer
finalMessage: IStringOrBuffer

@@ -160,3 +252,3 @@ }

export interface IHandshakeConfirmationJSON {
connection: IConnectionJSON
connectionKey: string
finalMessage: string

@@ -166,3 +258,3 @@ }

export interface IHandshakeConfirmation {
connection: IConnection
connection: IConnection<MsgPackCodec, MsgPackCodec>
finalMessage: Uint8Array

@@ -169,0 +261,0 @@ toJSON(): IHandshakeConfirmationJSON

@@ -1,14 +0,3 @@

import { IEncodable, IStringOrBuffer, EEncoding, Buffer } from './types'
import { IStringOrBuffer, EEncoding, Buffer } from './types'
function enumBuffer (num: number): Uint8Array {
const buf = new Uint8Array(1)
buf[0] = num
return buf
}
const MESSAGE_BINARY_UINT8 = enumBuffer(1)
const MESSAGE_BINARY_BUFFER = enumBuffer(2)
const MESSAGE_STRING = enumBuffer(3)
const MESSAGE_JSON = enumBuffer(4)
export function concatUint8Arrays (arrays: Uint8Array[]): Uint8Array {

@@ -25,18 +14,2 @@ const byteLength = arrays.reduce((len, array) => len + array.byteLength, 0)

export function anyToBuffer (message: IEncodable): Uint8Array {
if (typeof message === 'function') {
throw Object.assign(new Error('Cannot turn a function into a buffer'), { code: 'function-not-supported' })
}
if (message instanceof Buffer) {
return Buffer.concat([MESSAGE_BINARY_BUFFER, message] as Uint8Array[])
}
if (message instanceof Uint8Array) {
return concatUint8Arrays([MESSAGE_BINARY_UINT8, message])
}
if (typeof message === 'string') {
return concatUint8Arrays([MESSAGE_STRING, Buffer.from(message)])
}
return concatUint8Arrays([MESSAGE_JSON, Buffer.from(JSON.stringify(message))])
}
export function isStringOrBuffer (input: any): input is IStringOrBuffer {

@@ -73,22 +46,1 @@ if (typeof input === 'string') return true

}
export function bufferToAny (buffer: Uint8Array): IEncodable {
switch (buffer[0]) {
case MESSAGE_BINARY_UINT8[0]:
if (buffer instanceof Buffer) {
return new Uint8Array(buffer.buffer, buffer.byteOffset + 1, buffer.byteLength - 1)
}
return buffer.slice(1)
case MESSAGE_BINARY_BUFFER[0]:
if (buffer instanceof Buffer) {
return buffer.slice(1)
}
return Buffer.from(buffer.slice(1))
case MESSAGE_STRING[0]:
return bufferToString(buffer.slice(1))
case MESSAGE_JSON[0]:
return JSON.parse(bufferToString(buffer.slice(1)))
default:
throw Object.assign(new Error(`Couldnt deserialize from buffer: Unknown object type[${buffer[0]}].`), { code: 'deserialization-error', type: buffer[0] })
}
}
import { Buffer } from 'buffer'
import * as sodium from 'sodium-universal'
import { anyToBuffer, bufferToAny } from './buffer'
import { randomBuffer } from './randomBuffer'
import { IEncodable } from './types'

@@ -28,5 +26,4 @@ const {

export function encrypt (secretKey: Uint8Array, body: IEncodable): Uint8Array {
export function encrypt (secretKey: Uint8Array, message: Uint8Array): Uint8Array {
const nonce = randomBuffer(CRYPTO_SECRETBOX_NONCEBYTES)
const message = anyToBuffer(body)
const ciphertext = malloc(CRYPTO_SECRETBOX_MACBYTES + message.length)

@@ -38,3 +35,3 @@ secretBoxEasy(ciphertext, message, nonce, secretKey)

export function decrypt (secretKey: Uint8Array, encrypted: Uint8Array): IEncodable {
export function decrypt (secretKey: Uint8Array, encrypted: Uint8Array): Uint8Array {
const [nonce, ciphertext] = split(encrypted, CRYPTO_SECRETBOX_NONCEBYTES)

@@ -45,3 +42,3 @@ const decrypted = malloc(ciphertext.length - CRYPTO_SECRETBOX_MACBYTES)

}
return bufferToAny(decrypted)
return decrypted
}

@@ -11,3 +11,2 @@ import { AbortSignal } from 'abort-controller'

export type IStringOrBuffer = Uint8Array | string
export type IEncodable = IStringOrBuffer | object

@@ -14,0 +13,0 @@ export type EEncoding = 'base64' | 'hex' | 'utf8'

@@ -1,2 +0,3 @@

import { IEncodable, IStringOrBuffer } from './util/types';
import codecs, { Codec, CodecOption, INamedCodec } from '@consento/codecs';
import { IStringOrBuffer } from './util/types';
export interface IEncryptedMessage {

@@ -6,5 +7,21 @@ signature: Uint8Array;

}
export interface IEncryptionKeys {
encryptKey: Uint8Array;
decryptKey: Uint8Array;
}
export interface ISignKeys {
signKey: Uint8Array;
verifyKey: Uint8Array;
}
export declare enum EDecryptionError {
invalidEncryption = "invalid-encryption",
invalidSignature = "invalid-signature"
invalidSignature = "invalid-signature",
invalidMessage = "invalid-message",
missingBody = "missing-body",
missingSignature = "missing-signature",
unexpectedIndex = "unexpected-index",
vectorIntegrity = "vector-integrity",
vectorPayload = "vector-payload",
vectorIndex = "vector-index",
vectorNext = "vector-next"
}

@@ -27,10 +44,15 @@ export interface IVerifierJSON {

}
export interface IWriterJSON {
declare type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];
export interface IWriterJSON<TCodec extends INamedCodec> {
writerKey: string;
outVector?: ISignVectorJSON;
codec: PropType<TCodec, 'name'>;
}
export interface IWriterOptions {
export interface IWriterOptions<TCodec extends CodecOption> {
writerKey: IStringOrBuffer;
outVector?: ISignVectorOptions;
codec?: TCodec;
}
export interface IWriter extends IChannelActor {
toJSON(): IWriterJSON;
export interface IWriter<TCodec extends INamedCodec> extends IChannelActor {
toJSON(): IWriterJSON<TCodec>;
readonly writerKey: Uint8Array;

@@ -41,17 +63,27 @@ readonly writerKeyBase64: string;

readonly verifier: IVerifier;
readonly codec: TCodec;
outVector?: ISignVector;
sign(data: Uint8Array): Uint8Array;
encrypt(message: IEncodable): IEncryptedMessage;
encryptOnly(message: IEncodable): Uint8Array;
encrypt(message: any): IEncryptedMessage;
encryptOnly(message: any): Uint8Array;
encryptNext(message: any): IEncryptedMessage;
encryptOnlyNext(message: any): Uint8Array;
}
export interface IReaderJSON {
export interface IReaderJSON<TCodec extends INamedCodec> {
readerKey: string;
inVector?: ISignVectorJSON;
codec: PropType<TCodec, 'name'>;
}
export interface IReaderOptions {
export interface IReaderOptions<TCodec extends CodecOption> {
readerKey: IStringOrBuffer;
inVector?: ISignVectorOptions;
codec?: TCodec;
}
export interface IReader extends IChannelActor {
export interface IReader<TCodec extends INamedCodec> extends IChannelActor {
readonly readerKey: Uint8Array;
readonly readerKeyBase64: string;
readonly verifier: IVerifier;
toJSON(): IReaderJSON;
readonly codec: TCodec;
inVector?: ISignVector;
toJSON(): IReaderJSON<TCodec>;
/**

@@ -62,33 +94,73 @@ * Decrypts a message written by an associated Sender

*/
decrypt(encrypted: IEncryptedMessage | Uint8Array): IEncodable;
encryptOnly(message: IEncodable): Uint8Array;
decrypt(encrypted: IEncryptedMessage | Uint8Array): any;
decryptNext(encrypted: IEncryptedMessage | Uint8Array): any;
encryptOnly(message: any): Uint8Array;
}
export interface IConnectionJSON {
export interface ISignVector {
next: Uint8Array;
nextBase64: string;
index: number;
increment(next: Uint8Array): Uint8Array;
sign(message: Uint8Array): Uint8Array;
verify(message: Uint8Array, signature: Uint8Array): void;
toJSON(): ISignVectorJSON;
}
export interface ISignVectorOptions {
next: IStringOrBuffer;
index?: number;
}
export interface ISignVectorJSON {
next: string;
index: number;
}
export interface IConnectionJSON<TInputCodec extends INamedCodec, TOutputCodec extends INamedCodec> {
connectionKey: string;
inCodec: PropType<TInputCodec, 'name'>;
outCodec: PropType<TOutputCodec, 'name'>;
inVector?: ISignVectorJSON;
outVector?: ISignVectorJSON;
}
export declare type IConnectionOptions = {
export interface IConnectionOptionsByKey {
connectionKey: IStringOrBuffer;
} | {
input: IStringOrBuffer | IReader | IReaderOptions;
output: IStringOrBuffer | IWriter | IWriterOptions;
}
export interface IConnectionOptionsByIO<TInputCodec extends CodecOption = undefined, TOutputCodec extends CodecOption = undefined> {
input: IStringOrBuffer | IReader<Codec<TInputCodec>> | IReaderOptions<TInputCodec>;
output: IStringOrBuffer | IWriter<Codec<TOutputCodec>> | IWriterOptions<TOutputCodec>;
}
export declare type IConnectionOptions<TInputCodec extends CodecOption, TOutputCodec extends CodecOption> = (IConnectionOptionsByKey | IConnectionOptionsByIO<TInputCodec, TOutputCodec>) & {
inCodec?: TInputCodec;
outCodec?: TOutputCodec;
inVector?: ISignVectorOptions;
outVector?: ISignVectorOptions;
};
export interface IChannelJSON {
export interface IChannelJSON<TCodec extends INamedCodec> {
channelKey: string;
codec: PropType<TCodec, 'name'>;
inVector?: ISignVectorJSON;
outVector?: ISignVectorJSON;
}
export interface IChannelOptions {
export interface IChannelOptions<TCodec extends CodecOption> {
channelKey: IStringOrBuffer;
codec?: TCodec;
inVector?: ISignVectorOptions;
outVector?: ISignVectorOptions;
}
export interface IChannel extends IChannelActor {
export interface IChannel<TCodec extends INamedCodec> extends IChannelActor {
verifier: IVerifier;
toJSON(): IChannelJSON;
codec: TCodec;
channelKey: Uint8Array;
channelKeyBase64: string;
reader: IReader<TCodec>;
writer: IWriter<TCodec>;
toJSON(): IChannelJSON<TCodec>;
}
export interface IConnection {
output: IWriter;
input: IReader;
export interface IConnection<TInput extends INamedCodec, TOutput extends INamedCodec> {
output: IWriter<TOutput>;
input: IReader<TInput>;
connectionKey: Uint8Array;
connectionKeyBase64: string;
toJSON(): IConnectionJSON;
toJSON(): IConnectionJSON<TInput, TOutput>;
}
export interface IHandshakeInitJSON {
input: IReaderJSON;
input: Omit<IReaderJSON<any>, 'codec'>;
firstMessage: string;

@@ -98,3 +170,3 @@ handshakeSecret: string;

export interface IHandshakeInitOptions {
input: IReader | IReaderOptions;
input: Omit<IReaderOptions<any>, 'codec'>;
firstMessage: IStringOrBuffer;

@@ -104,3 +176,3 @@ handshakeSecret: IStringOrBuffer;

export interface IHandshakeInit {
input: IReader;
input: IReader<MsgPackCodec>;
firstMessage: Uint8Array;

@@ -115,23 +187,34 @@ handshakeSecret: Uint8Array;

}
export interface IHandshakeAcceptJSON extends IConnectionJSON {
export interface IHandshakeAcceptJSON {
connectionKey: string;
acceptMessage: IHandshakeAcceptMessage;
}
export declare type IHandshakeAcceptOptions = IConnectionOptions & {
export declare type IHandshakeAcceptOptions = ({
connectionKey: IStringOrBuffer;
} | {
input: IStringOrBuffer;
output: IStringOrBuffer;
}) & {
acceptMessage: IHandshakeAcceptMessage;
};
export interface IHandshakeAccept extends IConnection {
export declare type MsgPackCodec = typeof codecs.msgpack;
export interface IHandshakeAccept {
connectionKey: Uint8Array;
connectionKeyBase64: string;
input: IReader<MsgPackCodec>;
output: IWriter<MsgPackCodec>;
acceptMessage: IHandshakeAcceptMessage;
toJSON(): IHandshakeAcceptJSON;
finalize(message: Uint8Array): IConnection;
finalize(message: Uint8Array): IConnection<MsgPackCodec, MsgPackCodec>;
}
export interface IHandshakeConfirmationOptions {
connection: IConnectionOptions;
connectionKey: IStringOrBuffer;
finalMessage: IStringOrBuffer;
}
export interface IHandshakeConfirmationJSON {
connection: IConnectionJSON;
connectionKey: string;
finalMessage: string;
}
export interface IHandshakeConfirmation {
connection: IConnection;
connection: IConnection<MsgPackCodec, MsgPackCodec>;
finalMessage: Uint8Array;

@@ -151,1 +234,2 @@ toJSON(): IHandshakeConfirmationJSON;

}
export {};

@@ -8,3 +8,11 @@ "use strict";

EDecryptionError["invalidSignature"] = "invalid-signature";
EDecryptionError["invalidMessage"] = "invalid-message";
EDecryptionError["missingBody"] = "missing-body";
EDecryptionError["missingSignature"] = "missing-signature";
EDecryptionError["unexpectedIndex"] = "unexpected-index";
EDecryptionError["vectorIntegrity"] = "vector-integrity";
EDecryptionError["vectorPayload"] = "vector-payload";
EDecryptionError["vectorIndex"] = "vector-index";
EDecryptionError["vectorNext"] = "vector-next";
})(EDecryptionError = exports.EDecryptionError || (exports.EDecryptionError = {}));
//# sourceMappingURL=types.js.map

@@ -1,4 +0,3 @@

import { IEncodable, IStringOrBuffer, EEncoding } from './types';
import { IStringOrBuffer, EEncoding } from './types';
export declare function concatUint8Arrays(arrays: Uint8Array[]): Uint8Array;
export declare function anyToBuffer(message: IEncodable): Uint8Array;
export declare function isStringOrBuffer(input: any): input is IStringOrBuffer;

@@ -9,2 +8,1 @@ export declare function toBuffer(stringOrBuffer: IStringOrBuffer): Uint8Array;

export declare function bufferToString(buffer: Uint8Array, encoding?: EEncoding): string;
export declare function bufferToAny(buffer: Uint8Array): IEncodable;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bufferToAny = exports.bufferToString = exports.bufferEquals = exports.bufferCompare = exports.toBuffer = exports.isStringOrBuffer = exports.anyToBuffer = exports.concatUint8Arrays = void 0;
exports.bufferToString = exports.bufferEquals = exports.bufferCompare = exports.toBuffer = exports.isStringOrBuffer = exports.concatUint8Arrays = void 0;
const types_1 = require("./types");
function enumBuffer(num) {
const buf = new Uint8Array(1);
buf[0] = num;
return buf;
}
const MESSAGE_BINARY_UINT8 = enumBuffer(1);
const MESSAGE_BINARY_BUFFER = enumBuffer(2);
const MESSAGE_STRING = enumBuffer(3);
const MESSAGE_JSON = enumBuffer(4);
function concatUint8Arrays(arrays) {

@@ -25,18 +16,2 @@ const byteLength = arrays.reduce((len, array) => len + array.byteLength, 0);

exports.concatUint8Arrays = concatUint8Arrays;
function anyToBuffer(message) {
if (typeof message === 'function') {
throw Object.assign(new Error('Cannot turn a function into a buffer'), { code: 'function-not-supported' });
}
if (message instanceof types_1.Buffer) {
return types_1.Buffer.concat([MESSAGE_BINARY_BUFFER, message]);
}
if (message instanceof Uint8Array) {
return concatUint8Arrays([MESSAGE_BINARY_UINT8, message]);
}
if (typeof message === 'string') {
return concatUint8Arrays([MESSAGE_STRING, types_1.Buffer.from(message)]);
}
return concatUint8Arrays([MESSAGE_JSON, types_1.Buffer.from(JSON.stringify(message))]);
}
exports.anyToBuffer = anyToBuffer;
function isStringOrBuffer(input) {

@@ -81,23 +56,2 @@ if (typeof input === 'string')

exports.bufferToString = bufferToString;
function bufferToAny(buffer) {
switch (buffer[0]) {
case MESSAGE_BINARY_UINT8[0]:
if (buffer instanceof types_1.Buffer) {
return new Uint8Array(buffer.buffer, buffer.byteOffset + 1, buffer.byteLength - 1);
}
return buffer.slice(1);
case MESSAGE_BINARY_BUFFER[0]:
if (buffer instanceof types_1.Buffer) {
return buffer.slice(1);
}
return types_1.Buffer.from(buffer.slice(1));
case MESSAGE_STRING[0]:
return bufferToString(buffer.slice(1));
case MESSAGE_JSON[0]:
return JSON.parse(bufferToString(buffer.slice(1)));
default:
throw Object.assign(new Error(`Couldnt deserialize from buffer: Unknown object type[${buffer[0]}].`), { code: 'deserialization-error', type: buffer[0] });
}
}
exports.bufferToAny = bufferToAny;
//# sourceMappingURL=buffer.js.map

@@ -1,4 +0,3 @@

import { IEncodable } from './types';
export declare function createSecret(): Uint8Array;
export declare function encrypt(secretKey: Uint8Array, body: IEncodable): Uint8Array;
export declare function decrypt(secretKey: Uint8Array, encrypted: Uint8Array): IEncodable;
export declare function encrypt(secretKey: Uint8Array, message: Uint8Array): Uint8Array;
export declare function decrypt(secretKey: Uint8Array, encrypted: Uint8Array): Uint8Array;

@@ -25,3 +25,2 @@ "use strict";

const sodium = __importStar(require("sodium-universal"));
const buffer_2 = require("./buffer");
const randomBuffer_1 = require("./randomBuffer");

@@ -40,5 +39,4 @@ const { crypto_secretbox_KEYBYTES: CRYPTO_SECRETBOX_KEYBYTES, crypto_secretbox_NONCEBYTES: CRYPTO_SECRETBOX_NONCEBYTES, crypto_secretbox_MACBYTES: CRYPTO_SECRETBOX_MACBYTES, crypto_secretbox_easy: secretBoxEasy, crypto_secretbox_open_easy: secretBoxOpenEasy, sodium_malloc: malloc } = sodium.default;

exports.createSecret = createSecret;
function encrypt(secretKey, body) {
function encrypt(secretKey, message) {
const nonce = randomBuffer_1.randomBuffer(CRYPTO_SECRETBOX_NONCEBYTES);
const message = buffer_2.anyToBuffer(body);
const ciphertext = malloc(CRYPTO_SECRETBOX_MACBYTES + message.length);

@@ -56,5 +54,5 @@ secretBoxEasy(ciphertext, message, nonce, secretKey);

}
return buffer_2.bufferToAny(decrypted);
return decrypted;
}
exports.decrypt = decrypt;
//# sourceMappingURL=secretbox.js.map

@@ -7,3 +7,2 @@ import { AbortSignal } from 'abort-controller';

export declare type IStringOrBuffer = Uint8Array | string;
export declare type IEncodable = IStringOrBuffer | object;
export declare type EEncoding = 'base64' | 'hex' | 'utf8';

@@ -10,0 +9,0 @@ export declare class AbortError extends Error {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc