2016-11-03 11 views
1

ethereum 용 개인 키 암호화를 구현해야합니다. 이는 go-ethereum 구현과 호환되어야합니다 (Ruby 암호화 키는 Ethereum 구현에서도 작동해야 함).).aes-128-ctr + scrypt를 사용하여 Ruby에서 개인 키 암호화하기

리움 예를 들어 (16 진수 인코딩), 이와 같은 32 비트의 비밀 키를 사용

1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 

I이 키에게 go-ethereum 구현과 암호로 암호화 "패스워드"를 가져 오면, 그것을 출력이 생성

{ 
    "address":"1be31a94361a391bbafb2a4ccd704f57dc04d4bb", 
    "crypto":{ 
     "cipher":"aes-128-ctr", 
     "ciphertext":"62bbf1a5a93b8ba8c66b70b3381f9f5badf44b35287614d309d760ebeec47139", 
     "cipherparams":{ 
      "iv":"a4a6638ea73872c07d62fa065f37f790" 
     }, 
     "kdf":"scrypt", 
     "kdfparams":{ 
      "dklen":32, 
      "n":262144, 
      "p":1, 
      "r":8, 
      "salt":"69ccd8c258bb50ac2effd65837e09e45b8bd9a747a1a1f3558b65a16e2f46f1a" 
     }, 
     "mac":"68ca6bc011d4d656e12a34cefd28005dbf76d9cfac15db2eaa83920eec5b38a9" 
    }, 
    "id":"9863070b-6c16-4aef-8188-2a34660192bf", 
    "version":3 
} 
그래서

모든 KDF (키 유도 함수) 파라미터를 이용하여, 그것은 암호문 생성을

62bbf1a5a93b8ba8c66b70b3381f9f5badf44b35287614d309d760ebeec47139 
,

이제 Ruby를 사용하여 동일한 암호문을 재현하고 Go 구현을 살펴 보겠습니다.

# hard coded password 
password = "password" 

# hard coded test private key 
plain_private_key = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" 
puts "------------ Encryption input ------------ " 
puts "Clear private key = " + plain_private_key 

# Scrypt params, same as in Geth/Ethereum 
n = 262144 
r = 8 
p = 1 
dklen = 32 

# using same salt as Ethereum used 
salt = "69ccd8c258bb50ac2effd65837e09e45b8bd9a747a1a1f3558b65a16e2f46f1a" 
# using same iv as Ethereum used 
iv = "a4a6638ea73872c07d62fa065f37f790" 

puts "------------ Scrypt parameters ------------ " 
puts "Salt str = " + salt 
puts "Iv str = " + iv 
puts "n = " + n.to_s 
puts "r = " + r.to_s 
puts "p = " + p.to_s 
puts "dklen = " + dklen.to_s 

# Generate derived key 
derived_key = SCrypt::Engine.scrypt(password, salt, n, r, p, dklen) 
puts "------------ Scrypt output ------------ " 
puts "Derived key from password = " + derived_key.unpack("H*")[0] 

# Encrypt with derived key 
cipher_name = "aes-128-ctr" 
cipher = OpenSSL::Cipher.new cipher_name 
cipher.encrypt 
cipher.iv = iv 
cipher.key = derived_key 
encrypted = cipher.update([plain_private_key].pack("H*")) + cipher.final 
puts "------------ Encryption output ------------ " 
puts "Cipher text = " + encrypted.unpack("H*")[0] 

# Decrypt with derived key 
decipher = OpenSSL::Cipher.new cipher_name 
decipher.decrypt 
decipher.iv = iv 
decipher.key = derived_key 
decrypted = decipher.update(encrypted) + decipher.final 
decrypted_str = decrypted.unpack("H*")[0] 
puts "------------ Decryption output ------------ " 
puts "Decrypted: " + decrypted_str 
puts "Decryption worked: " + (plain_private_key == decrypted_str).to_s 

이것은 출력 :

------------ Encryption input ------------ 
Clear private key = 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 
------------ Scrypt parameters ------------ 
Salt str = 69ccd8c258bb50ac2effd65837e09e45b8bd9a747a1a1f3558b65a16e2f46f1a 
Iv str = a4a6638ea73872c07d62fa065f37f790 
n = 262144 
r = 8 
p = 1 
dklen = 32 
------------ Scrypt output ------------ 
Derived key = b6e4410aa658f21213c7e55bacbbd8093e67f7f1738e7235335b58a2b690dcf5 
------------ Encryption output ------------ 
Cipher text = 6fddd3d2199edf65a17d9277d2328f5357e70a5be2e173d17681883ef5a3a27e 
------------ Decryption output ------------ 
Decrypted: 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 
Decryption worked: true 

는 그러나 암호문이 go-ethereum이 같은 입력 및 매개 변수를 사용하여 생성 된 것과 다른이 내 코드입니다.

6fddd3d2199edf65a17d9277d2328f5357e70a5be2e173d17681883ef5a3a27e 

아무도 도와 줄 수 있습니까? 개인 키에 대한처럼

답변

0

키 유도 모두가 필요로하는 암호화를위한 IV의 소금 이진 문자열로 진수로 변환 할 수 동일한 방법 :

# using same salt as Ethereum used 
salt = ["69ccd8c258bb50ac2effd65837e09e45b8bd9a747a1a1f3558b65a16e2f46f1a"].pack('H*') 
# using same iv as Ethereum used 
iv = ["a4a6638ea73872c07d62fa065f37f790"].pack('H*') 

이 같은 결과를 제공합니다 이동 구현과 암호화 키 : 암호화 및 암호 해독은 첫 번째를 사용 : 나는 눈치 뭔가 다른, 즉이 즉각적인 문제와 관련이 없습니다


------------ Encryption output ------------ 
Cipher text = 62bbf1a5a93b8ba8c66b70b3381f9f5badf44b35287614d309d760ebeec47139 
16 바이트의 파생 키. 현재 Ruby OpenSSL 바인딩은 키를 올바른 길이로 잘라서 모든 것이 현재 작동하지만, change in future releases입니다. 즉, 업그레이드 한 후에 코드가 그대로 작동하지 않습니다. 아무것도가 변경되어있는 경우 (당신은 루비 구현해야하는 인증 키로서 사용되는 파생 키

cipher.key = derived_key[0...16] 

다른 16 바이트, 그래서 당신은 확인할 수 있습니다 올바른 키 길이를 제공해야합니다 그 구현을위한 Keccak 해쉬 함수).