make recoverPublicKey universal
This commit is contained in:
parent
6252736ad2
commit
e2cfc3ca6e
|
@ -1,4 +1,4 @@
|
|||
import { recoverPublicKeyFromMetadata } from '~/src/utils/recover-public-key-from-metadata'
|
||||
import { recoverPublicKey } from '~/src/utils/recover-public-key'
|
||||
|
||||
import { ApplicationMetadataMessage } from '../../../protos/application-metadata-message'
|
||||
import { ChatMessage } from '../../../protos/chat-message'
|
||||
|
@ -48,7 +48,10 @@ export function handleChannelChatMessage(
|
|||
return
|
||||
}
|
||||
|
||||
const publicKey = recoverPublicKeyFromMetadata(decodedMetadata)
|
||||
const publicKey = recoverPublicKey(
|
||||
decodedMetadata.signature,
|
||||
decodedMetadata.payload
|
||||
)
|
||||
|
||||
const decodedPayload = ChatMessage.decode(messageToDecode)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// todo?: rename to handle-message
|
||||
import { bytesToHex } from 'ethereum-cryptography/utils'
|
||||
|
||||
import { recoverPublicKeyFromMetadata } from '~/src/utils/recover-public-key-from-metadata'
|
||||
import { recoverPublicKey } from '~/src/utils/recover-public-key'
|
||||
|
||||
import { ApplicationMetadataMessage } from '../../../protos/application-metadata-message'
|
||||
import {
|
||||
|
@ -63,7 +63,10 @@ export function handleChannelChatMessage(
|
|||
// break
|
||||
// }
|
||||
|
||||
const publicKey = recoverPublicKeyFromMetadata(decodedMetadata)
|
||||
const publicKey = recoverPublicKey(
|
||||
decodedMetadata.signature,
|
||||
decodedMetadata.payload
|
||||
)
|
||||
|
||||
// todo: merge and process other types of messages
|
||||
// TODO?: ignore messages which are messageType !== COMMUNITY_CHAT
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import { keccak256 } from 'ethereum-cryptography/keccak'
|
||||
import { recoverPublicKey } from 'ethereum-cryptography/secp256k1'
|
||||
|
||||
import type { ApplicationMetadataMessage } from '../../protos/application-metadata-message'
|
||||
|
||||
/**
|
||||
* returns the public key of the signer
|
||||
* msg must be the 32-byte keccak hash of the message to be signed.
|
||||
* sig must be a 65-byte compact ECDSA signature containing the recovery id as the last element.
|
||||
*/
|
||||
export function recoverPublicKeyFromMetadata(
|
||||
metadata: ApplicationMetadataMessage
|
||||
): Uint8Array {
|
||||
const signature = metadata.signature.slice(0, 64)
|
||||
const recoveryId = metadata.signature.slice(-1)
|
||||
|
||||
const pk = recoverPublicKey(
|
||||
keccak256(metadata.payload),
|
||||
signature,
|
||||
Number(recoveryId)
|
||||
)
|
||||
|
||||
return pk
|
||||
}
|
|
@ -1,10 +1,25 @@
|
|||
import { recoverPublicKeyFromMetadata } from './recover-public-key-from-metadata'
|
||||
import { bytesToHex, utf8ToBytes } from 'ethereum-cryptography/utils'
|
||||
|
||||
import type { ApplicationMetadataMessage } from '../../protos/application-metadata-message'
|
||||
import { Account } from '../account'
|
||||
import { recoverPublicKey } from './recover-public-key'
|
||||
|
||||
describe('TODO: recoverPublicKeyFromMetadata', () => {
|
||||
import type { ApplicationMetadataMessage } from '~/protos/application-metadata-message'
|
||||
|
||||
describe('recoverPublicKey', () => {
|
||||
it('should recover public key', async () => {
|
||||
const metadataFixture = {
|
||||
const payload = utf8ToBytes('hello')
|
||||
|
||||
const account = new Account()
|
||||
const signature = await account.sign(payload)
|
||||
|
||||
expect(bytesToHex(recoverPublicKey(signature, payload))).toEqual(
|
||||
account.publicKey
|
||||
)
|
||||
})
|
||||
|
||||
it('should recover public key from fixture', async () => {
|
||||
const metadataFixture: ApplicationMetadataMessage = {
|
||||
type: 'TYPE_EMOJI_REACTION' as ApplicationMetadataMessage.Type,
|
||||
signature: new Uint8Array([
|
||||
250, 132, 234, 119, 159, 124, 98, 93, 197, 108, 99, 52, 186, 234, 142,
|
||||
101, 147, 180, 50, 190, 102, 61, 219, 189, 95, 124, 29, 74, 43, 46, 106,
|
||||
|
@ -25,8 +40,7 @@ describe('TODO: recoverPublicKeyFromMetadata', () => {
|
|||
102, 55, 99, 48, 98, 55, 55, 97, 55, 99, 48, 97, 53, 101, 98, 97, 53,
|
||||
102, 97, 57, 100, 52, 100, 57, 49, 98, 97, 56, 32, 5, 40, 2,
|
||||
]),
|
||||
type: 'TYPE_EMOJI_REACTION',
|
||||
} as unknown as ApplicationMetadataMessage
|
||||
}
|
||||
|
||||
const publicKeySnapshot = new Uint8Array([
|
||||
4, 172, 65, 157, 172, 154, 139, 187, 88, 130, 90, 60, 222, 96, 238, 240,
|
||||
|
@ -36,8 +50,33 @@ describe('TODO: recoverPublicKeyFromMetadata', () => {
|
|||
99, 24, 17,
|
||||
])
|
||||
|
||||
const result = recoverPublicKeyFromMetadata(metadataFixture)
|
||||
const result = recoverPublicKey(
|
||||
metadataFixture.signature,
|
||||
metadataFixture.payload
|
||||
)
|
||||
|
||||
expect(result).toEqual(publicKeySnapshot)
|
||||
})
|
||||
|
||||
it('should not recover public key with different payload', async () => {
|
||||
const payload = utf8ToBytes('1')
|
||||
|
||||
const account = new Account()
|
||||
const signature = await account.sign(payload)
|
||||
|
||||
const payload2 = utf8ToBytes('2')
|
||||
expect(recoverPublicKey(signature, payload2)).not.toEqual(account.publicKey)
|
||||
})
|
||||
|
||||
it('should throw error when signature length is not 65 bytes', async () => {
|
||||
const payload = utf8ToBytes('hello')
|
||||
const signature = new Uint8Array([
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
])
|
||||
|
||||
// TODO: use toThrowErrorMatchingInlineSnapshot
|
||||
expect(recoverPublicKey(signature, payload)).toThrow(
|
||||
'Signature must be 65 bytes long'
|
||||
)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,25 @@
|
|||
import { keccak256 } from 'ethereum-cryptography/keccak'
|
||||
import { recoverPublicKey as secpRecoverPublicKey } from 'ethereum-cryptography/secp256k1'
|
||||
|
||||
/**
|
||||
* returns the public key of the signer
|
||||
* msg must be the 32-byte keccak hash of the message to be signed.
|
||||
* sig must be a 65-byte compact ECDSA signature containing the recovery id as the last element.
|
||||
*/
|
||||
export function recoverPublicKey(
|
||||
sig: Uint8Array,
|
||||
payload: Uint8Array
|
||||
): Uint8Array {
|
||||
if (sig.length !== 65) {
|
||||
throw new Error('Signature must be 65 bytes long')
|
||||
}
|
||||
|
||||
if (sig[64] >= 4) {
|
||||
throw new Error('Recovery id must be less than 4')
|
||||
}
|
||||
|
||||
const signature = sig.slice(0, 64)
|
||||
const recoveryId = sig.slice(-1)
|
||||
|
||||
return secpRecoverPublicKey(keccak256(payload), signature, Number(recoveryId))
|
||||
}
|
Loading…
Reference in New Issue