Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devp2p-ethereum-cryptography-dependency #1947

Merged
merged 14 commits into from
Jun 18, 2022
Merged
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: 2 additions & 4 deletions package-lock.json

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

8 changes: 2 additions & 6 deletions packages/devp2p/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,22 @@
},
"dependencies": {
"@ethereumjs/common": "^2.6.4",
"@scure/base": "1.1.1",
"@types/bl": "^2.1.0",
"@types/k-bucket": "^5.0.0",
"@types/lru-cache": "^5.1.0",
"base64url": "^3.0.1",
"bl": "^1.1.2",
"debug": "^4.3.3",
"@ethereumjs/util": "^8.0.0",
"hi-base32": "^0.5.0",
"ethereum-cryptography": "^1.1.0",
"inherits": "^2.0.1",
"ip": "^1.1.3",
"k-bucket": "^5.0.0",
"keccak": "^3.0.1",
"lru-cache": "^5.1.1",
"ms": "^0.7.1",
"multiaddr": "^10.0.1",
"rlp": "^3.0.0",
"scanf": "^1.1.2",
"secp256k1": "^4.0.2",
"snappyjs": "^0.6.1"
},
"devDependencies": {
Expand All @@ -68,10 +66,8 @@
"@types/chalk": "^2.2.0",
"@types/debug": "^4.1.4",
"@types/ip": "^1.1.0",
"@types/keccak": "^3.0.1",
"@types/ms": "^0.7.30",
"@types/node": "^16.11.7",
"@types/secp256k1": "^4.0.1",
"@types/tape": "^4.13.2",
"chalk": "^2.4.2",
"eslint": "^6.8.0",
Expand Down
14 changes: 8 additions & 6 deletions packages/devp2p/src/dns/enr.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import * as base32 from 'hi-base32'
import { base32, base64url } from '@scure/base'
import { sscanf } from 'scanf'
import { ecdsaVerify } from 'secp256k1'
import { Multiaddr } from 'multiaddr'
import base64url from 'base64url'
import { arrToBufArr, bufArrToArr } from '@ethereumjs/util'
import RLP from 'rlp'
import { PeerInfo } from '../dpt'
import { toNewUint8Array, keccak256 } from '../util'
import { ecdsaVerify } from 'ethereum-cryptography/secp256k1-compat'

const Convert = require('multiaddr/src/convert')

Expand Down Expand Up @@ -52,7 +51,7 @@ export class ENR {
throw new Error(`String encoded ENR must start with '${this.RECORD_PREFIX}'`)

// ENRs are RLP encoded and written to DNS TXT entries as base64 url-safe strings
const base64BufferEnr = base64url.toBuffer(enr.slice(this.RECORD_PREFIX.length))
const base64BufferEnr = Buffer.from(base64url.decode(enr.slice(this.RECORD_PREFIX.length)))
const decoded = arrToBufArr(RLP.decode(Uint8Array.from(base64BufferEnr))) as Buffer[]
const [signature, seq, ...kvs] = decoded

Expand Down Expand Up @@ -109,14 +108,17 @@ export class ENR {
if (!rootVals.seq) throw new Error("Could not parse 'seq' value from ENR root entry")
if (!rootVals.signature) throw new Error("Could not parse 'sig' value from ENR root entry")

const decodedPublicKey = base32.decode.asBytes(publicKey)
const decodedPublicKey = [...base32.decode(publicKey + '===').values()]

// The signature is a 65-byte secp256k1 over the keccak256 hash
// of the record content, excluding the `sig=` part, encoded as URL-safe base64 string
// (Trailing recovery bit must be trimmed to pass `ecdsaVerify` method)
const signedComponent = root.split(' sig')[0]
const signedComponentBuffer = Buffer.from(signedComponent)
const signatureBuffer = base64url.toBuffer(rootVals.signature).slice(0, 64)
const signatureBuffer = Buffer.from(
[...base64url.decode(rootVals.signature + '=').values()].slice(0, 64)
)

const keyBuffer = Buffer.from(decodedPublicKey)

const isVerified = ecdsaVerify(signatureBuffer, keccak256(signedComponentBuffer), keyBuffer)
Expand Down
4 changes: 2 additions & 2 deletions packages/devp2p/src/dpt/dpt.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ms from 'ms'
import { EventEmitter } from 'events'
import { publicKeyCreate } from 'secp256k1'
import { getPublicKey } from 'ethereum-cryptography/secp256k1'
import { randomBytes } from 'crypto'
// import { debug as createDebugLogger } from 'debug'
import { devp2pDebug } from '../util'
Expand Down Expand Up @@ -106,7 +106,7 @@ export class DPT extends EventEmitter {
super()

this.privateKey = Buffer.from(privateKey)
this._id = pk2id(Buffer.from(publicKeyCreate(this.privateKey, false)))
this._id = pk2id(Buffer.from(getPublicKey(this.privateKey, false)))
this._shouldFindNeighbours = options.shouldFindNeighbours === false ? false : true
this._shouldGetDnsPeers = options.shouldGetDnsPeers ?? false
// By default, tries to connect to 12 new peers every 3s
Expand Down
6 changes: 3 additions & 3 deletions packages/devp2p/src/dpt/message.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { debug as createDebugLogger } from 'debug'
import ip from 'ip'
import secp256k1 from 'secp256k1'
import { bufArrToArr } from '@ethereumjs/util'
import RLP from 'rlp'
import { ecdsaRecover, ecdsaSign } from 'ethereum-cryptography/secp256k1-compat'
import { keccak256, int2buffer, buffer2int, assertEq, unstrictDecode } from '../util'
import { PeerInfo } from './dpt'

Expand Down Expand Up @@ -176,7 +176,7 @@ export function encode<T>(typename: string, data: T, privateKey: Buffer) {
])

const sighash = keccak256(typedata)
const sig = secp256k1.ecdsaSign(sighash, privateKey)
const sig = ecdsaSign(sighash, privateKey)
const hashdata = Buffer.concat([Buffer.from(sig.signature), Buffer.from([sig.recid]), typedata])
const hash = keccak256(hashdata)
return Buffer.concat([hash, hashdata])
Expand All @@ -195,7 +195,7 @@ export function decode(buffer: Buffer) {
const sighash = keccak256(typedata)
const signature = buffer.slice(32, 96)
const recoverId = buffer[96]
const publicKey = Buffer.from(secp256k1.ecdsaRecover(signature, recoverId, sighash, false))
const publicKey = Buffer.from(ecdsaRecover(signature, recoverId, sighash, false))

return { typename, data, publicKey }
}
12 changes: 6 additions & 6 deletions packages/devp2p/src/rlpx/ecies.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import crypto, { Decipher } from 'crypto'
import { debug as createDebugLogger } from 'debug'
import { publicKeyCreate, ecdh, ecdsaRecover, ecdsaSign } from 'secp256k1'
import { bufArrToArr } from '@ethereumjs/util'
import RLP from 'rlp'
import { getPublicKey } from 'ethereum-cryptography/secp256k1'
import { unstrictDecode } from '../util'
import { MAC } from './mac'

Expand All @@ -17,6 +17,7 @@ import {
buffer2int,
zfill,
} from '../util'
import { ecdsaSign, ecdsaRecover, ecdh } from 'ethereum-cryptography/secp256k1-compat'

const debug = createDebugLogger('devp2p:rlpx:peer')

Expand All @@ -26,10 +27,9 @@ function ecdhX(publicKey: Buffer, privateKey: Buffer) {
const pubKey = new Uint8Array(33)
pubKey[0] = (y[31] & 1) === 0 ? 0x02 : 0x03
pubKey.set(x, 1)
return pubKey
return pubKey.slice(1)
}
// @ts-ignore
return Buffer.from(ecdh(publicKey, privateKey, { hashfn }, Buffer.alloc(33)).slice(1))
return Buffer.from(ecdh(publicKey, privateKey, { hashfn: hashfn }, Buffer.alloc(32)))
}

// a straigth rip from python interop w/go ecies implementation
Expand Down Expand Up @@ -80,7 +80,7 @@ export class ECIES {

this._nonce = crypto.randomBytes(32)
this._ephemeralPrivateKey = genPrivateKey()
this._ephemeralPublicKey = Buffer.from(publicKeyCreate(this._ephemeralPrivateKey, false))
this._ephemeralPublicKey = Buffer.from(getPublicKey(this._ephemeralPrivateKey, false))
}

_encryptMessage(data: Buffer, sharedMacData: Buffer | null = null): Buffer | undefined {
Expand All @@ -106,7 +106,7 @@ export class ECIES {
.update(Buffer.concat([dataIV, sharedMacData]))
.digest()

const publicKey = publicKeyCreate(privateKey, false)
const publicKey = getPublicKey(privateKey, false)
return Buffer.concat([publicKey, dataIV, tag])
}

Expand Down
10 changes: 6 additions & 4 deletions packages/devp2p/src/rlpx/mac.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { createCipheriv } from 'crypto'
import createKeccakHash from 'keccak'
import { keccak256 } from 'ethereum-cryptography/keccak'
import { xor } from '../util'

export type Hash = ReturnType<typeof keccak256.create>

export class MAC {
_hash: any
_hash: Hash
_secret: Buffer
constructor(secret: Buffer) {
this._hash = createKeccakHash('keccak256')
this._hash = keccak256.create()
this._secret = secret
}

Expand All @@ -29,6 +31,6 @@ export class MAC {
}

digest() {
return this._hash._clone().digest().slice(0, 16)
return Buffer.from(this._hash.clone().digest().slice(0, 16))
}
}
4 changes: 2 additions & 2 deletions packages/devp2p/src/rlpx/rlpx.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as net from 'net'
import * as os from 'os'
import ms from 'ms'
import { publicKeyCreate } from 'secp256k1'
import { getPublicKey } from 'ethereum-cryptography/secp256k1'
import { EventEmitter } from 'events'
import { debug as createDebugLogger, Debugger } from 'debug'
import { devp2pDebug } from '../util'
Expand Down Expand Up @@ -54,7 +54,7 @@ export class RLPx extends EventEmitter {
super()

this._privateKey = Buffer.from(privateKey)
this._id = pk2id(Buffer.from(publicKeyCreate(this._privateKey, false)))
this._id = pk2id(Buffer.from(getPublicKey(this._privateKey, false)))

// options
this._timeout = options.timeout ?? ms('10s')
Expand Down
12 changes: 6 additions & 6 deletions packages/devp2p/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { randomBytes } from 'crypto'
import { privateKeyVerify, publicKeyConvert } from 'secp256k1'
import createKeccakHash from 'keccak'
import { arrToBufArr } from '@ethereumjs/util'
import RLP from 'rlp'
import { utils } from 'ethereum-cryptography/secp256k1'
import { publicKeyConvert } from 'ethereum-cryptography/secp256k1-compat'
import { keccak256 as _keccak256 } from 'ethereum-cryptography/keccak'
import { ETH } from './protocol/eth'
import { LES } from './protocol/les'
import { debug as createDebugLogger } from 'debug'
Expand All @@ -11,12 +11,12 @@ export const devp2pDebug = createDebugLogger('devp2p')

export function keccak256(...buffers: Buffer[]) {
const buffer = Buffer.concat(buffers)
return createKeccakHash('keccak256').update(buffer).digest()
return Buffer.from(_keccak256(buffer))
}

export function genPrivateKey(): Buffer {
const privateKey = randomBytes(32)
return privateKeyVerify(privateKey) ? privateKey : genPrivateKey()
const privateKey = utils.randomPrivateKey()
return utils.isValidPrivateKey(privateKey) ? Buffer.from(privateKey) : genPrivateKey()
}

export function pk2id(pk: Buffer): Buffer {
Expand Down
4 changes: 2 additions & 2 deletions packages/devp2p/test/dpt-message.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { publicKeyCreate } from 'ethereum-cryptography/secp256k1-compat'
import test from 'tape'
import * as secp256k1 from 'secp256k1'
import * as message from '../src/dpt/message'

const privateKey = Buffer.from(
'b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291',
'hex'
)
const publicKey = Buffer.from(secp256k1.publicKeyCreate(privateKey, false))
const publicKey = Buffer.from(publicKeyCreate(privateKey, false))

test('ping packet with version 4, additional list elements', (t) => {
const buffer = Buffer.from(
Expand Down
6 changes: 3 additions & 3 deletions packages/devp2p/test/rlpx-ecies.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { randomBytes } from 'crypto'
import * as secp256k1 from 'secp256k1'
import test, { Test } from 'tape'
import * as util from '../src/util'
import { ECIES } from '../src/rlpx/ecies'

import testdata from './testdata.json'
import { publicKeyCreate } from 'ethereum-cryptography/secp256k1-compat'

declare module 'tape' {
export interface Test {
Expand All @@ -16,8 +16,8 @@ function randomBefore(fn: Function) {
return (t: Test) => {
const privateKey1 = util.genPrivateKey()
const privateKey2 = util.genPrivateKey()
const publicKey1 = Buffer.from(secp256k1.publicKeyCreate(privateKey1, false))
const publicKey2 = Buffer.from(secp256k1.publicKeyCreate(privateKey2, false))
const publicKey1 = Buffer.from(publicKeyCreate(privateKey1, false))
const publicKey2 = Buffer.from(publicKeyCreate(privateKey2, false))
t.context = {
a: new ECIES(privateKey1, util.pk2id(publicKey1), util.pk2id(publicKey2)),
b: new ECIES(privateKey2, util.pk2id(publicKey2), util.pk2id(publicKey1)),
Expand Down