Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/arnaucube/cryptofun

Crypto algorithms from scratch in Go. Learning purposes only. ECC, BN128 pairing, Paillier, RSA, Homomorphic computation, ElGamal, Schnorr, ECDSA, BLS, ...
https://github.com/arnaucube/cryptofun

Last synced: about 10 hours ago
JSON representation

Crypto algorithms from scratch in Go. Learning purposes only. ECC, BN128 pairing, Paillier, RSA, Homomorphic computation, ElGamal, Schnorr, ECDSA, BLS, ...

Awesome Lists containing this project

README

        

# cryptofun [![Go Report Card](https://goreportcard.com/badge/github.com/arnaucube/cryptofun)](https://goreportcard.com/report/github.com/arnaucube/cryptofun) [![Build Status](https://travis-ci.org/arnaucube/cryptofun.svg?branch=master)](https://travis-ci.org/arnaucube/cryptofun)

Crypto algorithms from scratch. Academic purposes only.

- [RSA cryptosystem & Blind signature & Homomorphic Multiplication](#rsa-cryptosystem--blind-signature--homomorphic-multiplication)
- [Paillier cryptosystem & Homomorphic Addition](#paillier-cryptosystem--homomorphic-addition)
- [Shamir Secret Sharing](#shamir-secret-sharing)
- [Diffie-Hellman](#diffie-hellman)
- [ECC](#ecc)
- [ECC ElGamal](#ecc-elgamal)
- [ECC ECDSA](#ecc-ecdsa)
- [Schnorr signature](#schnorr-signature)
- [Bn128 pairing](#bn128)
- [BLS signature](#bls)

---

## RSA cryptosystem & Blind signature & Homomorphic Multiplication
- https://en.wikipedia.org/wiki/RSA_(cryptosystem)#
- https://en.wikipedia.org/wiki/Blind_signature
- https://en.wikipedia.org/wiki/Homomorphic_encryption

- [x] GenerateKeyPair
- [x] Encrypt
- [x] Decrypt
- [x] Blind
- [x] Blind Signature
- [x] Unblind Signature
- [x] Verify Signature
- [x] Homomorphic Multiplication

#### Usage
- Key generation, Encryption, Decryption
```go
// generate key pair
key, err := GenerateKeyPair()
if err!=nil {
fmt.Println(err)
}
mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes)

// encrypt message
c := Encrypt(m, key.PubK)

// decrypt ciphertext
d := Decrypt(c, key.PrivK)
if m == d {
fmt.Println("correctly decrypted")
}
```

- Blind signatures
```go
// key generation [Alice]
key, err := GenerateKeyPair()
if err!=nil {
fmt.Println(err)
}

// create new message [Alice]
mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes)

// define r value [Alice]
rVal := big.NewInt(int64(101))

// blind message [Alice]
mBlinded := Blind(m, rVal, key.PubK)

// Blind Sign the blinded message [Bob]
sigma := BlindSign(mBlinded, key.PrivK)

// unblind the blinded signed message, and get the signature of the message [Alice]
mSigned := Unblind(sigma, rVal, key.PubK)

// verify the signature [Alice/Bob/Trudy]
verified := Verify(m, mSigned, key.PubK)
if !verified {
fmt.Println("signature could not be verified")
}
```

- Homomorphic Multiplication
```go
// key generation [Alice]
key, err := GenerateKeyPair()
if err!=nil {
fmt.Println(err)
}

// define values [Alice]
n1 := big.NewInt(int64(11))
n2 := big.NewInt(int64(15))

// encrypt the values [Alice]
c1 := Encrypt(n1, key.PubK)
c2 := Encrypt(n2, key.PubK)

// compute homomorphic multiplication with the encrypted values [Bob]
c3c4 := HomomorphicMul(c1, c2, key.PubK)

// decrypt the result [Alice]
d := Decrypt(c3c4, key.PrivK)

// check that the result is the expected
if !bytes.Equal(new(big.Int).Mul(n1, n2).Bytes(), d.Bytes()) {
fmt.Println("decrypted result not equal to expected result")
}
```

## Paillier cryptosystem & Homomorphic Addition
- https://en.wikipedia.org/wiki/Paillier_cryptosystem
- https://en.wikipedia.org/wiki/Homomorphic_encryption

- [x] GenerateKeyPair
- [x] Encrypt
- [x] Decrypt
- [x] Homomorphic Addition

#### Usage
- Encrypt, Decrypt
```go
// key generation
key, err := GenerateKeyPair()
if err!=nil {
fmt.Println(err)
}

mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes)

// encryption
c := Encrypt(m, key.PubK)

// decryption
d := Decrypt(c, key.PubK, key.PrivK)
if m == d {
fmt.Println("ciphertext decrypted correctly")
}
```

- Homomorphic Addition
```go
// key generation [Alice]
key, err := GenerateKeyPair()
if err!=nil {
fmt.Println(err)
}

// define values [Alice]
n1 := big.NewInt(int64(110))
n2 := big.NewInt(int64(150))

// encrypt values [Alice]
c1 := Encrypt(n1, key.PubK)
c2 := Encrypt(n2, key.PubK)

// compute homomorphic addition [Bob]
c3c4 := HomomorphicAddition(c1, c2, key.PubK)

// decrypt the result [Alice]
d := Decrypt(c3c4, key.PubK, key.PrivK)
if !bytes.Equal(new(big.Int).Add(n1, n2).Bytes(), d.Bytes()) {
fmt.Println("decrypted result not equal to expected result")
}
```

## Shamir Secret Sharing
- https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing

- [x] create secret sharing from number of secrets needed, number of shares, random point p, secret to share
- [x] Lagrange Interpolation to restore the secret from the shares

#### Usage
```go
// define secret to share
k := 123456789

// define random prime
p, err := rand.Prime(rand.Reader, bits/2)
if err!=nil {
fmt.Println(err)
}

// define how many shares want to generate
nShares := big.NewInt(int64(6))

// define how many shares are needed to recover the secret
nNeededShares := big.NewInt(int64(3))

// create the shares
shares, err := Create(
nNeededShares,
nShares,
p,
big.NewInt(int64(k)))
assert.Nil(t, err)
if err!=nil {
fmt.Println(err)
}

// select shares to use
var sharesToUse [][]*big.Int
sharesToUse = append(sharesToUse, shares[2])
sharesToUse = append(sharesToUse, shares[1])
sharesToUse = append(sharesToUse, shares[0])

// recover the secret using Lagrange Interpolation
secr := LagrangeInterpolation(sharesToUse, p)

// check that the restored secret matches the original secret
if !bytes.Equal(k.Bytes(), secr.Bytes()) {
fmt.Println("reconstructed secret not correspond to original secret")
}
```

## Diffie-Hellman
- https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange

- [x] key exchange

## ECC
- https://en.wikipedia.org/wiki/Elliptic-curve_cryptography

- [x] define elliptic curve
- [x] get point at X
- [x] get order of a Point on the elliptic curve
- [x] Add two points on the elliptic curve
- [x] Multiply a point n times on the elliptic curve

#### Usage
- ECC basic operations
```go
// define new ec
ec := NewEC(big.NewInt(int64(0)), big.NewInt(int64(7)), big.NewInt(int64(11)))

// define two points over the curve
p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(7))}
p2 := Point{big.NewInt(int64(2)), big.NewInt(int64(2))}

// add the two points
q, err := ec.Add(p1, p2)
if err!=nil {
fmt.Println(err)
}

// multiply the two points
q, err := ec.Mul(p, big.NewInt(int64(1)))
if err!=nil {
fmt.Println(err)
}

// get order of a generator point over the elliptic curve
g := Point{big.NewInt(int64(7)), big.NewInt(int64(8))}
order, err := ec.Order(g)
if err!=nil {
fmt.Println(err)
}
```

## ECC ElGamal
- https://en.wikipedia.org/wiki/ElGamal_encryption

- [x] ECC ElGamal key generation
- [x] ECC ElGamal Encrypton
- [x] ECC ElGamal Decryption

#### Usage
- NewEG, Encryption, Decryption
```go
// define new elliptic curve
ec := ecc.NewEC(big.NewInt(int64(1)), big.NewInt(int64(18)), big.NewInt(int64(19)))

// define new point
g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))}

// define new ElGamal crypto system with the elliptic curve and the point
eg, err := NewEG(ec, g)
if err!=nil {
fmt.Println(err)
}

// define privK&pubK over the elliptic curve
privK := big.NewInt(int64(5))
pubK, err := eg.PubK(privK)
if err!=nil {
fmt.Println(err)
}

// define point to encrypt
m := ecc.Point{big.NewInt(int64(11)), big.NewInt(int64(12))}

// encrypt
c, err := eg.Encrypt(m, pubK, big.NewInt(int64(15)))
if err!=nil {
fmt.Println(err)
}

// decrypt
d, err := eg.Decrypt(c, privK)
if err!=nil {
fmt.Println(err)
}

// check that decryption is correct
if !m.Equal(d) {
fmt.Println("decrypted not equal to original")
}
```

## ECC ECDSA
- https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm

- [x] define ECDSA data structure
- [x] ECDSA Sign
- [x] ECDSA Verify signature

#### Usage
```go
// define new elliptic curve
ec := ecc.NewEC(big.NewInt(int64(1)), big.NewInt(int64(18)), big.NewInt(int64(19)))
// define new point
g := ecc.Point{big.NewInt(int64(7)), big.NewInt(int64(11))}

// define new ECDSA system
dsa, err := NewDSA(ec, g)
if err!=nil {
fmt.Println(err)
}

// define privK&pubK over the elliptic curve
privK := big.NewInt(int64(5))
pubK, err := dsa.PubK(privK)
if err!=nil {
fmt.Println(err)
}

// hash value to sign
hashval := big.NewInt(int64(40))

// define r
r := big.NewInt(int64(11))

// sign hashed value
sig, err := dsa.Sign(hashval, privK, r)
if err!=nil {
fmt.Println(err)
}

// verify signature
verified, err := dsa.Verify(hashval, sig, pubK)
if err!=nil {
fmt.Println(err)
}
if verified {
fmt.Println("signature correctly verified")
}
```

## Schnorr signature
- https://en.wikipedia.org/wiki/Schnorr_signature

- [x] Hash[M || R] (where M is the msg bytes and R is a Point on the ECC, using sha256 hash function)
- [x] Generate Schnorr scheme
- [x] Sign
- [x] Verify signature

#### Usage
```go
// define new elliptic curve
ec := ecc.NewEC(big.NewInt(int64(0)), big.NewInt(int64(7)), big.NewInt(int64(11)))
// define new point
g := ecc.Point{big.NewInt(int64(11)), big.NewInt(int64(27))} // Generator
// define new random r
r := big.NewInt(int64(23)) // random r

// define new Schnorr crypto system using the values
schnorr, sk, err := Gen(ec, g, r)
if err!=nil {
fmt.println(err)
}

// define message to sign
m := []byte("hola")

// also we can hash the message, but it's not mandatory, as it will be done inside the schnorr.Sign, but we can perform it now, just to check the function
h := Hash([]byte("hola"), c)
if h.String() != "34719153732582497359642109898768696927847420320548121616059449972754491425079") {
fmt.Println("not correctly hashed")
}

s, rPoint, err := schnorr.Sign(sk, m)
if err!=nil {
fmt.println(err)
}

// verify Schnorr signature
verified, err := Verify(schnorr.EC, sk.PubK, m, s, rPoint)
if err!=nil {
fmt.println(err)
}
if verified {
fmt.Println("Schnorr signature correctly verified")
}
```

## Bn128
Implementation of the bn128 pairing.
Code moved to https://github.com/arnaucube/go-snark/tree/master/bn128

## BLS
Boneh–Lynn–Shacham (BLS) signature scheme implemented in Go.
https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham

This package uses the BN128 Go implementation from https://github.com/arnaucube/go-snark/tree/master/bn128

### Usage
```go
bls, err := NewKeys()
assert.Nil(t, err)

fmt.Println("privK:", bls.PrivK)
fmt.Println("pubK:", bls.PubK)

m := []byte("test")
sig := bls.Sign(m)
fmt.Println("signature:", sig)

verified := bls.Verify(m, sig, bls.PubK)
assert.True(t, verified)

/* out:
privK: 28151522174243194157727175362620544050084772361374505986857263387912025505082855947281432752362814690196305655335201716186584298643231993241609823412370437094839017595372164876997343464950463323765646363122343203470911131219733598647659483557447955173651057370197665461325593653581904430885385707255151472097067657072671643359241937143381958053903725229458882818033464163487351806079175441316235756460455300637131488613568714712448336232283394011955460567718918055245116200622473324300828876609569556897836255866438665750954410544846238847540023603735360532628141508114304504053826700874403280496870140784630677100277
pubK: [528167154220154970470523315181365784447502116458960328551053767278433374201 18282159022449399855128689249640771309991127595389457870089153259100566421596 19728585501269572907574045312283749798205079570296187960832716959652451330253]
signature: [[12832528436266902887734423636380781315321578271441494003771296275495461508593 6964131770814642748778827029569297554111206304527781019989920684169107205085] [6508357389516441729339280841134358160957092583050390612877406497974519092306 12073245715182483402311045895787625736998570529454024932833669602347318770866] [13520730275909614846121720877644124261162513989808465368770765804305866618385 19571107788574492009101590535904131414163790958090376021518899789800327786039]]
verified: true
*/
```

---

To run all tests:
```
go test ./... -v
```