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

Change to use curve25519-voi's VRF #633

Merged
merged 10 commits into from
Jun 26, 2023
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,3 @@ jobs:
- name: Build Linux
run: GOOS=linux GOARCH=${{ matrix.goarch }} CC=${{ matrix.gcc }} TARGET_HOST=${{ matrix.host }} make build
if: "env.GIT_DIFF != ''"
- name: Build Linux with Libsodium
run: GOOS=linux GOARCH=${{ matrix.goarch }} CC=${{ matrix.gcc }} TARGET_HOST=${{ matrix.host }} LIBSODIUM=1 make build
if: "env.GIT_DIFF != ''"
21 changes: 2 additions & 19 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,12 @@ jobs:
name: "${{ github.sha }}-05"
path: ./pkgs.txt.part.05

build-libsodium:
name: Build libsodium
runs-on: ubuntu-latest
needs: split-test-files
steps:
- uses: actions/checkout@v3
- run: make libsodium
- uses: actions/upload-artifact@v3
with:
name: libsodium
path: crypto/vrf/internal/vrf/sodium

tests:
Kynea0b marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ubuntu-latest
needs: build-libsodium
needs: split-test-files
strategy:
fail-fast: false
matrix:
vrf: ["r2ishiguro", "libsodium"]
part: ["00", "01", "02", "03", "04", "05"]
steps:
- uses: actions/setup-go@v4
Expand All @@ -74,13 +61,9 @@ jobs:
with:
name: "${{ github.sha }}-${{ matrix.part }}"
if: env.GIT_DIFF
- uses: actions/download-artifact@v3
with:
name: libsodium
path: crypto/vrf/internal/vrf/sodium
- name: test & coverage report creation
run: |
cat pkgs.txt.part.${{ matrix.part }} | xargs go test -mod=readonly -timeout 7m -race -coverprofile=${{ matrix.part }}profile.out -covermode=atomic -tags ${{ matrix.vrf }}
cat pkgs.txt.part.${{ matrix.part }} | xargs go test -mod=readonly -timeout 7m -race -coverprofile=${{ matrix.part }}profile.out -covermode=atomic
if: env.GIT_DIFF
- uses: actions/upload-artifact@v3
with:
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,6 @@ jobs:
docker load -i ${{ needs.e2e-build.outputs.CACHE_FILE }}
if: "env.GIT_DIFF != ''"

- name: Build libsodium
run: make libsodium

- name: Build e2e runner
working-directory: test/e2e
run: make runner
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

36 changes: 3 additions & 33 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ OUTPUT?=build/ostracon
INCLUDE = -I=${GOPATH}/src/github.com/Finschia/ostracon -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf
BUILD_TAGS ?= ostracon
VERSION := $(shell git describe --always)
ifeq ($(LIBSODIUM), 1)
BUILD_TAGS += libsodium
LIBSODIUM_TARGET = libsodium
else
BUILD_TAGS += r2ishiguro
LIBSODIUM_TARGET =
endif
LD_FLAGS = -X github.com/Finschia/ostracon/version.OCCoreSemVer=$(VERSION)
BUILD_FLAGS = -mod=readonly -ldflags "$(LD_FLAGS)"
HTTPS_GIT := https://github.com/Finschia/ostracon.git
Expand Down Expand Up @@ -64,11 +57,11 @@ include tests.mk
### Build Ostracon ###
###############################################################################

build: $(LIBSODIUM_TARGET)
build:
CGO_ENABLED=1 go build $(BUILD_FLAGS) -tags "$(BUILD_TAGS)" -o $(OUTPUT) ./cmd/ostracon/
.PHONY: build

install: $(LIBSODIUM_TARGET)
install:
CGO_ENABLED=1 go install $(BUILD_FLAGS) -tags "$(BUILD_TAGS)" ./cmd/ostracon
.PHONY: install

Expand Down Expand Up @@ -138,29 +131,6 @@ install_abci:
### Distribution ###
###############################################################################

########################################
### libsodium

VRF_ROOT = $(SRCPATH)/crypto/vrf/internal/vrf
LIBSODIUM_ROOT = $(VRF_ROOT)/libsodium
LIBSODIUM_OS = $(VRF_ROOT)/sodium/$(TARGET_OS)_$(TARGET_ARCH)
ifneq ($(TARGET_HOST), "")
LIBSODIUM_HOST = "--host=$(TARGET_HOST)"
endif

libsodium:
@if [ ! -f $(LIBSODIUM_OS)/lib/libsodium.a ]; then \
rm -rf $(LIBSODIUM_ROOT) && \
mkdir $(LIBSODIUM_ROOT) && \
git submodule update --init --recursive && \
cd $(LIBSODIUM_ROOT) && \
./autogen.sh && \
./configure --disable-shared --prefix="$(LIBSODIUM_OS)" $(LIBSODIUM_HOST) && \
$(MAKE) && \
$(MAKE) install; \
fi
.PHONY: libsodium

########################################
### Distribution

Expand Down Expand Up @@ -291,7 +261,7 @@ DOCKER_CMD = docker run --rm \
DOCKER_IMG = golang:1.18-alpine
BUILD_CMD = apk add --update --no-cache git make gcc libc-dev build-base curl jq bash file gmp-dev clang libtool autoconf automake \
&& cd $(DOCKER_HOME) \
&& LIBSODIUM=$(LIBSODIUM) make build-linux
&& make build-linux

# Login docker-container for confirmation building linux binary
build-shell:
Expand Down
12 changes: 0 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,6 @@ git clone https://github.com/Finschia/ostracon.git
git clone [email protected]:Finschia/ostracon.git
```

### git clone with recursive if you want to use libsodium
```shell
git clone --recursive https://github.com/Finschia/ostracon.git
# or
git clone --recursive [email protected]:Finschia/ostracon.git
```

### git submodule if you forget to clone with submodule
```shell
git submodule update --init --recursive
```

## Local Standalone
**Build**
```sh
Expand Down
2 changes: 1 addition & 1 deletion crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type PubKey interface {
Address() Address
Bytes() []byte
VerifySignature(msg []byte, sig []byte) bool
VRFVerify(proof Proof, seed []byte) (Output, error) // TODO 🏺 rename to VerifyVRFProof to match VerifySignature
VRFVerify(proof []byte, message []byte) (Output, error)
Equals(PubKey) bool
Type() string
}
Expand Down
34 changes: 13 additions & 21 deletions crypto/ed25519/ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import (
"fmt"
"io"

"golang.org/x/crypto/ed25519"

"github.com/Finschia/ostracon/crypto"
"github.com/Finschia/ostracon/crypto/tmhash"
"github.com/Finschia/ostracon/crypto/vrf"
tmjson "github.com/Finschia/ostracon/libs/json"
"github.com/oasisprotocol/curve25519-voi/primitives/ed25519"
vrf "github.com/oasisprotocol/curve25519-voi/primitives/ed25519/extra/ecvrf"
)

