From e8e30a87d2766e15e37a66aacf3a5896032a3403 Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Thu, 18 Jul 2024 14:03:05 +0200 Subject: [PATCH 1/7] Add P256 example --- .../standard-library/cryptography/p256.mdx | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/pages/core/standard-library/cryptography/p256.mdx b/src/pages/core/standard-library/cryptography/p256.mdx index 21254c4d..b49b975f 100644 --- a/src/pages/core/standard-library/cryptography/p256.mdx +++ b/src/pages/core/standard-library/cryptography/p256.mdx @@ -12,6 +12,45 @@ added to CosmWasm. ## Example -## Signature verification +### Signature verification -TODO: Add example as soon as secp256r1 is properly released +```rust filename="contract.rs" template="core" +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query( + deps: Deps, + _env: Env, + msg: EcdsaVerifyMsg, +) -> StdResult { + let public_key = msg.public_key; + let signature = msg.signature; + let message_hash = msg.message_hash; + + // Verify the signature. On chain! + let is_valid = deps.api.secp256r1_verify(&message_hash, &signature, &public_key)?; + let response = format!("{{ \"is_valid\": {is_valid} }}"); + + Ok(QueryResponse::new(response.into_bytes())) +} +``` + +### Public key recovery + +```rust filename="contract.rs" template="core" +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query( + deps: Deps, + _env: Env, + msg: EcdsaRecoverMsg, +) -> StdResult { + let signature = msg.signature; + let message_hash = msg.message_hash; + let recovery_id = msg.recovery_id; + + // Recover the public key. On chain! + let public_key = deps.api.secp256r1_recover_pubkey(&message_hash, &signature, recovery_id)?; + let public_key = HexBinary::from(public_key).to_hex(); + let response = format!("{{ \"public_key\": \"{public_key}\" }}"); + + Ok(QueryResponse::new(response.into_bytes())) +} +``` From 623a8fd1fb1709e7ad634884c8e53c7da832fecd Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Thu, 18 Jul 2024 14:12:55 +0200 Subject: [PATCH 2/7] Add BLS12-381 doctests --- docs-test-gen/templates/core.tpl | 8 +++++ .../cryptography/bls12-381.mdx | 36 ++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/docs-test-gen/templates/core.tpl b/docs-test-gen/templates/core.tpl index e87e73ca..51becfb3 100644 --- a/docs-test-gen/templates/core.tpl +++ b/docs-test-gen/templates/core.tpl @@ -35,6 +35,14 @@ struct Ed25519VerifyMsg { signature: Binary, } +#[cw_serde] +struct Bls12VerifyMsg { + signature: Binary, + pubkey: Binary, + msg: Binary, + dst: Binary, +} + #[cw_serde] struct ExecuteMsg {} diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx index 7125a154..848f2501 100644 --- a/src/pages/core/standard-library/cryptography/bls12-381.mdx +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -20,6 +20,40 @@ CosmWasm offers a byte-oriented API for signature verification. This API also doesn't care whether the public key is part of the G1 or G2 group (same for the other components). They just have to somehow fit together. -TODO: Add example as soon as BLS12-381 is properly released +## Verify on G1 + +```rust filename="contract.rs" template="core" +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query( + deps: Deps, + _env: Env, + msg: Bls12VerifyMsg, +) -> StdResult { + // Verify the signature. On chain! + let msg_hash = deps.api.bls12_381_hash_to_g2(HashFunction::Sha256, &msg.msg, &msg.dst)?; + let is_valid = deps.api.bls12_381_pairing_equality(&BLS12_381_G1_GENERATOR, &msg.signature, &msg.pubkey, &msg_hash)?; + let response = format!("{{ \"is_valid\": {is_valid} }}"); + + Ok(QueryResponse::new(response.into_bytes())) +} +``` + +## Verify on G2 + +```rust filename="contract.rs" template="core" +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query( + deps: Deps, + _env: Env, + msg: Bls12VerifyMsg, +) -> StdResult { + // Verify the signature. On chain! + let msg_hash = deps.api.bls12_381_hash_to_g1(HashFunction::Sha256, &msg.msg, &msg.dst)?; + let is_valid = deps.api.bls12_381_pairing_equality(&BLS12_381_G2_GENERATOR, &msg.signature, &msg.pubkey, &msg_hash)?; + let response = format!("{{ \"is_valid\": {is_valid} }}"); + + Ok(QueryResponse::new(response.into_bytes())) +} +``` [drand]: https://drand.love/ From 9509ab94f4dbfe2ee0d72f081425e9ac0a57384d Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Thu, 18 Jul 2024 15:03:06 +0200 Subject: [PATCH 3/7] Fix argument order --- src/pages/core/standard-library/cryptography/bls12-381.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx index 848f2501..44400058 100644 --- a/src/pages/core/standard-library/cryptography/bls12-381.mdx +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -49,7 +49,7 @@ pub fn query( ) -> StdResult { // Verify the signature. On chain! let msg_hash = deps.api.bls12_381_hash_to_g1(HashFunction::Sha256, &msg.msg, &msg.dst)?; - let is_valid = deps.api.bls12_381_pairing_equality(&BLS12_381_G2_GENERATOR, &msg.signature, &msg.pubkey, &msg_hash)?; + let is_valid = deps.api.bls12_381_pairing_equality(&msg.signature, &BLS12_381_G2_GENERATOR, &msg.pubkey, &msg_hash)?; let response = format!("{{ \"is_valid\": {is_valid} }}"); Ok(QueryResponse::new(response.into_bytes())) From 80e1df8c5fad6f3e05a86d841dc3720d6e78096b Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Thu, 18 Jul 2024 15:08:40 +0200 Subject: [PATCH 4/7] Use typed responses --- docs-test-gen/templates/core.tpl | 10 ++++++++++ .../standard-library/cryptography/bls12-381.mdx | 12 ++++++++---- .../core/standard-library/cryptography/ed25519.mdx | 6 ++++-- .../core/standard-library/cryptography/k256.mdx | 13 ++++++++----- .../core/standard-library/cryptography/p256.mdx | 13 ++++++++----- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/docs-test-gen/templates/core.tpl b/docs-test-gen/templates/core.tpl index 51becfb3..4eeddc01 100644 --- a/docs-test-gen/templates/core.tpl +++ b/docs-test-gen/templates/core.tpl @@ -43,6 +43,16 @@ struct Bls12VerifyMsg { dst: Binary, } +#[cw_serde] +struct RecoveryResponse { + public_key: HexBinary, +} + +#[cw_serde] +struct VerifyResponse { + is_valid: bool, +} + #[cw_serde] struct ExecuteMsg {} diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx index 44400058..f4cc3880 100644 --- a/src/pages/core/standard-library/cryptography/bls12-381.mdx +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -32,9 +32,11 @@ pub fn query( // Verify the signature. On chain! let msg_hash = deps.api.bls12_381_hash_to_g2(HashFunction::Sha256, &msg.msg, &msg.dst)?; let is_valid = deps.api.bls12_381_pairing_equality(&BLS12_381_G1_GENERATOR, &msg.signature, &msg.pubkey, &msg_hash)?; - let response = format!("{{ \"is_valid\": {is_valid} }}"); + let response = to_json_binary(&VerifyResponse { + is_valid + })?; - Ok(QueryResponse::new(response.into_bytes())) + Ok(response) } ``` @@ -50,9 +52,11 @@ pub fn query( // Verify the signature. On chain! let msg_hash = deps.api.bls12_381_hash_to_g1(HashFunction::Sha256, &msg.msg, &msg.dst)?; let is_valid = deps.api.bls12_381_pairing_equality(&msg.signature, &BLS12_381_G2_GENERATOR, &msg.pubkey, &msg_hash)?; - let response = format!("{{ \"is_valid\": {is_valid} }}"); + let response = to_json_binary(&VerifyResponse { + is_valid + })?; - Ok(QueryResponse::new(response.into_bytes())) + Ok(response) } ``` diff --git a/src/pages/core/standard-library/cryptography/ed25519.mdx b/src/pages/core/standard-library/cryptography/ed25519.mdx index e40eaec4..0963c36d 100644 --- a/src/pages/core/standard-library/cryptography/ed25519.mdx +++ b/src/pages/core/standard-library/cryptography/ed25519.mdx @@ -29,9 +29,11 @@ pub fn query( // Verify the signature. On chain! let is_valid = deps.api.ed25519_verify(&message, &signature, &public_key)?; - let response = format!("{{ \"is_valid\": {is_valid} }}"); + let response = to_json_binary(&VerifyResponse { + is_valid + })?; - Ok(QueryResponse::new(response.into_bytes())) + Ok(response) } ``` diff --git a/src/pages/core/standard-library/cryptography/k256.mdx b/src/pages/core/standard-library/cryptography/k256.mdx index dbaad897..78d41816 100644 --- a/src/pages/core/standard-library/cryptography/k256.mdx +++ b/src/pages/core/standard-library/cryptography/k256.mdx @@ -29,9 +29,11 @@ pub fn query( // Verify the signature. On chain! let is_valid = deps.api.secp256k1_verify(&message_hash, &signature, &public_key)?; - let response = format!("{{ \"is_valid\": {is_valid} }}"); + let response = to_json_binary(&VerifyResponse { + is_valid + })?; - Ok(QueryResponse::new(response.into_bytes())) + Ok(response) } ``` @@ -50,9 +52,10 @@ pub fn query( // Recover the public key. On chain! let public_key = deps.api.secp256k1_recover_pubkey(&message_hash, &signature, recovery_id)?; - let public_key = HexBinary::from(public_key).to_hex(); - let response = format!("{{ \"public_key\": \"{public_key}\" }}"); + let response = to_json_binary(&RecoveryResponse { + public_key: public_key.into(), + })?; - Ok(QueryResponse::new(response.into_bytes())) + Ok(response) } ``` diff --git a/src/pages/core/standard-library/cryptography/p256.mdx b/src/pages/core/standard-library/cryptography/p256.mdx index b49b975f..096375eb 100644 --- a/src/pages/core/standard-library/cryptography/p256.mdx +++ b/src/pages/core/standard-library/cryptography/p256.mdx @@ -27,9 +27,11 @@ pub fn query( // Verify the signature. On chain! let is_valid = deps.api.secp256r1_verify(&message_hash, &signature, &public_key)?; - let response = format!("{{ \"is_valid\": {is_valid} }}"); + let response = to_json_binary(&VerifyResponse { + is_valid + })?; - Ok(QueryResponse::new(response.into_bytes())) + Ok(response) } ``` @@ -48,9 +50,10 @@ pub fn query( // Recover the public key. On chain! let public_key = deps.api.secp256r1_recover_pubkey(&message_hash, &signature, recovery_id)?; - let public_key = HexBinary::from(public_key).to_hex(); - let response = format!("{{ \"public_key\": \"{public_key}\" }}"); + let response = to_json_binary(&RecoveryResponse { + public_key: public_key.into(), + })?; - Ok(QueryResponse::new(response.into_bytes())) + Ok(response) } ``` From f4fbdb2b83e0ae3f4d15fab895ec179a12852758 Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Thu, 18 Jul 2024 15:16:25 +0200 Subject: [PATCH 5/7] Update src/pages/core/standard-library/cryptography/bls12-381.mdx Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- src/pages/core/standard-library/cryptography/bls12-381.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx index f4cc3880..c649e67c 100644 --- a/src/pages/core/standard-library/cryptography/bls12-381.mdx +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -42,6 +42,8 @@ pub fn query( ## Verify on G2 +Signature verification with public key in G2 (See https://hackmd.io/@benjaminion/bls12-381#Verification in combination with https://hackmd.io/@benjaminion/bls12-381#Swapping-G1-and-G2): + ```rust filename="contract.rs" template="core" #[cfg_attr(not(feature = "library"), entry_point)] pub fn query( From 760b433ad9798756f6bb0636ded4808e1e933756 Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Thu, 18 Jul 2024 15:16:33 +0200 Subject: [PATCH 6/7] Update src/pages/core/standard-library/cryptography/bls12-381.mdx Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- src/pages/core/standard-library/cryptography/bls12-381.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx index c649e67c..15686379 100644 --- a/src/pages/core/standard-library/cryptography/bls12-381.mdx +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -22,6 +22,8 @@ other components). They just have to somehow fit together. ## Verify on G1 +Signature verification with public key in G1: + ```rust filename="contract.rs" template="core" #[cfg_attr(not(feature = "library"), entry_point)] pub fn query( From b929b1be0240ea7e1ebf313565880ea15b1bcb4a Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Thu, 18 Jul 2024 15:16:47 +0200 Subject: [PATCH 7/7] Update src/pages/core/standard-library/cryptography/bls12-381.mdx Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- src/pages/core/standard-library/cryptography/bls12-381.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx index 15686379..a8e669b1 100644 --- a/src/pages/core/standard-library/cryptography/bls12-381.mdx +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -55,7 +55,7 @@ pub fn query( ) -> StdResult { // Verify the signature. On chain! let msg_hash = deps.api.bls12_381_hash_to_g1(HashFunction::Sha256, &msg.msg, &msg.dst)?; - let is_valid = deps.api.bls12_381_pairing_equality(&msg.signature, &BLS12_381_G2_GENERATOR, &msg.pubkey, &msg_hash)?; + let is_valid = deps.api.bls12_381_pairing_equality(&msg.signature, &BLS12_381_G2_GENERATOR, &msg_hash, &msg.pubkey)?; let response = to_json_binary(&VerifyResponse { is_valid })?;