Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/value-objects/crypto/PrivateKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Buffer } from 'buffer';
import { InvalidFormatError } from '../../errors/InvalidFormatError';
import { InvalidLengthError } from '../../errors/InvalidLengthError';
import { assert } from '../../patterns';
import { Media } from '../media';
import { NullObject } from '../NullObject';
import { StringValueObject } from '../StringValueObject';
import { CryptoAdapter } from './CryptoAdapter';
Expand Down Expand Up @@ -48,7 +49,10 @@ export class PrivateKey extends Key {
}

public sign(payload: CryptoPayload): Signature {
const messageBuffer = Buffer.from(payload.valueOf());
const messageBuffer =
payload instanceof Media
? payload.getBuffer()
Comment thread
haskou marked this conversation as resolved.
Resolved
: Buffer.from(payload.valueOf());
const signatureBuffer = CryptoAdapter.sign(messageBuffer, this.valueOf());

return Signature.fromBuffer(signatureBuffer);
Expand Down
11 changes: 9 additions & 2 deletions src/value-objects/crypto/PublicKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Buffer } from 'buffer';
import { InvalidFormatError } from '../../errors/InvalidFormatError';
import { InvalidLengthError } from '../../errors/InvalidLengthError';
import { assert } from '../../patterns';
import { Media } from '../media';
import { NullObject } from '../NullObject';
import { StringValueObject } from '../StringValueObject';
import { CryptoAdapter } from './CryptoAdapter';
Expand Down Expand Up @@ -42,7 +43,10 @@ export class PublicKey extends Key {
payload: CryptoPayload,
signature: Signature,
): boolean {
const messageBuffer = Buffer.from(payload.valueOf());
const messageBuffer =
payload instanceof Media
? payload.getBuffer()
: Buffer.from(payload.valueOf());
const signatureBuffer = Buffer.from(signature.valueOf(), 'base64');
const valid = CryptoAdapter.verify(
signatureBuffer,
Expand All @@ -54,7 +58,10 @@ export class PublicKey extends Key {
}

public encrypt(payload: CryptoPayload): EncryptedPayload {
const messageBuffer = Buffer.from(payload.valueOf());
const messageBuffer =
payload instanceof Media
? payload.getBuffer()
: Buffer.from(payload.valueOf());

const x25519Pub = CryptoAdapter.publicKeyToX25519(this.valueOf());

Expand Down
7 changes: 6 additions & 1 deletion src/value-objects/hashes/MD5Hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ export class MD5Hash extends Hash {
public static from(
buffer: string | StringValueObject | Media | Buffer,
): MD5Hash {
return new MD5Hash(CryptoAdapter.hash('md5', buffer.valueOf()));
return new MD5Hash(
CryptoAdapter.hash(
'md5',
buffer instanceof Media ? buffer.getBuffer() : buffer.valueOf(),
),
);
}

constructor(source: string | StringValueObject) {
Expand Down
7 changes: 6 additions & 1 deletion src/value-objects/hashes/SHA256Hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ export class SHA256Hash extends ValueObject<string> {
public static from(
buffer: string | StringValueObject | Media | Buffer,
): SHA256Hash {
return new SHA256Hash(CryptoAdapter.hash('sha256', buffer.valueOf()));
return new SHA256Hash(
CryptoAdapter.hash(
'sha256',
buffer instanceof Media ? buffer.getBuffer() : buffer.valueOf(),
),
);
}

constructor(source: string | StringValueObject) {
Expand Down
7 changes: 6 additions & 1 deletion src/value-objects/hashes/SHA512Hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ export class SHA512Hash extends ValueObject<string> {
public static from(
buffer: string | StringValueObject | Media | Buffer,
): SHA512Hash {
return new SHA512Hash(CryptoAdapter.hash('sha512', buffer.valueOf()));
return new SHA512Hash(
CryptoAdapter.hash(
'sha512',
buffer instanceof Media ? buffer.getBuffer() : buffer.valueOf(),
),
);
}

constructor(source: string | StringValueObject) {
Expand Down
8 changes: 7 additions & 1 deletion src/value-objects/media/Media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@ import { NullObject } from '../NullObject';
import { ValueObject } from '../ValueObject';

export class Media extends ValueObject<string> {
private readonly buffer?: Buffer;

constructor(value: string | Buffer) {
super(value?.toString());

if (NullObject.isNullObject(this)) {
return this;
}

this.buffer = Buffer.isBuffer(value) ? Buffer.from(value) : undefined;
}

public getBuffer(): Buffer {
return Buffer.from(this.value);
return this.buffer === undefined
? Buffer.from(this.value)
: Buffer.from(this.buffer);
}

public getSize(): number {
Expand Down
15 changes: 15 additions & 0 deletions tests/value-objects/crypto/PrivateKey.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
InvalidFormatError,
InvalidLengthError,
Key,
Media,
PrivateKey,
PublicKey,
Signature,
Expand Down Expand Up @@ -142,6 +143,20 @@ describe('PrivateKey', () => {
);
expect(valid).toBeTrue();
});

it('should sign raw Media bytes', () => {
const key = new PrivateKey(privatePem);
const payload = Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]);
const sig = key.sign(new Media(payload));

const valid = crypto.verify(
null,
payload,
publicPem,
Buffer.from(sig.valueOf(), 'base64'),
);
expect(valid).toBeTrue();
});
});

describe('decrypt', () => {
Expand Down
20 changes: 20 additions & 0 deletions tests/value-objects/crypto/PublicKey.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
InvalidFormatError,
InvalidLengthError,
Key,
Media,
PrivateKey,
PublicKey,
Signature,
Expand Down Expand Up @@ -112,6 +113,15 @@ describe('PublicKey', () => {

expect(key.isValidSignature(payloadVO, signature)).toBeTrue();
});

it('should verify signatures against raw Media bytes', () => {
const key = new PublicKey(publicPem);
const payload = Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]);
const sigBuf = crypto.sign(null, payload, privatePem);
const signature = Signature.fromBuffer(sigBuf);

expect(key.isValidSignature(new Media(payload), signature)).toBeTrue();
});
});

describe('encrypt', () => {
Expand Down Expand Up @@ -146,6 +156,16 @@ describe('PublicKey', () => {
expect(encrypted).toBeInstanceOf(EncryptedPayload);
});

it('should encrypt raw Media bytes', () => {
const pubKey = new PublicKey(publicPem);
const privKey = new PrivateKey(privatePem);
const payload = Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]);
const encrypted = pubKey.encrypt(new Media(payload));
const decrypted = privKey.decrypt(encrypted);

expect(decrypted).toEqual(payload);
});

it('should produce output that can be decrypted by the corresponding PrivateKey', () => {
const pubKey = new PublicKey(publicPem);
const privKey = new PrivateKey(privatePem);
Expand Down
8 changes: 8 additions & 0 deletions tests/value-objects/hashes/MD5Hash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createHash } from 'crypto';

import {
InvalidHashError,
Media,
MD5Hash,
NullObject,
StringValueObject,
Expand Down Expand Up @@ -98,6 +99,13 @@ describe('MD5Hash', () => {
expect(hash.valueOf()).toBe(expected);
});

it('should compute MD5 hash from raw Media bytes', () => {
const input = Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]);
const expected = computeMD5(input);
const hash = MD5Hash.from(new Media(input));
expect(hash.valueOf()).toBe(expected);
});

it('should compute MD5 hash from StringValueObject', () => {
const input = new StringValueObject('hello');
const expected = computeMD5(input.valueOf());
Expand Down
8 changes: 8 additions & 0 deletions tests/value-objects/hashes/SHA256Hash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
SHA256Hash,
NullObject,
InvalidHashError,
Media,
StringValueObject,
} from '../../../src';

Expand Down Expand Up @@ -102,6 +103,13 @@ describe('SHA256Hash', () => {
expect(hash.valueOf()).toBe(expected);
});

it('should compute SHA256 hash from raw Media bytes', () => {
const input = Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]);
const expected = computeSHA256(input);
const hash = SHA256Hash.from(new Media(input));
expect(hash.valueOf()).toBe(expected);
});

it('should compute SHA256 hash from StringValueObject', () => {
const input = new StringValueObject('hello');
const expected = computeSHA256(input.valueOf());
Expand Down
8 changes: 8 additions & 0 deletions tests/value-objects/hashes/SHA512Hash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
SHA512Hash,
NullObject,
InvalidHashError,
Media,
StringValueObject,
} from '../../../src';

Expand Down Expand Up @@ -102,6 +103,13 @@ describe('SHA512Hash', () => {
expect(hash.valueOf()).toBe(expected);
});

it('should compute SHA512 hash from raw Media bytes', () => {
const input = Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]);
const expected = computeSHA512(input);
const hash = SHA512Hash.from(new Media(input));
expect(hash.valueOf()).toBe(expected);
});

it('should compute SHA512 hash from StringValueObject', () => {
const input = new StringValueObject('hello');
const expected = computeSHA512(input.valueOf());
Expand Down
11 changes: 11 additions & 0 deletions tests/value-objects/media/Media.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ describe('Media', () => {
expect(media).toBeInstanceOf(Media);
expect(media.valueOf()).toBe(testContent);
});

it('should preserve non-text bytes from a Buffer', () => {
const source = Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]);
const media = new Media(source);

source[0] = 0x00;

expect(media.getBuffer()).toEqual(
Buffer.from([0xff, 0xfe, 0xfd, 0x00, 0x80]),
);
});
});

describe('getBuffer', () => {
Expand Down
Loading