타원 곡선 검증 가능 랜덤 함수
verifiable random function(VRF)은 난수를 생성하고 그 수가 secret key를 사용해 생성되었음을 증명할 수 있게 하는 cryptographic primitive이다. 누구나 secret key에 대응하는 public key를 사용해 그 증명을 검증할 수 있으므로, 이는 누구나 검증할 수 있는 출력을 생성하는 random number generator(RNG)로 사용할 수 있다. 온체인에서 verifiable randomness가 필요한 애플리케이션도 이를 통해 이점을 얻을 수 있다.
VRF construction
Sui의 Move API에서 사용하는 VRF는 CFRG VRF draft specifications version 15를 따르는 elliptic curve VRF(ECVRF)이다. 이는 SHA-512 hash function과 함께 Ristretto255 elliptic curve group construction을 사용한다. nonce는 RFC6979에 따라 생성된다.
같은 specification을 따르고 suite string으로 sui_vrf를 사용하는 구현이라면 모두 VRF output을 계산하고 proof를 생성하는 데 사용할 수 있다(VRF specs의 section 5 참조).
fastcrypto library는 이런 구현을 위한 CLI tool을 제공하며, 다음 예시에서 이를 사용한다.
Generate keys
fastcrypto repository의 root에서 다음 command를 실행해 key pair를 생성한다:
$ cargo run --bin ecvrf-cli keygen
이 command는 secret key와 public key를 모두 hex format으로 출력한다. secret key와 public key는 모두 32-byte string이다:
Secret key: c0cbc5bf0b2f992fe14fee0327463c7b03d14cbbcb38ce2584d95ee0c112b40b
Public key: 928744da5ffa614d65dd1d5659a8e9dd558e68f8565946ef3d54215d90cba015
Compute VRF output and proof
입력 string Hello, World!의 VRF output과 proof를 계산하려면, 이 값의 hexadecimal 표현인 48656c6c6f2c20776f726c6421과 앞서 생성한 key pair를 사용해 다음 command를 실행한다:
$ cargo run --bin ecvrf-cli prove --input 48656c6c6f2c20776f726c6421 --secret-key c0cbc5bf0b2f992fe14fee0327463c7b03d14cbbcb38ce2584d95ee0c112b40b
이 command는 80-byte proof와 64-byte VRF output을 모두 hex format으로 출력해야 한다:
Proof: 18ccf8bf316f00b387fc6e7b26f2d3ddadbf5e9c66d3a30986f12b208108551f9c6da87793a857d79261338a50430074b1dbc7f8f05e492149c51313381248b4229ebdda367146dbbbf95809c7fb330d
Output: 2b7e45821d80567761e8bb3fc519efe5ad80cdb4423227289f960319bbcf6eea1aef30c023617d73f589f98272b87563c6669f82b51dafbeb5b9cf3b17c73437
Verify proof
Sui Move framework의 sui::ecvrf::ecvrf_verify를 사용하면 smart contract 안에서 proof와 output을 검증할 수 있다:
module math::ecvrf_test {
use sui::ecvrf;
use sui::event;
/// output이 검증되었는지 여부에 대한 event이다.
struct VerifiedEvent has copy, drop {
is_verified: bool,
}
public fun verify_ecvrf_output(output: vector<u8>, alpha_string: vector<u8>, public_key: vector<u8>, proof: vector<u8>) {
event::emit(VerifiedEvent {is_verified: ecvrf::ecvrf_verify(&output, &alpha_string, &public_key, &proof)});
}
}
검증에는 CLI tool도 사용할 수 있다:
$ cargo run --bin ecvrf-cli verify --output 2b7e45821d80567761e8bb3fc519efe5ad80cdb4423227289f960319bbcf6eea1aef30c023617d73f589f98272b87563c6669f82b51dafbeb5b9cf3b17c73437 --proof 18ccf8bf316f00b387fc6e7b26f2d3ddadbf5e9c66d3a30986f12b208108551f9c6da87793a857d79261338a50430074b1dbc7f8f05e492149c51313381248b4229ebdda367146dbbbf95809c7fb330d --input 48656c6c6f2c20776f726c6421 --public-key 928744da5ffa614d65dd1d5659a8e9dd558e68f8565946ef3d54215d90cba015
위 command는 다음과 같은 검증 결과를 반환한다:
Proof verified correctly!