Skip to content

Commit

Permalink
feat: add self-encryption support
Browse files Browse the repository at this point in the history
  • Loading branch information
neekolas authored and rygine committed Oct 26, 2023
1 parent d9bdfc6 commit ae6ed82
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 2 deletions.
8 changes: 7 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
},
"dependencies": {
"@noble/secp256k1": "^1.5.2",
"@xmtp/proto": "^3.29.0",
"@xmtp/ecies-bindings-wasm": "^0.1.5",
"@xmtp/proto": "^3.28.0-beta.1",
"async-mutex": "^0.4.0",
"elliptic": "^6.5.4",
"ethers": "^5.5.3",
Expand Down
32 changes: 32 additions & 0 deletions src/crypto/SelfEncryption.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
// eslint-disable-next-line camelcase
ecies_decrypt_k256_sha3_256,
// eslint-disable-next-line camelcase
ecies_encrypt_k256_sha3_256,
} from '@xmtp/ecies-bindings-wasm'
import { PrivateKey } from '.'

// Uses ECIES to encrypt messages where the sender and recipient are the same
export default class SelfEncryption {
privateKey: PrivateKey

constructor(identityKey: PrivateKey) {
this.privateKey = identityKey
}

encrypt(data: Uint8Array): Uint8Array {
return ecies_encrypt_k256_sha3_256(
this.privateKey.publicKey.secp256k1Uncompressed.bytes,
this.privateKey.secp256k1.bytes,
data
)
}

decrypt(message: Uint8Array): Uint8Array {
return ecies_decrypt_k256_sha3_256(
this.privateKey.publicKey.secp256k1Uncompressed.bytes,
this.privateKey.secp256k1.bytes,
message
)
}
}
36 changes: 36 additions & 0 deletions test/crypto/P4Encryption.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { PrivateKeyBundleV1 } from '../../src/crypto/PrivateKeyBundle'
import SelfEncryption from '../../src/crypto/SelfEncryption'
import { newWallet } from '../helpers'
import { equalBytes } from '../../src/crypto/utils'

describe('SelfEncryption', () => {
let bundle: PrivateKeyBundleV1

beforeEach(async () => {
bundle = await PrivateKeyBundleV1.generate(newWallet())
})

it('round trips data', async () => {
const message = new TextEncoder().encode('hello world')
const encryptor = new SelfEncryption(bundle.identityKey)

const ciphertext = encryptor.encrypt(message)
expect(ciphertext).toBeDefined()

const decrypted = encryptor.decrypt(ciphertext)
expect(equalBytes(decrypted, message)).toBeTruthy()
})

it('throws on decryption failure', async () => {
const message = new TextEncoder().encode('hello world')
const encryptor = new SelfEncryption(bundle.identityKey)

const ciphertext = encryptor.encrypt(message)
expect(ciphertext).toBeDefined()

const differentEncryptor = new SelfEncryption(
(await PrivateKeyBundleV1.generate(newWallet())).identityKey
)
expect(() => differentEncryptor.decrypt(ciphertext)).toThrow()
})
})

0 comments on commit ae6ed82

Please sign in to comment.