John starr rocks!
This commit is contained in:
1 parent
d2cd50b2e3
commit
0095eb7159
12 files changed
+343
-9
No files matched your search
@@ -0,0 +1,59 @@
|
|||||||
|
package asymetric
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "crypto/sha256"
|
||||||
|
_ "crypto/sha512"
|
||||||
|
|
||||||
|
"crypto"
|
||||||
|
"crypto/rsa"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RsaOaepPss struct {
|
||||||
|
PrivateKey *rsa.PrivateKey
|
||||||
|
PublicKey *rsa.PublicKey
|
||||||
|
Hash crypto.Hash
|
||||||
|
|
||||||
|
Random io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RsaOaepPss) getHash() (crypto.Hash, error) {
|
||||||
|
if !this.Hash.Available() {
|
||||||
|
return 0, errors.New(fmt.Sprintf("hash function %v is unabailable", this.Hash))
|
||||||
|
} else {
|
||||||
|
return this.Hash, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RsaOaepPss) Encrypt(data []byte) ([]byte, error) {
|
||||||
|
label := make([]byte, 0)
|
||||||
|
if hash, err := this.getHash(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return rsa.EncryptOAEP(hash.New(), this.Random, this.PublicKey, data, label)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RsaOaepPss) Decrypt(ciphertext []byte) ([]byte, error) {
|
||||||
|
label := make([]byte, 0)
|
||||||
|
if hash, err := this.getHash(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return rsa.DecryptOAEP(hash.New(), this.Random, this.PrivateKey, ciphertext, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RsaOaepPss) Sign(hashedData []byte) ([]byte, error) {
|
||||||
|
ret, err := rsa.SignPSS(this.Random, this.PrivateKey, this.Hash, hashedData, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(">>> ", len(hashedData))
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RsaOaepPss) VerifySignature(hashedData []byte, signature []byte) error {
|
||||||
|
return rsa.VerifyPSS(this.PublicKey, this.Hash, hashedData, signature, nil)
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package asymetric
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "crypto/sha512"
|
||||||
|
|
||||||
|
"crypto"
|
||||||
|
"crypto/rsa"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/didiercrunch/filou/helper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var random = helper.NewMockRandomReader()
|
||||||
|
|
||||||
|
func generateKeyPair() (*rsa.PrivateKey, *rsa.PublicKey) {
|
||||||
|
if key, err := rsa.GenerateKey(random, 1024); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return key, &key.PublicKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncrypt(t *testing.T) {
|
||||||
|
bobPrivKey, bobPubKey := generateKeyPair()
|
||||||
|
|
||||||
|
r := &RsaOaepPss{nil, bobPubKey, crypto.SHA384, random}
|
||||||
|
|
||||||
|
ciphertext, err := r.Encrypt([]byte("this is a secret message"))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
orgTest, err := rsa.DecryptOAEP(crypto.SHA384.New(), random, bobPrivKey, ciphertext, []byte{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if string(orgTest) != "this is a secret message" {
|
||||||
|
t.Error("the decryption of the message does not fit the original message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncryptDecrypt(t *testing.T) {
|
||||||
|
bobPrivKey, bobPubKey := generateKeyPair()
|
||||||
|
|
||||||
|
message := "this is a secret message"
|
||||||
|
|
||||||
|
rAlice := &RsaOaepPss{nil, bobPubKey, crypto.SHA384, random}
|
||||||
|
rBob := &RsaOaepPss{bobPrivKey, nil, crypto.SHA384, random}
|
||||||
|
|
||||||
|
if ciphertext, err := rAlice.Encrypt([]byte(message)); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if decryptedText, err := rBob.Decrypt(ciphertext); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else if string(decryptedText) != message {
|
||||||
|
t.Error("the decryption of the message does not fit the original message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSign(t *testing.T) {
|
||||||
|
alicePrivKey, alicePubKey := generateKeyPair()
|
||||||
|
h := crypto.SHA384.New()
|
||||||
|
h.Write([]byte("this is a secret message"))
|
||||||
|
hashedMessage := h.Sum(nil)
|
||||||
|
|
||||||
|
rAlice := &RsaOaepPss{alicePrivKey, nil, crypto.SHA384, random}
|
||||||
|
signature, err := rAlice.Sign(hashedMessage)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := rsa.VerifyPSS(alicePubKey, crypto.SHA384, hashedMessage, signature, nil); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignAndVerify(t *testing.T) {
|
||||||
|
alicePrivKey, alicePubKey := generateKeyPair()
|
||||||
|
h := crypto.SHA384.New()
|
||||||
|
h.Write([]byte("this is a secret message"))
|
||||||
|
hashedMessage := h.Sum(nil)
|
||||||
|
|
||||||
|
rAlice := &RsaOaepPss{alicePrivKey, nil, crypto.SHA384, random}
|
||||||
|
rBob := &RsaOaepPss{nil, alicePubKey, crypto.SHA384, random}
|
||||||
|
if signature, err := rAlice.Sign(hashedMessage); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else if err := rBob.VerifySignature(hashedMessage, signature); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAvailableHashes(t *testing.T) {
|
||||||
|
hashes := map[crypto.Hash]bool{crypto.SHA224: true, crypto.SHA256: true, crypto.SHA384: true, crypto.SHA512: true}
|
||||||
|
var i crypto.Hash
|
||||||
|
for i = 0; i < 22; i++ {
|
||||||
|
r := &RsaOaepPss{Hash: i}
|
||||||
|
if _, err := r.getHash(); err != nil && hashes[i] {
|
||||||
|
t.Error("should support", i, "hash type but does not")
|
||||||
|
} else if err == nil && !hashes[i] {
|
||||||
|
t.Error("should not support", i, "hash type but does")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/didiercrunch/filou/keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PrivateContract struct {
|
||||||
|
PublicContract
|
||||||
|
RSAPrivateKey []*keys.RSAPrivateKey `yaml:"rsa_private_key,omitempty" json:"rsa_private_key,omitempty"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/didiercrunch/filou/keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PublicContract struct {
|
||||||
|
AcceptedHashes []string `yaml:"accepted_hashes" json:"accepted_hashes"`
|
||||||
|
AcceptedBlockCypher []string `yaml:"accepted_block_cypher" json:"accepted_block_cypher"`
|
||||||
|
RSAPublicKey []*keys.RSAPublicKey `yaml:"rsa_public_key, omitempty" json:"rsa_public_key,omitempty"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/didiercrunch/filou/helper"
|
||||||
|
"github.com/didiercrunch/filou/keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertJSONMarshalling(c *PublicContract) error {
|
||||||
|
ret := new(PublicContract)
|
||||||
|
if data, err := json.Marshal(c); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err = json.Unmarshal(data, ret); err != nil {
|
||||||
|
return err
|
||||||
|
} else if !reflect.DeepEqual(ret, c) {
|
||||||
|
fmt.Println(string(data))
|
||||||
|
return errors.New("bad serisalization")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectJson(c *PublicContract, jsonData string) error {
|
||||||
|
ret := new(PublicContract)
|
||||||
|
if err := json.Unmarshal([]byte(jsonData), ret); err != nil {
|
||||||
|
return err
|
||||||
|
} else if !reflect.DeepEqual(ret.RSAPublicKey, c.RSAPublicKey) {
|
||||||
|
return errors.New("bad serisalization")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleJsonification(t *testing.T) {
|
||||||
|
c := &PublicContract{
|
||||||
|
AcceptedHashes: []string{"sha246"},
|
||||||
|
AcceptedBlockCypher: []string{"aes"},
|
||||||
|
RSAPublicKey: []*keys.RSAPublicKey{&keys.RSAPublicKey{helper.B(12), 3}},
|
||||||
|
}
|
||||||
|
if err := assertJSONMarshalling(c); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyRSAPublicKey(t *testing.T) {
|
||||||
|
c := &PublicContract{
|
||||||
|
AcceptedHashes: []string{"sha246"},
|
||||||
|
AcceptedBlockCypher: []string{"aes"},
|
||||||
|
RSAPublicKey: []*keys.RSAPublicKey{&keys.RSAPublicKey{helper.B(12), 3}},
|
||||||
|
}
|
||||||
|
jsonData := `{
|
||||||
|
"accepted_hashes": ["sha246"],
|
||||||
|
"accepted_block_cypher": ["aes"],
|
||||||
|
"rsa_public_key": [{"n": "c", "e": 3}]
|
||||||
|
}`
|
||||||
|
if err := expectJson(c, jsonData); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,46 @@
|
|||||||
|
|
||||||
|
### public contract
|
||||||
|
|
||||||
|
A public contract is the information a user publish to allow anybody to send
|
||||||
|
him encrypted files. Of course the public contract contains the user
|
||||||
|
public key but it contains much more.
|
||||||
|
|
||||||
|
The contract itself does not need to be sign. The signature is level of
|
||||||
|
complexity above the public contract
|
||||||
|
|
||||||
|
|
||||||
|
~~~
|
||||||
|
---
|
||||||
|
# example of a contract
|
||||||
|
|
||||||
|
name: john dear
|
||||||
|
|
||||||
|
organizarion: JohnDeer corporation
|
||||||
|
|
||||||
|
email: johndear@johndeer.co
|
||||||
|
|
||||||
|
url: "the url where to fiofbnd an exact copy of the contract"
|
||||||
|
|
||||||
|
root_url: "the url where to find the most up to date version of the contract"
|
||||||
|
|
||||||
|
accepted_hashs:
|
||||||
|
- sha512
|
||||||
|
|
||||||
|
accepted_block_cypher:
|
||||||
|
- aes
|
||||||
|
|
||||||
|
accepted_modes:
|
||||||
|
- ofb
|
||||||
|
|
||||||
|
signatures_required: yes
|
||||||
|
|
||||||
|
rsa_public_keys:
|
||||||
|
-
|
||||||
|
n: "hexadecimal n"
|
||||||
|
e: 3424
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
### public key
|
### public key
|
||||||
Note that any private key are a public key.
|
Note that any private key are a public key.
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -105,7 +105,12 @@ func (this *Enveloper) WriteEncryptedKey(z *zip.Writer) error {
|
|||||||
func (this *Enveloper) WriteToWriter(w io.Writer) error {
|
func (this *Enveloper) WriteToWriter(w io.Writer) error {
|
||||||
z := zip.NewWriter(w)
|
z := zip.NewWriter(w)
|
||||||
defer z.Close()
|
defer z.Close()
|
||||||
if err := this.WritePayload(z); err != nil {
|
errc := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errc <- this.WritePayload(z)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := <-errc; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := this.CreateEnvelopCompletely(); err != nil {
|
if err := this.CreateEnvelopCompletely(); err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnvelop(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,8 +3,11 @@ package integration
|
|||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/rsa"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/didiercrunch/filou/asymetric"
|
||||||
"github.com/didiercrunch/filou/envelop"
|
"github.com/didiercrunch/filou/envelop"
|
||||||
"github.com/didiercrunch/filou/helper"
|
"github.com/didiercrunch/filou/helper"
|
||||||
"github.com/didiercrunch/filou/payload"
|
"github.com/didiercrunch/filou/payload"
|
||||||
@@ -23,6 +26,22 @@ func (this *mockEncryptor) Encrypt(data []byte) ([]byte, error) {
|
|||||||
|
|
||||||
type mockSigner struct{}
|
type mockSigner struct{}
|
||||||
|
|
||||||
|
var random = helper.NewMockRandomReader()
|
||||||
|
|
||||||
|
func generateRSAKeyPair() (*rsa.PrivateKey, *rsa.PublicKey) {
|
||||||
|
if key, err := rsa.GenerateKey(random, 2048); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return key, &key.PublicKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEncryterAndSigner() *asymetric.RsaOaepPss {
|
||||||
|
alicePrivateKey, _ := generateRSAKeyPair()
|
||||||
|
_, bobPubKey := generateRSAKeyPair()
|
||||||
|
return &asymetric.RsaOaepPss{alicePrivateKey, bobPubKey, crypto.SHA512, random}
|
||||||
|
}
|
||||||
|
|
||||||
func (this *mockSigner) Sign(data []byte) ([]byte, error) {
|
func (this *mockSigner) Sign(data []byte) ([]byte, error) {
|
||||||
// a slice with the sum of the data plus a "secret" value
|
// a slice with the sum of the data plus a "secret" value
|
||||||
var sum byte = 36
|
var sum byte = 36
|
||||||
@@ -33,11 +52,13 @@ func (this *mockSigner) Sign(data []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPayloadCanBeUseInEnvelop(t *testing.T) {
|
func TestPayloadCanBeUseInEnvelop(t *testing.T) {
|
||||||
|
encryterAndSigner := getEncryterAndSigner()
|
||||||
payload_ := payload.GetDefaultPayload(bytes.NewBufferString("some data to encrypt"))
|
payload_ := payload.GetDefaultPayload(bytes.NewBufferString("some data to encrypt"))
|
||||||
envelop := envelop.NewEnveloper(&mockEncryptor{}, payload_, &mockSigner{})
|
envelop := envelop.NewEnveloper(encryterAndSigner, payload_, encryterAndSigner)
|
||||||
w := helper.NewMockIoWriter()
|
w := helper.NewMockIoWriter()
|
||||||
if err := envelop.WriteToWriter(w); err != nil {
|
if err := envelop.WriteToWriter(w); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
r, err := zip.NewReader(w.ReaderAt(), int64(w.Length()))
|
r, err := zip.NewReader(w.ReaderAt(), int64(w.Length()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+5
-5
@@ -10,11 +10,11 @@ import (
|
|||||||
// All the method to encode/decode keys to json, yaml...
|
// All the method to encode/decode keys to json, yaml...
|
||||||
|
|
||||||
type encodingRSAKey struct {
|
type encodingRSAKey struct {
|
||||||
N string
|
N string `json:"n,omitempty"`
|
||||||
P string
|
P string `json:"p,omitempty"`
|
||||||
Q string
|
Q string `json:"q,omitempty"`
|
||||||
D string
|
D string `json:"d,omitempty"`
|
||||||
E int
|
E int `json:"e,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *encodingRSAKey) CreateFromRSAPrivateKey(key *RSAPrivateKey) *encodingRSAKey {
|
func (this *encodingRSAKey) CreateFromRSAPrivateKey(key *RSAPrivateKey) *encodingRSAKey {
|
||||||
|
|||||||
@@ -41,3 +41,15 @@ func TestRSAPublicKeyJsonification(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRSAPublicKeyJsonificationFromString(t *testing.T) {
|
||||||
|
data := []byte(`{"N":"3ff","E":89}`)
|
||||||
|
key := new(RSAPublicKey)
|
||||||
|
if err := json.Unmarshal(data, key); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(key, &RSAPublicKey{B(1023), 89}) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -137,7 +137,6 @@ func (this *Payload) computeHash(reader io.Reader) (io.Reader, error) {
|
|||||||
}(readerHash)
|
}(readerHash)
|
||||||
|
|
||||||
return read, nil
|
return read, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Payload) encrypt(reader io.Reader, stream cipher.Stream) (io.Reader, error) {
|
func (this *Payload) encrypt(reader io.Reader, stream cipher.Stream) (io.Reader, error) {
|
||||||
@@ -148,5 +147,4 @@ func (this *Payload) encrypt(reader io.Reader, stream cipher.Stream) (io.Reader,
|
|||||||
cipherWriter.Close()
|
cipherWriter.Close()
|
||||||
}(stream)
|
}(stream)
|
||||||
return this.computeHash(ret)
|
return this.computeHash(ret)
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user