Skip to content

Commit

Permalink
Merge pull request #1 from logicalmechanism/encryption-review-1
Browse files Browse the repository at this point in the history
use elgamal and prove bob could decrypt with knowing the actual msg
  • Loading branch information
logicalmechanism authored Jun 11, 2024
2 parents d42dac0 + 4e9a207 commit 32666bd
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

- uses: aiken-lang/[email protected]
with:
version: v1.0.26-alpha
version: v1.0.29-alpha

- run: aiken fmt --check
- run: aiken check -D
Expand Down
16 changes: 9 additions & 7 deletions lib/seedelf/bls12_381.ak
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@

use aiken/builtin

/// This is the g1 point from the zCash implementation.
pub fn g1() -> G1Element {
builtin.bls12_381_g1_uncompress(
#"97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
)
}
/// The generator of the G1 group of the BLS12-381 curve.
/// This constant represents a fixed base point on the elliptic curve.
pub const g1 =
#<Bls12_381, G1>"97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"

/// Represents the additive identity (zero) in the G1 group.
pub const zero =
#<Bls12_381, G1>"c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

/// This is mathematically equivalent to g^x mod q.
pub fn pk(sk: Int) -> G1Element {
builtin.bls12_381_g1_scalar_mul(sk, g1())
builtin.bls12_381_g1_scalar_mul(sk, g1)
}
185 changes: 185 additions & 0 deletions lib/seedelf/elgamal.ak
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
////
////

use aiken/builtin
use aiken/hash
use seedelf/bls12_381 as bls
use seedelf/types/zk.{Register}

pub type CypherText {
c1: ByteArray,
c2: ByteArray,
h: ByteArray,
}

/// Encrypt a bls123-381 encoded message to some register using the ElGamal
/// encryption scheme. The return type is the two-pair cypher text. These two
/// pieces of data make up the cypher to be passed to the owner of the regiser.
///
/// ```aiken
/// encryption.encrypt(msg, scaler, datum)
/// ```
pub fn encryption(msg: ByteArray, scaler: Int, datum: Register) -> CypherText {
//
// the message element
let m: G1Element = builtin.bls12_381_g1_uncompress(msg)
//
// generator element
let g: G1Element = builtin.bls12_381_g1_uncompress(datum.alpha)
//
// public key element
let u: G1Element = builtin.bls12_381_g1_uncompress(datum.beta)
//
// calculate the random scaler element as c1
let c1: G1Element = builtin.bls12_381_g1_scalar_mul(scaler, g)
//
// calculate the s element to add to the message element
let s: G1Element = builtin.bls12_381_g1_scalar_mul(scaler, u)
//
// add m and s together as c2
let c2: G1Element = builtin.bls12_381_g1_add(m, s)
//
// Build the cypher text element consisting of c1 and c2
CypherText {
c1: c1 |> builtin.bls12_381_g1_compress,
c2: c2 |> builtin.bls12_381_g1_compress,
h: hash.sha3_256(msg),
}
}

/// Decrypt a cypher text using a cypher key using the ElGamal encryption
/// scheme. The return type is the bls12-381 encoded message.
///
/// ```aiken
/// encryption.decrypt(cypher_text, cypher_key)
/// ```
pub fn decryption_proof(cypher_text: CypherText, cypher_key: ByteArray) -> Bool {
// convert the cypher text elements
let c2: G1Element = builtin.bls12_381_g1_uncompress(cypher_text.c2)
// multiply c1 by the secret key
let s: G1Element = builtin.bls12_381_g1_uncompress(cypher_key)
//
// Find the inverse of the s point
let neg_s: G1Element = builtin.bls12_381_g1_neg(s)
//
// decrypt the msg
let m: G1Element = builtin.bls12_381_g1_add(c2, neg_s)
let msg: ByteArray = m |> builtin.bls12_381_g1_compress
and {
!builtin.bls12_381_g1_equal(m, bls.zero),
hash.sha3_256(msg) == cypher_text.h,
}
}