//-------------------------------------
Expand Down Expand Up @@ -63,11 +62,8 @@ func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {

// VRFProve generates a VRF Proof for given message to generate a verifiable random.
func (privKey PrivKey) VRFProve(message []byte) (crypto.Proof, error) {
proof, err := vrf.Prove(privKey[:], message)
if err != nil {
return nil, err
}
return crypto.Proof(proof[:]), nil
proof := vrf.Prove(ed25519.PrivateKey(privKey[:]), message)
return proof, nil
}

// PubKey gets the corresponding public key from the private key.
Expand Down Expand Up @@ -173,21 +169,17 @@ func (pubKey PubKey) Type() string {
return KeyType
}

// VRFVerify verifies that the given VRF Proof was generated from the message by the owner of this public key.
func (pubKey PubKey) VRFVerify(proof crypto.Proof, message []byte) (crypto.Output, error) {
valid, err := vrf.Verify(pubKey[:], vrf.Proof(proof), message)
if err != nil {
return nil, fmt.Errorf("the specified proof is not a valid ed25519 proof: err: %s", err.Error())
}
if !valid {
return nil, fmt.Errorf("the specified Proof is not generated with this pair-key: %s",
// VRFVerify guarantees that the public key is validated such that the "full uniqueness" and
// "full collision" properties are satisfied.
// The internal function of VRFVerify is implemented based on the IETF draft.
// See sections 3.1 and 3.2 here https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/.
func (pubKey PubKey) VRFVerify(proof []byte, message []byte) (crypto.Output, error) {
isValid, hash := vrf.Verify(ed25519.PublicKey(pubKey), proof, message)
if !isValid {
return nil, fmt.Errorf("either Public Key or Proof is an invalid value.: err: %s",
hex.EncodeToString(proof))
}
output, err := vrf.ProofToHash(vrf.Proof(proof))
if err != nil {
return nil, err
}
return crypto.Output(output), nil
return hash, nil
}

func (pubKey PubKey) Equals(other crypto.PubKey) bool {
Expand Down
41 changes: 16 additions & 25 deletions crypto/ed25519/ed25519_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"encoding/hex"
"testing"

coniks "github.com/coniks-sys/coniks-go/crypto/vrf"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -36,7 +34,6 @@ func TestVRFProveAndVRFVerify(t *testing.T) {

privKey := ed25519.GenPrivKey()
pubKey := privKey.PubKey()

message, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000")
proof, err := privKey.VRFProve(message)
assert.Nil(t, err)
Expand All @@ -46,26 +43,20 @@ func TestVRFProveAndVRFVerify(t *testing.T) {
assert.Nil(t, err)
assert.NotNil(t, output)

// error
{
message, _ = hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000001")
output, err = pubKey.VRFVerify(proof, message)
assert.NotNil(t, err)
assert.Nil(t, output)
}

// invalid
{
privateKey, _ := coniks.GenerateKey(nil)
copy(privKey[:], privateKey)
pubKey = privKey.PubKey()

proof, err = privKey.VRFProve(message)
assert.Nil(t, err)
assert.NotNil(t, proof)

output, err = pubKey.VRFVerify(proof, message)
assert.NotNil(t, err)
assert.Nil(t, output)
}
// *** If the combination of (pubkey, message, proof) is incorrect ***
// invalid message
inValidMessage, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000001")
_, err1 := pubKey.VRFVerify(proof, inValidMessage)
assert.Error(t, err1)

// invalid pubkey
invalidPrivKey := ed25519.GenPrivKey()
invalidPubkey := invalidPrivKey.PubKey()
_, err2 := invalidPubkey.VRFVerify(proof, message)
assert.Error(t, err2)

// invalid proof
invalidProof, _ := invalidPrivKey.VRFProve(message)
_, err3 := pubKey.VRFVerify(invalidProof, message)
assert.Error(t, err3)
}
2 changes: 1 addition & 1 deletion crypto/secp256k1/secp256k1.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func (pubKey PubKey) String() string {
}

// VRFVerify is not supported in Secp256k1.
func (pubKey PubKey) VRFVerify(proof crypto.Proof, seed []byte) (crypto.Output, error) {
func (pubKey PubKey) VRFVerify(_ []byte, _ []byte) (crypto.Output, error) {
return nil, fmt.Errorf("VRF verify is not supported by the secp256k1")
}

Expand Down
2 changes: 1 addition & 1 deletion crypto/sr25519/pubkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (pubKey PubKey) VerifySignature(msg []byte, sig []byte) bool {
}

// VRFVerify is not supported in Sr25519.
func (pubKey PubKey) VRFVerify(proof crypto.Proof, seed []byte) (crypto.Output, error) {
func (pubKey PubKey) VRFVerify(_ []byte, _ []byte) (crypto.Output, error) {
return nil, fmt.Errorf("VRF verify is not supported by the sr25519")
}

Expand Down
97 changes: 0 additions & 97 deletions crypto/vrf/README.md

This file was deleted.

Loading