diff --git a/asymetric/rsa.go b/asymetric/rsa.go index c445fb5..3e40ae0 100644 --- a/asymetric/rsa.go +++ b/asymetric/rsa.go @@ -48,9 +48,6 @@ func (this *RsaOaepPss) Decrypt(ciphertext []byte) ([]byte, error) { 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 } diff --git a/contract/best_contract.go b/contract/best_contract.go new file mode 100644 index 0000000..ebe8bc0 --- /dev/null +++ b/contract/best_contract.go @@ -0,0 +1,79 @@ +package contract + +import ( + "errors" + "strings" +) + +type AcceptedContract struct { + Hash string + BlockCipher string + BlockCipherMode string + AsymetricCryptography string +} + +func listContains(lst []string, elm string) bool { + for _, elm_ := range lst { + if elm == elm_ { + return true + } + } + return false +} + +func joinAsError(msg []string) error { + if len(msg) > 0 { + return errors.New(strings.Join(msg, "\n")) + } + return nil +} + +func getFirstItemInList1ThatIsAlsoInList2(lst1, lst2 []string) (string, error) { + for _, elm := range lst1 { + if listContains(lst2, elm) { + return elm, nil + } + } + return "", errors.New("no items in list1 is in list2") +} + +func getBestBlockCipher(prvCtr *PrivateContract, pubCtr *PublicContract) (string, error) { + if b, err := getFirstItemInList1ThatIsAlsoInList2(pubCtr.AcceptedBlockCyphers, prvCtr.AcceptedBlockCyphers); err != nil { + return "", errors.New("cannot find a block cypher that satisfy both contracts") + } else { + return b, nil + } +} + +func getBestBlockCipherMode(prvCtr *PrivateContract, pubCtr *PublicContract) (string, error) { + if m, err := getFirstItemInList1ThatIsAlsoInList2(pubCtr.AcceptedBlockCypherModes, prvCtr.AcceptedBlockCypherModes); err != nil { + return "", errors.New("cannot find a block cypher mode that satisfy both contracts") + } else { + return m, nil + } +} + +func getBestHash(prvCtr *PrivateContract, pubCtr *PublicContract) (string, error) { + if h, err := getFirstItemInList1ThatIsAlsoInList2(pubCtr.AcceptedHashes, prvCtr.AcceptedHashes); err != nil { + return "", errors.New("cannot find a hash that satisfy both contracts") + } else { + return h, nil + } +} + +func GetAcceptedContract(prvCtr *PrivateContract, pubCtr *PublicContract) (*AcceptedContract, error) { + ret := new(AcceptedContract) + errs := make([]string, 0, 4) + var err error + if ret.Hash, err = getBestHash(prvCtr, pubCtr); err != nil { + errs = append(errs, err.Error()) + } + if ret.BlockCipher, err = getBestBlockCipher(prvCtr, pubCtr); err != nil { + errs = append(errs, err.Error()) + } + if ret.BlockCipherMode, err = getBestBlockCipherMode(prvCtr, pubCtr); err != nil { + errs = append(errs, err.Error()) + } + + return ret, joinAsError(errs) +} diff --git a/contract/best_contract_test.go b/contract/best_contract_test.go new file mode 100644 index 0000000..05087b4 --- /dev/null +++ b/contract/best_contract_test.go @@ -0,0 +1,63 @@ +package contract + +import ( + "testing" +) + +func TestGetBestHash(t *testing.T) { + prvCtr := new(PrivateContract) + pubCtr := new(PublicContract) + + pubCtr.AcceptedHashes = []string{"SHA384", "SHA256", "MD5"} + prvCtr.AcceptedHashes = []string{"SHA384", "SHA256"} + if h, err := getBestHash(prvCtr, pubCtr); err != nil { + t.Error(err) + } else if h != "SHA384" { + t.Error("bad choosen hash: ", h) + } + prvCtr.AcceptedHashes = []string{"SHA1", "MD4"} + if h, err := getBestHash(prvCtr, pubCtr); err == nil { + t.Error("should have an error here") + } else if h != "" { + t.Error("should not have choosen any hash function here") + } +} + +func TestGetFirstItemInList1ThatIsAlsoInList2(t *testing.T) { + lst1 := []string{"a", "b", "c"} + lst2 := []string{"b", "c"} + if c, err := getFirstItemInList1ThatIsAlsoInList2(lst1, lst2); c != "b" || err != nil { + t.Fail() + } + lst2 = []string{"d", "e"} + if c, err := getFirstItemInList1ThatIsAlsoInList2(lst1, lst2); c != "" || err == nil { + t.Fail() + } +} + +func TestGetAcceptedContract(t *testing.T) { + prvCtr := new(PrivateContract) + pubCtr := new(PublicContract) + + pubCtr.AcceptedHashes = []string{"SHA384", "SHA256", "MD5"} + prvCtr.AcceptedHashes = []string{"SHA384", "SHA256"} + + pubCtr.AcceptedBlockCyphers = []string{"aes", "des"} + prvCtr.AcceptedBlockCyphers = []string{"aes"} + + pubCtr.AcceptedBlockCypherModes = []string{"ofb"} + prvCtr.AcceptedBlockCypherModes = []string{"ofb"} + + ac, err := GetAcceptedContract(prvCtr, pubCtr) + if err != nil { + t.Error(err) + return + } + if ac.Hash != "SHA384" { + t.Error("bad hash") + } + if ac.BlockCipher != "aes" { + t.Error("bad block cipher") + } + +} diff --git a/contract/public_contract.go b/contract/public_contract.go index 1ada899..153ceb3 100644 --- a/contract/public_contract.go +++ b/contract/public_contract.go @@ -5,7 +5,8 @@ import ( ) 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"` + AcceptedHashes []string `yaml:"accepted_hashes" json:"accepted_hashes"` + AcceptedBlockCyphers []string `yaml:"accepted_block_cypher" json:"accepted_block_cypher"` + AcceptedBlockCypherModes []string `yaml:"accepted_block_cypher_mode" json:"accepted_block_cypher_mode"` + RSAPublicKey []*keys.RSAPublicKey `yaml:"rsa_public_key, omitempty" json:"rsa_public_key,omitempty"` } diff --git a/contract/public_contract_test.go b/contract/public_contract_test.go index 495ea08..217027f 100644 --- a/contract/public_contract_test.go +++ b/contract/public_contract_test.go @@ -36,9 +36,9 @@ func expectJson(c *PublicContract, jsonData string) error { func TestSimpleJsonification(t *testing.T) { c := &PublicContract{ - AcceptedHashes: []string{"sha246"}, - AcceptedBlockCypher: []string{"aes"}, - RSAPublicKey: []*keys.RSAPublicKey{&keys.RSAPublicKey{helper.B(12), 3}}, + AcceptedHashes: []string{"sha246"}, + AcceptedBlockCyphers: []string{"aes"}, + RSAPublicKey: []*keys.RSAPublicKey{&keys.RSAPublicKey{helper.B(12), 3}}, } if err := assertJSONMarshalling(c); err != nil { t.Error(err) @@ -47,9 +47,9 @@ func TestSimpleJsonification(t *testing.T) { func TestEmptyRSAPublicKey(t *testing.T) { c := &PublicContract{ - AcceptedHashes: []string{"sha246"}, - AcceptedBlockCypher: []string{"aes"}, - RSAPublicKey: []*keys.RSAPublicKey{&keys.RSAPublicKey{helper.B(12), 3}}, + AcceptedHashes: []string{"sha246"}, + AcceptedBlockCyphers: []string{"aes"}, + RSAPublicKey: []*keys.RSAPublicKey{&keys.RSAPublicKey{helper.B(12), 3}}, } jsonData := `{ "accepted_hashes": ["sha246"], diff --git a/doc/fileformat.md b/doc/fileformat.md index e4ea000..6a08feb 100644 --- a/doc/fileformat.md +++ b/doc/fileformat.md @@ -24,13 +24,16 @@ 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 + - sha512 # first choice + - sha256 # second choice accepted_block_cypher: - - aes + - aes # first choice + - 3des # second choice accepted_modes: - - ofb + - ofb # first choice + - cbc # second choice signatures_required: yes diff --git a/integration/enveloppayload_test.go b/integration/enveloppayload_test.go index 11dcb86..d585822 100644 --- a/integration/enveloppayload_test.go +++ b/integration/enveloppayload_test.go @@ -13,19 +13,6 @@ import ( "github.com/didiercrunch/filou/payload" ) -type mockEncryptor struct{} - -func (this *mockEncryptor) Encrypt(data []byte) ([]byte, error) { - // cesar encryption! - ret := make([]byte, len(data)) - for i, d := range data { - ret[i] = d + 3 // modulo is implicit - } - return ret, nil -} - -type mockSigner struct{} - var random = helper.NewMockRandomReader() func generateRSAKeyPair() (*rsa.PrivateKey, *rsa.PublicKey) { @@ -42,15 +29,6 @@ func getEncryterAndSigner() *asymetric.RsaOaepPss { return &asymetric.RsaOaepPss{alicePrivateKey, bobPubKey, crypto.SHA512, random} } -func (this *mockSigner) Sign(data []byte) ([]byte, error) { - // a slice with the sum of the data plus a "secret" value - var sum byte = 36 - for _, d := range data { - sum += d - } - return []byte{sum}, nil -} - func TestPayloadCanBeUseInEnvelop(t *testing.T) { encryterAndSigner := getEncryterAndSigner() payload_ := payload.GetDefaultPayload(bytes.NewBufferString("some data to encrypt"))