/// Have Alice encrypt a message for Bob then Bob decrypts it.
test valid_decryption_proof() {
//
// the message Alice wants to encrypt
let msg: ByteArray = #"acab"
//
// encode the message as a point on the curve
let secret_msg: ByteArray =
bls.pk(builtin.bytearray_to_integer(True, msg))
|> builtin.bls12_381_g1_compress
//
// a random scaler selected by Alice
let scaler: Int =
44421586105950619360037151099874190412588687312032470042646096642156420779682
//
// Bob's secret x
let x: Int =
86478456268645743314319142250097583782656584143510069178425111699273215020899
//
// Bob's Datum
let datum: Register =
Register {
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
//
// Alice will encrypt the secret msg to Bob
let cypher_text: CypherText = encryption(secret_msg, scaler, datum)
//
// Bob will decrypt the msg
let c1: G1Element = builtin.bls12_381_g1_uncompress(cypher_text.c1)
//
// this would be done off chain to keep x private
let cypher_key: ByteArray =
builtin.bls12_381_g1_scalar_mul(x, c1)
|> builtin.bls12_381_g1_compress
//
// Prove that Bob could decrypt and its the correct msg
decryption_proof(cypher_text, cypher_key)
}

/// Have Alice encrypt a message for Carol then Bob decrypts it.
test invalid_decryption_proof() fail {
//
// the message Alice wants to encrypt
let msg: ByteArray = #"acab"
//
// encode the message as a point on the curve
let secret_msg: ByteArray =
bls.pk(builtin.bytearray_to_integer(True, msg))
|> builtin.bls12_381_g1_compress
//
// a random scaler selected by Alice
let scaler: Int =
44421586105950619360037151099874190412588687312032470042646096642156420779682
//
// Bob's secret x
let x: Int =
86478456268645743314319142250097583782656584143510069178425111699273215020899
// Carol's secret y
let y: Int =
50097583782656584143510069178425111699273215020899864784562686457433143191422
//
//
// Carol's Datum
let datum2: Register =
Register {
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(y) |> builtin.bls12_381_g1_compress,
}
//
// Alice will encrypt the secret msg to Carol
let cypher_text: CypherText = encryption(secret_msg, scaler, datum2)
//
// Bob will decrypt the msg
let c1: G1Element = builtin.bls12_381_g1_uncompress(cypher_text.c1)
//
// this would be done off chain to keep x private
let cypher_key: ByteArray =
builtin.bls12_381_g1_scalar_mul(x, c1)
|> builtin.bls12_381_g1_compress
//
// Prove that Bob could not decrypt the msg
decryption_proof(cypher_text, cypher_key)
}

/// There isn't anything being encrypted here, the message is the zero point.
test no_encryption_proof() fail {
//
// Bob's secret x
let x: Int =
86478456268645743314319142250097583782656584143510069178425111699273215020899
// the message Alice wants to encrypt
let msg: ByteArray = #"acab"
let cypher_text: CypherText =
CypherText {
c1: bls.g1 |> builtin.bls12_381_g1_compress,
c2: bls.pk(x) |> builtin.bls12_381_g1_compress,
h: hash.sha3_256(msg),
}
//
// Bob will decrypt the msg
let c1: G1Element = builtin.bls12_381_g1_uncompress(cypher_text.c1)
//
// this would be done off chain to keep x private
let cypher_key: ByteArray =
builtin.bls12_381_g1_scalar_mul(x, c1)
|> builtin.bls12_381_g1_compress
//
// Prove that Bob could not decrypt the msg
decryption_proof(cypher_text, cypher_key)
}
106 changes: 0 additions & 106 deletions lib/seedelf/encryption.ak

This file was deleted.

6 changes: 3 additions & 3 deletions lib/seedelf/signing.ak
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ test good_verify() {
// the datum register using the g1 generator and the public value for x
let datum: Register =
Register {
alpha: bls.g1() |> builtin.bls12_381_g1_compress,
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
// this message to sign
Expand Down Expand Up @@ -83,7 +83,7 @@ test rerandomized_good_verify() {
// the datum register using the g1 generator and the public value for x
let a0: Register =
Register {
alpha: bls.g1() |> builtin.bls12_381_g1_compress,
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
// The re-randomizer number
Expand Down Expand Up @@ -119,7 +119,7 @@ test bad_verify() fail {
// the datum register using the g1 generator and the public value for x
let datum: Register =
Register {
alpha: bls.g1() |> builtin.bls12_381_g1_compress,
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
// this message to sign
Expand Down
8 changes: 4 additions & 4 deletions lib/seedelf/spending.ak
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ test d_log_256_bit_secret() {
// the datum register using the g1 generator and the public value for x
let a0: Register =
Register {
alpha: bls.g1() |> builtin.bls12_381_g1_compress,
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
// a random number
Expand Down Expand Up @@ -132,7 +132,7 @@ test can_unlock_after_rerandomizing() {
// the datum register
let a0: Register =
Register {
alpha: bls.g1() |> builtin.bls12_381_g1_compress,
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
// The re-randomizer number
Expand Down Expand Up @@ -173,7 +173,7 @@ test cant_spend_good_verify_msg() fail {
// the datum register using the g1 generator and the public value for x
let datum: Register =
Register {
alpha: bls.g1() |> builtin.bls12_381_g1_compress,
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
// this message to sign
Expand Down Expand Up @@ -205,7 +205,7 @@ test many_unlocks() {
// the datum register
let a0: Register =
Register {
alpha: bls.g1() |> builtin.bls12_381_g1_compress,
alpha: bls.g1 |> builtin.bls12_381_g1_compress,
beta: bls.pk(x) |> builtin.bls12_381_g1_compress,
}
// The re-randomizer number
Expand Down

0 comments on commit 32666bd

Please sign in to comment.