ecka-eg

module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 15, 2024 License: ISC

README

ecka-eg

ISC License GoDoc Go Report Card

ECKA-EG Key Agreement Protocol

With verifiable encryption, Bob can prove to Alice that he has used a given encryption key of a ciphertext with a NIZK (Non-interactive Zero Knowledge Proof). In this case we will use ElGamal encryption and generate a proof of the public key which has been used for the encryption. If Bob uses Trent's public key to encrypt some ciphertext for Alice, then Bob can produce a proof that it has been encrypted with Trent's public key. Alice will then be able to check this against Trent's public key.

Theory

We initially create a private key as a random number x and a public key of:

With standard ElGamal encryption, we generate a random value r to give:

We then create a symmetric key from this elliptic curve point:

and where Derive just converts a point on the curve to a byte array value that is the length of the required symmetric encryption key (such as for 32 bytes in the case of 256-bit Anubis).

Next, we compute the ciphertext values of:


and where M is the msg value converted into a scalar value. We then append these together to create the additional data that will be used for the symmetric key encryption of the message:

We then generate a nonce value (Nonce) and then perform symmetric key encryption on the message:

The ciphertext then has values of C1, C2, Nonce, and cipher. C1, C2 are points on the curve, and the Nonce value and cipher are byte array values. To decrypt, we take the private key (x) and derive:




Here is an overview of the method:

To generate the proof, we generate a random value (r) and a blinding factor (b) to give two points on the elliptic curve:


Next, we create the challenge bytes with:

We take this value and hash it (H()), and create a scalar value with (ek) to produce:

We then create two Schnorr proof values:

To verify the proof, we reconstruct R1:

We reconstruct R2:

This works because:

We then reconstruct the challenge with:

We take this value and hash it (H()), and create a scalar value with (ek) to produce:

This value is then checked against the challenge in the proof, and if they are the same, the proof is verified.

Usage
package main

import (
   "fmt"

   "os"

   "github.com/pedroalbanese/ecka-eg/core/curves"
   "github.com/pedroalbanese/ecka-eg/elgamal"
)

func main() {

   argCount := len(os.Args[1:])
   val := "hello"
   if argCount > 0 {
   	val = os.Args[1]
   }

   domain := []byte("MyDomain")

   bls12381g1 := curves.BLS12381G1()
   ek, dk, _ := elgamal.NewKeys(bls12381g1)

   msgBytes := []byte(val)

   cs, proof, _ := ek.VerifiableEncrypt(msgBytes, &elgamal.EncryptParams{
   	Domain:          domain,
   	MessageIsHashed: true,
   	GenProof:        true,
   	ProofNonce:      domain,
   })

   fmt.Printf("=== ElGamal Verifiable Encryption ===\n")
   fmt.Printf("Input text: %s\n", val)
   fmt.Printf("=== Generating keys ===\n")
   res1, _ := ek.MarshalBinary()
   fmt.Printf("Public key %x\n", res1)
   res2, _ := dk.MarshalBinary()
   fmt.Printf("Private key %x\n", res2)
   fmt.Printf("=== Encrypting and Decrypting ===\n")
   res3, _ := cs.MarshalBinary()
   fmt.Printf("\nCiphertext: %x\n", res3)
   dbytes, _, _ := dk.VerifiableDecryptWithDomain(domain, cs)
   fmt.Printf("\nDecrypted: %s\n", dbytes)

   fmt.Printf("\n=== Checking proof===\n")
   rtn := ek.VerifyDomainEncryptProof(domain, cs, proof)
   if rtn == nil {
   	fmt.Printf("Encryption has been verified\n")
   } else {
   	fmt.Printf("Encryption has NOT been verified\n")
   }

   fmt.Printf("=== Now we will try with the wrong proof ===\n")
   ek2, _, _ := elgamal.NewKeys(bls12381g1)
   cs, proof2, _ := ek2.VerifiableEncrypt(msgBytes, &elgamal.EncryptParams{
   	Domain:          domain,
   	MessageIsHashed: true,
   	GenProof:        true,
   	ProofNonce:      domain,
   })

   rtn = ek.VerifyDomainEncryptProof(domain, cs, proof2)
   if rtn == nil {
   	fmt.Printf("Encryption has been verified\n")
   } else {
   	fmt.Printf("Encryption has NOT been verified\n")
   }

}

Documentation
BSI TR-03111 ECKA-EG (Elliptic Curve Key Agreement based on ElGamal)

License

This project is licensed under the ISC License.

Directories

Path Synopsis
curves
This implementation IS NOT constant time as it leverages math/big for big number operations.
This implementation IS NOT constant time as it leverages math/big for big number operations.
curves/native/pasta/fp
Autogenerated: './src/ExtractionOCaml/word_by_word_montgomery' --lang Go pasta_fp 64 '2^254 + 45560315531419706090280762371685220353'
Autogenerated: './src/ExtractionOCaml/word_by_word_montgomery' --lang Go pasta_fp 64 '2^254 + 45560315531419706090280762371685220353'
curves/native/pasta/fq
Autogenerated: './src/ExtractionOCaml/word_by_word_montgomery' --lang Go pasta_fq 64 '2^254 + 45560315531506369815346746415080538113'
Autogenerated: './src/ExtractionOCaml/word_by_word_montgomery' --lang Go pasta_fq 64 '2^254 + 45560315531506369815346746415080538113'

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL