https://github.com/pedroalbanese/ecka-eg
ECKA-EG Key Agreement Function
https://github.com/pedroalbanese/ecka-eg
ecies elgamal elgamal-cryptosystem elgamal-encryption
Last synced: about 2 months ago
JSON representation
ECKA-EG Key Agreement Function
- Host: GitHub
- URL: https://github.com/pedroalbanese/ecka-eg
- Owner: pedroalbanese
- License: isc
- Created: 2024-04-06T18:57:34.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-10-04T19:05:45.000Z (about 1 year ago)
- Last Synced: 2025-10-11T13:44:24.641Z (about 2 months ago)
- Topics: ecies, elgamal, elgamal-cryptosystem, elgamal-encryption
- Language: Go
- Homepage: http://albanese.atwebpages.com/ec-elgamal.php
- Size: 507 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# ecka-eg
[](https://github.com/pedroalbanese/ecka-eg/blob/master/LICENSE.md)
[](http://godoc.org/github.com/pedroalbanese/ecka-eg)
[](https://goreportcard.com/report/github.com/pedroalbanese/ecka-eg)
### 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  and a public key of:

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

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

and where  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  is the  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 () and then perform symmetric key encryption on the message:

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




Here is an overview of the method:
To generate the proof, we generate a random value () and a blinding factor () to give two points on the elliptic curve:


Next, we create the challenge bytes with:

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

We then create two Schnorr proof values:


To verify the proof, we reconstruct :

We reconstruct :

This works because:

We then reconstruct the challenge with:

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

This value is then checked against the challenge in the proof, and if they are the same, the proof is verified.
### Usage
```go
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)](https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03111/BSI-TR-03111_V-2-1_pdf.pdf?__blob=publicationFile&v=1)
## License
This project is licensed under the ISC License.
#### Copyright (c) 2020-2024 Pedro F. Albanese - ALBANESE Research Lab.