Skip to content

Commit

Permalink
feat: encryption with signatures (#494)
Browse files Browse the repository at this point in the history
  • Loading branch information
agazso authored Nov 13, 2023
1 parent 8818541 commit 7108b07
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 222 deletions.
33 changes: 33 additions & 0 deletions src/lib/adapters/waku/codec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
createEncoder as createWakuSymmetricEncoder,
createDecoder as createWakuSymmetricDecoder,
} from '@waku/message-encryption/symmetric'
import { getTopic, type ContentTopic } from './waku'
import { bytesToHex, hexToBytes } from '@waku/utils/bytes'
import { type Hex, fixHex } from './crypto'

function toHex(value: Uint8Array | Hex): Hex {
return typeof value === 'string' ? fixHex(value) : bytesToHex(value)
}

export function createSymmetricEncoder(options: {
contentTopic: ContentTopic
symKey: Uint8Array | Hex
sigPrivKey?: Uint8Array | Hex
}) {
const contentTopic = getTopic(options.contentTopic, toHex(options.symKey))
return createWakuSymmetricEncoder({
...options,
contentTopic,
symKey: hexToBytes(options.symKey),
sigPrivKey: options.sigPrivKey ? hexToBytes(options.sigPrivKey) : undefined,
})
}

export function createSymmetricDecoder(options: {
contentTopic: ContentTopic
symKey: Uint8Array | Hex
}) {
const contentTopic = getTopic(options.contentTopic, toHex(options.symKey))
return createWakuSymmetricDecoder(contentTopic, hexToBytes(options.symKey))
}
19 changes: 3 additions & 16 deletions src/lib/adapters/waku/crypto.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { describe, it, expect } from 'vitest'
import { hash, publicKeyToAddress, sign, signatureToPublicKey } from './crypto'
import { publicKeyToAddress } from './crypto'

const testPrivateKey = 'd195918969e09d9394c768e25b621eafc4c360117a9e1eebb0a68bfd53119ba4'
// const testPrivateKey = 'd195918969e09d9394c768e25b621eafc4c360117a9e1eebb0a68bfd53119ba4'
const testCompressedPublicKey = '0374a6b1cea74a7a755396d8c62a3be4eb9098c7bb286dcdfc02ab93e7683c93f9'
const testUncompressedPublicKey =
'0474a6b1cea74a7a755396d8c62a3be4eb9098c7bb286dcdfc02ab93e7683c93f99515f1cf8980e0cb25b6078113813d90d99303aaea1aa34c12805f8355768e21'
const testAddress = publicKeyToAddress(testUncompressedPublicKey)
const testAddress = '0x5018604b6fcfb992e48c102dcff8f9084a68b751'

describe('publicKeyToAddress', () => {
it('calculates correct address for compressed public key', () => {
Expand All @@ -18,16 +18,3 @@ describe('publicKeyToAddress', () => {
expect(address).toEqual(testAddress)
})
})

describe('sign', () => {
it('calculates signature', () => {
const message = 'hello'

const data = new TextEncoder().encode(message)
const signature = sign(testPrivateKey, data)
const messageHash = hash(data)
const recoveredPublicKey = signatureToPublicKey(signature, messageHash)

expect(recoveredPublicKey).toEqual(testCompressedPublicKey)
})
})
23 changes: 6 additions & 17 deletions src/lib/adapters/waku/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import {
getSharedSecret as nobleGetSharedSecret,
sign as nobleSign,
ProjectivePoint,
Signature,
} from '@noble/secp256k1'
import { getSharedSecret as nobleGetSharedSecret, ProjectivePoint } from '@noble/secp256k1'
import { keccak_256 } from '@noble/hashes/sha3'
import { bytesToHex, hexToBytes } from '@waku/utils/bytes'
import { gcm } from '@noble/ciphers/aes'
import { randomBytes } from '@noble/ciphers/webcrypto/utils'

type Hex = string
export type Hex = string

function fixHex(h: Hex): Hex {
export function fixHex(h: Hex): Hex {
if (h.startsWith('0x')) {
return h.slice(2)
}
Expand Down Expand Up @@ -53,13 +48,7 @@ export function publicKeyToAddress(publicKey: Hex): Hex {
return '0x' + keyHash.slice(-40)
}

export function signatureToPublicKey(signature: Hex, messageHash: Hex): Hex {
const publicKey = Signature.fromCompact(fixHex(signature)).recoverPublicKey(fixHex(messageHash))
return publicKey.toHex(true)
}

export function sign(privateKey: Hex, data: Uint8Array): Hex {
const messageHash = hash(data)
const signature = nobleSign(messageHash, fixHex(privateKey))
return signature.toCompactHex()
export function compressPublicKey(publicKey: Hex | Uint8Array): Hex {
publicKey = typeof publicKey === 'string' ? fixHex(publicKey) : bytesToHex(publicKey)
return ProjectivePoint.fromHex(publicKey).toHex(true)
}
Loading

1 comment on commit 7108b07

@vercel
Copy link

@vercel vercel bot commented on 7108b07 Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.