[ethers.js] HD wallet으로 주소 파생

12개의 seed wallet이 있는 경우, 다음과 같이 파생 주소를 확인할 수 있다.

$ npm install ethers@^5.0.0

const { ethers } = require('ethers');

// 12개의 시드 단어를 여기에 입력하세요
const mnemonic = "Your seed 12 words here";

// HD Node 생성
const hdNode = ethers.utils.HDNode.fromMnemonic(mnemonic);

// 파생 경로 설정
const derivationPath = "m/44'/60'/0'/0/"; // "m/44'/905956'/0'/0/" 와 같이 사용도 가능

// 파생 주소 생성 및 출력 함수
function generateAddresses(count) {
    const addresses = [];
    for (let i = 0; i < count; i++) {
        const walletNode = hdNode.derivePath(derivationPath + i);
        console.log(i, walletNode.address);
        addresses.push({
            index: i,
            address: walletNode.address,
        });
    }
    return addresses;
}

// 원하는 주소 개수를 설정하세요
const numAddresses = 85535;
const addresses = generateAddresses(numAddresses);

[Ethereum] 트랜잭션 해시로부터 Public key 및 주소 얻기

Ethereum의 경우 버전에 따라 트랜잭션에 gasPrice를 쓸 지, maxFeePerGas/maxPriorityFeePerGas 를 쓸 지가 정해진다. https://ethereum.stackexchange.com/questions/147692/how-to-get-public-key-by-the-transaction-hash 를 참고.

주소를 얻을 때, Public key에서 앞의 한 바이트(0x04)를 빼고, keccak256을 돌리는 부분에 유의하자.

const { ethers } = require("hardhat");

// 트랜잭션 서명 값
// const r = "0xe680637b83a1dd102364503bd77979b87c92ba651132a4df8e839af69c20af95";
// const s = "0x65becfa32384747adb05f543397baaf23d1c55fa28d0c9a38924912dae6df28f";
// const v = 12266684226873;
// const chainId = 6133342113419;

// 트랜잭션 해시
const txHash = "0xc7159866fb5b94d291e8624bdc731b7a6d46533b398065de7aa7dd1af7b6aa36";
const ethermainHash = "0xef120deb6ff2e516ad44724d220c0cd73166d169a2a0b0f66dfb5613d2d6169c"
const sepoliaHash = "0xfe4ddad4cae9ea353fc91441ee5db6c70bd5468673d907926be92dd4b8a63f63"

// 실제 트랜잭션에 사용된 private key. 아무거나 넣자.
const privateKey = "0x0000000000000000000000000000000000000000000000000000000000000001";

// Web3 프로바이더 설정 (Hardhat 로컬 노드 사용 예시)
const provider = ethers.provider;

// 서명된 트랜잭션 정보 가져오기
async function getPublicKeyFromTransactionHash(provider, txHash) {
  // Fetch the transaction using the transaction hash and provier
  const tx = await provider.getTransaction(txHash);

  console.log(tx);

  // Extract the all the relevant fields from the transaction (We need all of them)
  const unsignedTx = {
    gasPrice: tx.gasPrice,
    gasLimit: tx.gasLimit,
    value: tx.value,
    nonce: tx.nonce,
    data: tx.data,
    chainId: tx.chainId,
    to: tx.to,
    type: tx.type,
    // maxFeePerGas: tx.maxFeePerGas,
    // maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
  };

  // Serializing tx without the signature
  const serializedTx = ethers.utils.serializeTransaction(unsignedTx);

  // Extract the signature (v, r, s) from the transaction
  const { v, r, s } = tx;

  // Join splitted signature
  const signature = ethers.utils.joinSignature({ v, r, s });

  const recoveredPublicKey = ethers.utils.recoverPublicKey(
    ethers.utils.keccak256(serializedTx),
    signature,
  );
  console.log("recoveredPublicKey:", recoveredPublicKey);
  const keccak = ethers.utils.keccak256("0x" + recoveredPublicKey.slice(4))
  console.log("keccak256 of recoveredPublicKey:", keccak, ethers.utils.keccak256("0x" + recoveredPublicKey.slice(4)));

  // Recover the address or public key with (replace recoverAddress by recoverPublicKey) associated with the transaction
  return ethers.utils.recoverAddress(
    ethers.utils.keccak256(serializedTx),
    signature
  );
}

async function main() {
  const address = await getPublicKeyFromTransactionHash(provider, txHash);

  console.log("Address:", address);
}

main()
.then(() => process.exit(0))
.catch((error) => {
    console.error(error);
    process.exit(1);
});

[Ethereum] 키와 주소

