From 04e282ffcdbae71b235a8f62fde9e1fdf0cb4657 Mon Sep 17 00:00:00 2001
From: 6h057 <15034695+omarsy@users.noreply.github.com>
Date: Wed, 17 Apr 2024 16:55:45 +0200
Subject: [PATCH] feat(stdlibs): support crypto/ed25519.Verify (#1863)
Support crypto/ed25519 on GnoVM
Contributors' checklist...
- [x] Added new tests, or not needed, or not feasible
- [x] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [x] Updated the official documentation or not needed
- [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [ ] Added references to related issues and PRs
- [ ] Provided any useful hints for running manual tests
- [ ] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
---------
Signed-off-by: Norman Meier
Co-authored-by: Miguel Victoria Villaquiran
Co-authored-by: Norman Meier
Co-authored-by: n0izn0iz
---
docs/reference/go-gno-compatibility.md | 4 ++-
gnovm/stdlibs/crypto/ed25519/ed25519.gno | 8 +++++
gnovm/stdlibs/crypto/ed25519/ed25519.go | 9 +++++
gnovm/stdlibs/crypto/ed25519/ed25519_test.gno | 16 +++++++++
gnovm/stdlibs/native.go | 36 +++++++++++++++++++
5 files changed, 72 insertions(+), 1 deletion(-)
create mode 100644 gnovm/stdlibs/crypto/ed25519/ed25519.gno
create mode 100644 gnovm/stdlibs/crypto/ed25519/ed25519.go
create mode 100644 gnovm/stdlibs/crypto/ed25519/ed25519_test.gno
diff --git a/docs/reference/go-gno-compatibility.md b/docs/reference/go-gno-compatibility.md
index fbc7d10668e..87f4f1105c8 100644
--- a/docs/reference/go-gno-compatibility.md
+++ b/docs/reference/go-gno-compatibility.md
@@ -124,7 +124,7 @@ Legend:
| crypto/dsa | `tbd` |
| crypto/ecdh | `tbd` |
| crypto/ecdsa | `tbd` |
-| crypto/ed25519 | `tbd` |
+| crypto/ed25519 | `part`[^8] |
| crypto/elliptic | `tbd` |
| crypto/hmac | `todo` |
| crypto/md5 | `test`[^2] |
@@ -289,6 +289,8 @@ Legend:
bit of boilerplate, but you can use `sort.Interface` + `sort.Sort`!
[^7]: `time.Now` returns the block time rather than the system time, for
determinism. Concurrent functionality (such as `time.Ticker`) is not implemented.
+[^8]: `crypto/ed25519` is currently only implemented for `Verify`, which should
+ still cover a majority of use cases. A full implementation is welcome.
## Tooling (`gno` binary)
diff --git a/gnovm/stdlibs/crypto/ed25519/ed25519.gno b/gnovm/stdlibs/crypto/ed25519/ed25519.gno
new file mode 100644
index 00000000000..80c9d24085b
--- /dev/null
+++ b/gnovm/stdlibs/crypto/ed25519/ed25519.gno
@@ -0,0 +1,8 @@
+package ed25519
+
+// Verify returns true if the signature is valid for the message and public key.
+func Verify(publicKey []byte, message []byte, signature []byte) bool {
+ return verify(publicKey, message, signature)
+}
+
+func verify(publicKey []byte, message []byte, signature []byte) bool // injected
diff --git a/gnovm/stdlibs/crypto/ed25519/ed25519.go b/gnovm/stdlibs/crypto/ed25519/ed25519.go
new file mode 100644
index 00000000000..b19e6870312
--- /dev/null
+++ b/gnovm/stdlibs/crypto/ed25519/ed25519.go
@@ -0,0 +1,9 @@
+package ed25519
+
+import (
+ "crypto/ed25519"
+)
+
+func X_verify(publicKey []byte, message []byte, signature []byte) bool {
+ return ed25519.Verify(publicKey, message, signature)
+}
diff --git a/gnovm/stdlibs/crypto/ed25519/ed25519_test.gno b/gnovm/stdlibs/crypto/ed25519/ed25519_test.gno
new file mode 100644
index 00000000000..419c3bc61a7
--- /dev/null
+++ b/gnovm/stdlibs/crypto/ed25519/ed25519_test.gno
@@ -0,0 +1,16 @@
+package ed25519
+
+import (
+ "crypto/ed25519"
+ "encoding/hex"
+ "std"
+ "testing"
+)
+
+func TestVerify(t *testing.T) {
+ publicKey, _ := hex.DecodeString("0D853FA898A07EB91F618BB3E8B738B0E45BE9B3053799A2C42F8204F5FA3505")
+ signature, _ := hex.DecodeString("2B39638983858715AD2FA059665ADFE267936B8F20C4DA01E9650958E0CA65C0255C75164360F468087FE8385140E48EE3471E332472A50AEE599F9D0EADD106")
+ if !ed25519.Verify(publicKey, []byte("hello gno.land"), signature) {
+ t.Error("verify failed")
+ }
+}
diff --git a/gnovm/stdlibs/native.go b/gnovm/stdlibs/native.go
index dcd6305db43..3b1ab719e72 100644
--- a/gnovm/stdlibs/native.go
+++ b/gnovm/stdlibs/native.go
@@ -7,6 +7,7 @@ import (
"reflect"
gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
+ libs_crypto_ed25519 "github.com/gnolang/gno/gnovm/stdlibs/crypto/ed25519"
libs_crypto_sha256 "github.com/gnolang/gno/gnovm/stdlibs/crypto/sha256"
libs_math "github.com/gnolang/gno/gnovm/stdlibs/math"
libs_std "github.com/gnolang/gno/gnovm/stdlibs/std"
@@ -24,6 +25,41 @@ type nativeFunc struct {
}
var nativeFuncs = [...]nativeFunc{
+ {
+ "crypto/ed25519",
+ "verify",
+ []gno.FieldTypeExpr{
+ {Name: gno.N("p0"), Type: gno.X("[]byte")},
+ {Name: gno.N("p1"), Type: gno.X("[]byte")},
+ {Name: gno.N("p2"), Type: gno.X("[]byte")},
+ },
+ []gno.FieldTypeExpr{
+ {Name: gno.N("r0"), Type: gno.X("bool")},
+ },
+ func(m *gno.Machine) {
+ b := m.LastBlock()
+ var (
+ p0 []byte
+ rp0 = reflect.ValueOf(&p0).Elem()
+ p1 []byte
+ rp1 = reflect.ValueOf(&p1).Elem()
+ p2 []byte
+ rp2 = reflect.ValueOf(&p2).Elem()
+ )
+
+ gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0)
+ gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1)
+ gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 2, "")).TV, rp2)
+
+ r0 := libs_crypto_ed25519.X_verify(p0, p1, p2)
+
+ m.PushValue(gno.Go2GnoValue(
+ m.Alloc,
+ m.Store,
+ reflect.ValueOf(&r0).Elem(),
+ ))
+ },
+ },
{
"crypto/sha256",
"sum256",