Commit 32c12074 authored by Viktor Trón's avatar Viktor Trón Committed by GitHub

simple El-Gamal encryption for trojan chunks (#728)

* encryption: add elgamal package to support pss encryption

* encryption: add Key accessor to interfaces

* encryption,elgamal:renaming and comments

* typo
parent ed2d6085
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package elgamal
import (
"crypto/ecdsa"
"hash"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/encryption"
)
// New constructs an encryption interface (the modified blockcipher) with a base key derived from
// a shared secret (using a private key and the counterparty's public key) hashed with a salt
func New(key *ecdsa.PrivateKey, pub *ecdsa.PublicKey, salt []byte, padding int, hashfunc func() hash.Hash) (encryption.Interface, error) {
dh := crypto.NewDH(key)
sk, err := dh.SharedKey(pub, salt)
if err != nil {
return nil, err
}
return encryption.New(sk, padding, 0, hashfunc), nil
}
// NewEncrypter constructs an El-Gamal encryptor
// this involves generating an ephemeral key pair the public part of which is returned
// as it is needed for the counterparty to decrypt
func NewEncrypter(pub *ecdsa.PublicKey, salt []byte, padding int, hashfunc func() hash.Hash) (encryption.Encrypter, *ecdsa.PublicKey, error) {
privKey, err := crypto.GenerateSecp256k1Key()
if err != nil {
return nil, nil, err
}
enc, err := New(privKey, pub, salt, padding, hashfunc)
if err != nil {
return nil, nil, err
}
return enc, &privKey.PublicKey, nil
}
// NewDecrypter constructs an el-Gamal decrypter the receiving party uses
// the public key must be the ephemeral return value of the Encrypter constructor
func NewDecrypter(key *ecdsa.PrivateKey, pub *ecdsa.PublicKey, salt []byte, hashfunc func() hash.Hash) (encryption.Decrypter, error) {
return New(key, pub, salt, 0, hashfunc)
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package elgamal_test
import (
"bytes"
"crypto/rand"
"io"
"testing"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/encryption/elgamal"
"github.com/ethersphere/bee/pkg/swarm"
)
func TestElgamalCorrect(t *testing.T) {
plaintext := []byte("some highly confidential text")
key, err := crypto.GenerateSecp256k1Key()
if err != nil {
t.Fatal(err)
}
pub := &key.PublicKey
salt := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
t.Fatal(err)
}
padding := 4032
enc, ephpub, err := elgamal.NewEncrypter(pub, salt, padding, swarm.NewHasher)
if err != nil {
t.Fatal(err)
}
ciphertext, err := enc.Encrypt(plaintext)
if err != nil {
t.Fatal(err)
}
if len(ciphertext) != padding {
t.Fatalf("ciphertext has incorrect length: expected %v, got %v", padding, len(ciphertext))
}
dec, err := elgamal.NewDecrypter(key, ephpub, salt, swarm.NewHasher)
if err != nil {
t.Fatal(err)
}
expected := plaintext
decryptedtext, err := dec.Decrypt(ciphertext)
if err != nil {
t.Fatal(err)
}
if len(decryptedtext) != padding {
t.Fatalf("decrypted text has incorrect length: expected %v, got %v", padding, len(decryptedtext))
}
plaintext = decryptedtext[:len(expected)]
if !bytes.Equal(plaintext, expected) {
t.Fatalf("original and encrypted-decrypted plaintexts do no match: expected %x, got %x", expected, plaintext)
}
}
......@@ -30,17 +30,19 @@ const (
type Key []byte
type Encryptor interface {
type Encrypter interface {
Key() Key
Encrypt(data []byte) ([]byte, error)
}
type Decryptor interface {
type Decrypter interface {
Key() Key
Decrypt(data []byte) ([]byte, error)
}
type Interface interface {
Encryptor
Decryptor
Encrypter
Decrypter
Reset()
}
......@@ -53,7 +55,7 @@ type Encryption struct {
hashFunc func() hash.Hash // hasher constructor function
}
// New constructs a new encryptor/decryptor
// New constructs a new encrypter/decrypter
func New(key Key, padding int, initCtr uint32, hashFunc func() hash.Hash) Interface {
return &Encryption{
key: key,
......@@ -64,6 +66,11 @@ func New(key Key, padding int, initCtr uint32, hashFunc func() hash.Hash) Interf
}
}
// Key returns the base key
func (e *Encryption) Key() Key {
return e.key
}
// Encrypt encrypts the data and does padding if specified
func (e *Encryption) Encrypt(data []byte) ([]byte, error) {
length := len(data)
......
......@@ -24,6 +24,7 @@ type Encryptor struct {
encryptFunc func(data []byte) ([]byte, error)
decryptFunc func(data []byte) ([]byte, error)
resetFunc func()
keyFunc func() encryption.Key
}
// New returns a new Encryptor configured with provided options.
......@@ -35,6 +36,14 @@ func New(opts ...Option) *Encryptor {
return e
}
// Key has only bogus
func (e *Encryptor) Key() encryption.Key {
if e.keyFunc == nil {
return nil
}
return e.keyFunc()
}
// Encrypt calls the configured encrypt function, or returns ErrNotImplemented
// if it is not set.
func (e *Encryptor) Encrypt(data []byte) ([]byte, error) {
......@@ -85,6 +94,13 @@ func WithResetFunc(f func()) Option {
}
}
// WithKeyFunc sets the Encryptor Key function.
func WithKeyFunc(f func() encryption.Key) Option {
return func(e *Encryptor) {
e.keyFunc = f
}
}
// WithXOREncryption sets Encryptor Encrypt and Decrypt functions with XOR
// encryption function that uses the provided key for encryption.
func WithXOREncryption(key []byte) Option {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment