From 4f55647bd7da42675cc24bfd16229a4ed3025f8c Mon Sep 17 00:00:00 2001 From: Sec Cake Date: Mon, 2 May 2022 00:40:16 +0800 Subject: [PATCH] Added some hash validation (#875) --- README.md | 10 ++ baked_in.go | 60 ++++++++ regexes.go | 20 +++ validator_test.go | 359 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 449 insertions(+) diff --git a/README.md b/README.md index 0201880..2294cce 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,16 @@ Baked-in Validations | uuid5 | Universally Unique Identifier UUID v5 | | uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 | | uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 | +| md4 | MD4 hash | +| md5 | MD5 hash | +| sha256 | SHA256 hash | +| sha384 | SHA384 hash | +| sha512 | SHA512 hash | +| ripemd128 | RIPEMD-128 hash | +| ripemd128 | RIPEMD-160 hash | +| tiger128 | TIGER128 hash | +| tiger160 | TIGER160 hash | +| tiger192 | TIGER192 hash | | semver | Semantic Versioning 2.0.0 | | ulid | Universally Unique Lexicographically Sortable Identifier ULID | diff --git a/baked_in.go b/baked_in.go index 2234479..f2f0939 100644 --- a/baked_in.go +++ b/baked_in.go @@ -151,6 +151,16 @@ var ( "uuid4_rfc4122": isUUID4RFC4122, "uuid5_rfc4122": isUUID5RFC4122, "ulid": isULID, + "md4": isMD4, + "md5": isMD5, + "sha256": isSHA256, + "sha384": isSHA384, + "sha512": isSHA512, + "ripemd128": isRIPEMD128, + "ripemd160": isRIPEMD160, + "tiger128": isTIGER128, + "tiger160": isTIGER160, + "tiger192": isTIGER192, "ascii": isASCII, "printascii": isPrintableASCII, "multibyte": hasMultiByteCharacter, @@ -500,6 +510,56 @@ func isULID(fl FieldLevel) bool { return uLIDRegex.MatchString(fl.Field().String()) } +// isMD4 is the validation function for validating if the field's value is a valid MD4. +func isMD4(fl FieldLevel) bool { + return md4Regex.MatchString(fl.Field().String()) +} + +// isMD5 is the validation function for validating if the field's value is a valid MD5. +func isMD5(fl FieldLevel) bool { + return md5Regex.MatchString(fl.Field().String()) +} + +// isSHA256 is the validation function for validating if the field's value is a valid SHA256. +func isSHA256(fl FieldLevel) bool { + return sha256Regex.MatchString(fl.Field().String()) +} + +// isSHA384 is the validation function for validating if the field's value is a valid SHA384. +func isSHA384(fl FieldLevel) bool { + return sha384Regex.MatchString(fl.Field().String()) +} + +// isSHA512 is the validation function for validating if the field's value is a valid SHA512. +func isSHA512(fl FieldLevel) bool { + return sha512Regex.MatchString(fl.Field().String()) +} + +// isRIPEMD128 is the validation function for validating if the field's value is a valid PIPEMD128. +func isRIPEMD128(fl FieldLevel) bool { + return ripemd128Regex.MatchString(fl.Field().String()) +} + +// isRIPEMD160 is the validation function for validating if the field's value is a valid PIPEMD160. +func isRIPEMD160(fl FieldLevel) bool { + return ripemd160Regex.MatchString(fl.Field().String()) +} + +// isTIGER128 is the validation function for validating if the field's value is a valid TIGER128. +func isTIGER128(fl FieldLevel) bool { + return tiger128Regex.MatchString(fl.Field().String()) +} + +// isTIGER160 is the validation function for validating if the field's value is a valid TIGER160. +func isTIGER160(fl FieldLevel) bool { + return tiger160Regex.MatchString(fl.Field().String()) +} + +// isTIGER192 is the validation function for validating if the field's value is a valid isTIGER192. +func isTIGER192(fl FieldLevel) bool { + return tiger192Regex.MatchString(fl.Field().String()) +} + // isISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN. func isISBN(fl FieldLevel) bool { return isISBN10(fl) || isISBN13(fl) diff --git a/regexes.go b/regexes.go index a8668f8..9c1c634 100644 --- a/regexes.go +++ b/regexes.go @@ -30,6 +30,16 @@ const ( uUID5RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-5[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" uUIDRFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" uLIDRegexString = "^[A-HJKMNP-TV-Z0-9]{26}$" + md4RegexString = "^[0-9a-f]{32}$" + md5RegexString = "^[0-9a-f]{32}$" + sha256RegexString = "^[0-9a-f]{64}$" + sha384RegexString = "^[0-9a-f]{96}$" + sha512RegexString = "^[0-9a-f]{128}$" + ripemd128RegexString = "^[0-9a-f]{32}$" + ripemd160RegexString = "^[0-9a-f]{40}$" + tiger128RegexString = "^[0-9a-f]{32}$" + tiger160RegexString = "^[0-9a-f]{40}$" + tiger192RegexString = "^[0-9a-f]{48}$" aSCIIRegexString = "^[\x00-\x7F]*$" printableASCIIRegexString = "^[\x20-\x7E]*$" multibyteRegexString = "[^\x00-\x7F]" @@ -84,6 +94,16 @@ var ( uUID5RFC4122Regex = regexp.MustCompile(uUID5RFC4122RegexString) uUIDRFC4122Regex = regexp.MustCompile(uUIDRFC4122RegexString) uLIDRegex = regexp.MustCompile(uLIDRegexString) + md4Regex = regexp.MustCompile(md4RegexString) + md5Regex = regexp.MustCompile(md5RegexString) + sha256Regex = regexp.MustCompile(sha256RegexString) + sha384Regex = regexp.MustCompile(sha384RegexString) + sha512Regex = regexp.MustCompile(sha512RegexString) + ripemd128Regex = regexp.MustCompile(ripemd128RegexString) + ripemd160Regex = regexp.MustCompile(ripemd160RegexString) + tiger128Regex = regexp.MustCompile(tiger128RegexString) + tiger160Regex = regexp.MustCompile(tiger160RegexString) + tiger192Regex = regexp.MustCompile(tiger192RegexString) aSCIIRegex = regexp.MustCompile(aSCIIRegexString) printableASCIIRegex = regexp.MustCompile(printableASCIIRegexString) multibyteRegex = regexp.MustCompile(multibyteRegexString) diff --git a/validator_test.go b/validator_test.go index 8abe0ce..933626f 100644 --- a/validator_test.go +++ b/validator_test.go @@ -4309,6 +4309,365 @@ func TestULIDValidation(t *testing.T) { } } +func TestMD4Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "md4") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d MD4 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d MD4 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "md4" { + t.Fatalf("Index: %d MD4 failed Error: %s", i, errs) + } + } + } + } +} + +func TestMD5Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "md5") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d MD5 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d MD5 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "md5" { + t.Fatalf("Index: %d MD5 failed Error: %s", i, errs) + } + } + } + } +} + +func TestSHA256Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "sha256") + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d SHA256 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d SHA256 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "sha256" { + t.Fatalf("Index: %d SHA256 failed Error: %s", i, errs) + } + } + } + } +} + +func TestSHA384Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "sha384") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d SHA384 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d SHA384 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "sha384" { + t.Fatalf("Index: %d SHA384 failed Error: %s", i, errs) + } + } + } + } +} + +func TestSHA512Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "sha512") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d SHA512 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d SHA512 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "sha512" { + t.Fatalf("Index: %d SHA512 failed Error: %s", i, errs) + } + } + } + } +} + +func TestRIPEMD128Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "ripemd128") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d RIPEMD128 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d RIPEMD128 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "ripemd128" { + t.Fatalf("Index: %d RIPEMD128 failed Error: %s", i, errs) + } + } + } + } +} + +func TestRIPEMD160Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "ripemd160") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d RIPEMD160 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d RIPEMD160 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "ripemd160" { + t.Fatalf("Index: %d RIPEMD160 failed Error: %s", i, errs) + } + } + } + } +} + +func TestTIGER128Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "tiger128") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d TIGER128 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d TIGER128 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "tiger128" { + t.Fatalf("Index: %d TIGER128 failed Error: %s", i, errs) + } + } + } + } +} + +func TestTIGER160Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac6f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "tiger160") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d TIGER160 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d TIGER160 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "tiger160" { + t.Fatalf("Index: %d TIGER160 failed Error: %s", i, errs) + } + } + } + } +} + +func TestTIGER192Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc4", true}, + {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc-", false}, + {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc41", false}, + {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dcC", false}, + {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "tiger192") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d TIGER192 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d TIGER192 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "tiger192" { + t.Fatalf("Index: %d TIGER192 failed Error: %s", i, errs) + } + } + } + } +} + func TestISBNValidation(t *testing.T) { tests := []struct { param string