타원 곡선 함수, Elliptic curve cryptography 에서 다음 p를 사용

p = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1
y ** 2 mod p = (x ** 3 + 7) mod p

Private key -> Public key -> Address 로 얻는다.

개인키 (Private key)

k가 private key.

k = rand() % (2 ** 256), 따라서 256 bits, 64 bytes.

공개키 (Public key)

K가 public key로 (x, y) 좌표. G는 미리 정의된 값.

K = k * G = (x, y)

Public key, K를 표현할 때는 Standards for Efficient Cryptography (SEC1)Serialized EC public key prefixes 의 prefix를 사용해서 나타낸다. 이더리움은 uncompressed point만을 지원하므로 0x04 prefix로 사용한다. 따라서 0x04 뒤에 x와 y를 concatenate한다.

0x04 | x | y

주소 (Address)

keccak-256 Hash function을 사용. Public key (x, y)를 concatenate한 값(0x04가 붙지 않았다!)을 keccak-256 로 hash 값을 얻은 후 마지막 20 바이트 값을 사용한다.

(keccak-256(x | y))[-20:]

[OpenSSL] command line 명령으로 TLS 서버 실행하기

기본적으로 s_server 인자와 -accept 를 사용한다. cert파일과 key파일은 자체 인증서를 생성하든지, letsencrypt에서 얻든지 한다. https에 사용되는 인증서를 letsencrypt로부터 얻는 방법은 [TLS] Letsencrypt로부터 https 사용을 위한 인증서 얻기를 참고한다.

$ openssl s_server -accept 443 -key /etc/letsencrypt/live/blog.dasomoli.org/privkey.pem -cert /etc/letsencrypt/live/blog.dasomoli.org/fullchain.pem

-msg 를 사용하면 TLS 관련 메시지를 볼 수 있다. decrypted된 text만 보고 싶다면 -quiet 옵션을 주면 된다. stdout으로 출력된다.

[Python] sorted() 설명

sorted() 함수는 iterable로 정렬한 list를 만든다. doc string을 보자.

Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order.

설명에서 보이는대로 key로 function을 받아 그 function의 기준에 따라 정렬 가능하다. 순서를 작아지는 순서로 하고 싶다면, reverse 를 True로 주면 된다. 예를 들면 다음과 같다.

names = [ 'Bamtol', 'Mong', 'Justin', 'Jay']
sorted(names)
['Bamtol', 'Jay', 'Justin', 'Mong']

key를 len()으로 주고, 작아지는 순서대로 해보자.

sorted(names, key=len, reverse=True)
['Bamtol', 'Justin', 'Mong', 'Jay']

[Eclipse] Source code Navigation 단축키

Eclipse는 내부적으로 Indexer가 돌아서 이를 이용해 찾고 싶은 File, Funtion decalaration/definition, symbol 등을 찾을 수 있다. 내가 자주 쓰는 단축키는 다음과 같다.

  • F3: Funtion declaratiin/definition. 함수 선언이나, 함수 정의로 이동하고 싶을 때 사용한다.
  • Alt + ‘<-‘: 이전 코드. 이전에 보던 부분으로 돌아갈 때 사용한다.
  • Ctrl + Shift + ‘R’: File name 찾아서 열기. 파일 이름을 알 때, 혹은 앞 몇글자만 기억날 때, 찾아서 연다.
  • Ctrl + Shift + ‘G’: Workspace에서 Reference 찾기. 함수 호출되는 부분을 찾고 싶을 때 사용한다.
  • Ctrl + ‘H’: Search. 주로 File Search를 이용한다. Scope을 셋팅해서 쓰는 것도 좋다.
  • Ctrl + Alt + ‘G’: Workspace에서 Text 찾기. Ctrl + ‘H’ 대신 사용하기도 한다.
  • Ctrl + ‘O’: Quick Outline. 주로 함수를 찾아 이동할 때 사용한다.

ssh 접속 시 no matching key exchange method found. 문제

SSH 접속 시 다음과 같은 에러가 발생할 때가 있다.

Unable to negotiate with blog.dasomoli.org: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

OpenSSH가 7.0이상이면, 요 키 교환 알고리즘이 기본으로 켜져 있지 않아서 나는 문제인데, 다음과 같은 방법으로 해결 가능하다.

ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 user@host

이걸 명령 줄 때마다 하긴 귀찮으니까 ~/.ssh/config 파일 안에 다음 내용을 추가하면 된다.

Host blog.dasomoli.org
KexAlgorithms +diffie-hellman-group1-sha1

참고: Using OpenSSH with legacy SSH implementations