From ecaaa91da99662225cee34e18041407660dac043 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 24 Jan 2019 15:56:28 -0800 Subject: [PATCH] lang/funcs: Factor out the various hash function implementations These all follow the pattern of creating a hash and converting it to a string using some encoding function, so we can write this implementation only once and parameterize it with a hash factory function and an encoding function. This also includes a new test for the sha512 function, which was previously missing a test and, it turns out, actually computing sha256 instead. --- lang/funcs/crypto.go | 122 ++++++++------------------------------ lang/funcs/crypto_test.go | 33 +++++++++++ 2 files changed, 59 insertions(+), 96 deletions(-) diff --git a/lang/funcs/crypto.go b/lang/funcs/crypto.go index abec789ca..912364cf8 100644 --- a/lang/funcs/crypto.go +++ b/lang/funcs/crypto.go @@ -11,6 +11,7 @@ import ( "encoding/hex" "encoding/pem" "fmt" + "hash" uuid "github.com/hashicorp/go-uuid" "github.com/zclconf/go-cty/cty" @@ -33,41 +34,11 @@ var UUIDFunc = function.New(&function.Spec{ // Base64Sha256Func constructs a function that computes the SHA256 hash of a given string // and encodes it with Base64. -var Base64Sha256Func = function.New(&function.Spec{ - Params: []function.Parameter{ - { - Name: "str", - Type: cty.String, - }, - }, - Type: function.StaticReturnType(cty.String), - Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - s := args[0].AsString() - h := sha256.New() - h.Write([]byte(s)) - shaSum := h.Sum(nil) - return cty.StringVal(base64.StdEncoding.EncodeToString(shaSum[:])), nil - }, -}) +var Base64Sha256Func = makeStringHashFunction(sha256.New, base64.StdEncoding.EncodeToString) // Base64Sha512Func constructs a function that computes the SHA256 hash of a given string // and encodes it with Base64. -var Base64Sha512Func = function.New(&function.Spec{ - Params: []function.Parameter{ - { - Name: "str", - Type: cty.String, - }, - }, - Type: function.StaticReturnType(cty.String), - Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - s := args[0].AsString() - h := sha512.New() - h.Write([]byte(s)) - shaSum := h.Sum(nil) - return cty.StringVal(base64.StdEncoding.EncodeToString(shaSum[:])), nil - }, -}) +var Base64Sha512Func = makeStringHashFunction(sha512.New, base64.StdEncoding.EncodeToString) // BcryptFunc constructs a function that computes a hash of the given string using the Blowfish cipher. var BcryptFunc = function.New(&function.Spec{ @@ -108,22 +79,7 @@ var BcryptFunc = function.New(&function.Spec{ }) // Md5Func constructs a function that computes the MD5 hash of a given string and encodes it with hexadecimal digits. -var Md5Func = function.New(&function.Spec{ - Params: []function.Parameter{ - { - Name: "str", - Type: cty.String, - }, - }, - Type: function.StaticReturnType(cty.String), - Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - s := args[0].AsString() - h := md5.New() - h.Write([]byte(s)) - hash := hex.EncodeToString(h.Sum(nil)) - return cty.StringVal(hash), nil - }, -}) +var Md5Func = makeStringHashFunction(md5.New, hex.EncodeToString) // RsaDecryptFunc constructs a function that decrypts an RSA-encrypted ciphertext. var RsaDecryptFunc = function.New(&function.Spec{ @@ -173,60 +129,34 @@ var RsaDecryptFunc = function.New(&function.Spec{ // Sha1Func contructs a function that computes the SHA1 hash of a given string // and encodes it with hexadecimal digits. -var Sha1Func = function.New(&function.Spec{ - Params: []function.Parameter{ - { - Name: "str", - Type: cty.String, - }, - }, - Type: function.StaticReturnType(cty.String), - Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - s := args[0].AsString() - h := sha1.New() - h.Write([]byte(s)) - hash := hex.EncodeToString(h.Sum(nil)) - return cty.StringVal(hash), nil - }, -}) +var Sha1Func = makeStringHashFunction(sha1.New, hex.EncodeToString) // Sha256Func contructs a function that computes the SHA256 hash of a given string // and encodes it with hexadecimal digits. -var Sha256Func = function.New(&function.Spec{ - Params: []function.Parameter{ - { - Name: "str", - Type: cty.String, - }, - }, - Type: function.StaticReturnType(cty.String), - Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - s := args[0].AsString() - h := sha256.New() - h.Write([]byte(s)) - hash := hex.EncodeToString(h.Sum(nil)) - return cty.StringVal(hash), nil - }, -}) +var Sha256Func = makeStringHashFunction(sha256.New, hex.EncodeToString) -// Sha512Func contructs a function that computes the SHA256 hash of a given string +// Sha512Func contructs a function that computes the SHA512 hash of a given string // and encodes it with hexadecimal digits. -var Sha512Func = function.New(&function.Spec{ - Params: []function.Parameter{ - { - Name: "str", - Type: cty.String, +var Sha512Func = makeStringHashFunction(sha512.New, hex.EncodeToString) + +func makeStringHashFunction(hf func() hash.Hash, enc func([]byte) string) function.Function { + return function.New(&function.Spec{ + Params: []function.Parameter{ + { + Name: "str", + Type: cty.String, + }, }, - }, - Type: function.StaticReturnType(cty.String), - Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - s := args[0].AsString() - h := sha256.New() - h.Write([]byte(s)) - hash := hex.EncodeToString(h.Sum(nil)) - return cty.StringVal(hash), nil - }, -}) + Type: function.StaticReturnType(cty.String), + Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { + s := args[0].AsString() + h := hf() + h.Write([]byte(s)) + rv := enc(h.Sum(nil)) + return cty.StringVal(rv), nil + }, + }) +} // UUID generates and returns a Type-4 UUID in the standard hexadecimal string // format. diff --git a/lang/funcs/crypto_test.go b/lang/funcs/crypto_test.go index f31fd0f17..ecc3aaaec 100644 --- a/lang/funcs/crypto_test.go +++ b/lang/funcs/crypto_test.go @@ -301,6 +301,39 @@ func TestSha256(t *testing.T) { } } +func TestSha512(t *testing.T) { + tests := []struct { + String cty.Value + Want cty.Value + Err bool + }{ + { + cty.StringVal("test"), + cty.StringVal("ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"), + false, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("sha512(%#v)", test.String), func(t *testing.T) { + got, err := Sha512(test.String) + + if test.Err { + if err == nil { + t.Fatal("succeeded; want error") + } + return + } else if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + if !got.RawEquals(test.Want) { + t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) + } + }) + } +} + const ( CipherBase64 = "eczGaDhXDbOFRZGhjx2etVzWbRqWDlmq0bvNt284JHVbwCgObiuyX9uV0LSAMY707IEgMkExJqXmsB4OWKxvB7epRB9G/3+F+pcrQpODlDuL9oDUAsa65zEpYF0Wbn7Oh7nrMQncyUPpyr9WUlALl0gRWytOA23S+y5joa4M34KFpawFgoqTu/2EEH4Xl1zo+0fy73fEto+nfkUY+meuyGZ1nUx/+DljP7ZqxHBFSlLODmtuTMdswUbHbXbWneW51D7Jm7xB8nSdiA2JQNK5+Sg5x8aNfgvFTt/m2w2+qpsyFa5Wjeu6fZmXSl840CA07aXbk9vN4I81WmJyblD/ZA==" PrivateKey = `