github.com/Aoi-hosizora/ahlib-more@v1.5.1-0.20230404072844-256112befaf6/xcrypto/xcrypto.go (about) 1 package xcrypto 2 3 import ( 4 "bytes" 5 "crypto/md5" 6 "crypto/sha1" 7 "crypto/sha256" 8 "crypto/sha512" 9 "encoding/base32" 10 "encoding/base64" 11 "encoding/hex" 12 "errors" 13 "github.com/Aoi-hosizora/ahlib/xstring" 14 "golang.org/x/crypto/bcrypt" 15 "golang.org/x/crypto/md4" 16 "golang.org/x/crypto/sha3" 17 "hash" 18 "hash/adler32" 19 "hash/crc32" 20 "hash/crc64" 21 "hash/fnv" 22 ) 23 24 // =============== 25 // hash algorithms 26 // =============== 27 28 // FNV32 uses fnv32 to hash string to uint32. 29 func FNV32(text string) uint32 { 30 algorithm := fnv.New32() // hash/fnv 31 return Uint32Hasher(algorithm, text) 32 } 33 34 // FNV32a uses fnv32a to hash string to uint32. 35 func FNV32a(text string) uint32 { 36 algorithm := fnv.New32a() // hash/fnv 37 return Uint32Hasher(algorithm, text) 38 } 39 40 // FNV64 uses fnv64 to hash string to uint64. 41 func FNV64(text string) uint64 { 42 algorithm := fnv.New64() // hash/fnv 43 return Uint64Hasher(algorithm, text) 44 } 45 46 // FNV64a uses fnv64a to hash string to uint64. 47 func FNV64a(text string) uint64 { 48 algorithm := fnv.New64a() // hash/fnv 49 return Uint64Hasher(algorithm, text) 50 } 51 52 // FNV128 uses fnv128 to hash string. 53 func FNV128(text string) string { 54 algorithm := fnv.New128() // hash/fnv 55 return StringHasher(algorithm, text) 56 } 57 58 // FNV128a uses fnv128 to hash string. 59 func FNV128a(text string) string { 60 algorithm := fnv.New128a() // hash/fnv 61 return StringHasher(algorithm, text) 62 } 63 64 // CRC32 uses crc32 (IEEE table) to hash string to uint32. 65 func CRC32(text string) uint32 { 66 algorithm := crc32.NewIEEE() // hash/crc32 67 return Uint32Hasher(algorithm, text) 68 } 69 70 // CRC64 uses crc64 (ISO table) to hash string to uint64. 71 func CRC64(text string) uint64 { 72 algorithm := crc64.New(crc64.MakeTable(crc64.ISO)) // hash/crc64 73 return Uint64Hasher(algorithm, text) 74 } 75 76 // ADLER32 uses adler32 to hash string to uint32. 77 func ADLER32(text string) uint32 { 78 algorithm := adler32.New() // hash/adler32 79 return Uint32Hasher(algorithm, text) 80 } 81 82 // MD4 uses md4 to hash string. 83 func MD4(text string) string { 84 algorithm := md4.New() // x/crypto/md4 85 return StringHasher(algorithm, text) 86 } 87 88 // MD5 uses md5 to hash string. 89 func MD5(text string) string { 90 algorithm := md5.New() // crypto/md5 91 return StringHasher(algorithm, text) 92 } 93 94 // SHA1 uses sha-1 to hash string. 95 func SHA1(text string) string { 96 algorithm := sha1.New() // crypto/sha1 97 return StringHasher(algorithm, text) 98 } 99 100 // SHA224 uses sha2-224 to hash string. 101 func SHA224(text string) string { 102 algorithm := sha256.New224() // crypto/sha256 103 return StringHasher(algorithm, text) 104 } 105 106 // SHA256 uses sha2-256 to hash string. 107 func SHA256(text string) string { 108 algorithm := sha256.New() // crypto/sha256 109 return StringHasher(algorithm, text) 110 } 111 112 // SHA384 uses sha2-384 to hash string. 113 func SHA384(text string) string { 114 algorithm := sha512.New384() // crypto/sha512 115 return StringHasher(algorithm, text) 116 } 117 118 // SHA512 uses sha2-512 to hash string. 119 func SHA512(text string) string { 120 algorithm := sha512.New() // crypto/sha512 121 return StringHasher(algorithm, text) 122 } 123 124 // SHA512_224 uses sha2-512/224 to hash string. 125 func SHA512_224(text string) string { 126 algorithm := sha512.New512_224() // crypto/sha512 127 return StringHasher(algorithm, text) 128 } 129 130 // SHA512_256 uses sha2-512/256 to hash string. 131 func SHA512_256(text string) string { 132 algorithm := sha512.New512_256() // crypto/sha512 133 return StringHasher(algorithm, text) 134 } 135 136 // SHA3_224 uses sha3-224 to hash string. 137 func SHA3_224(text string) string { 138 algorithm := sha3.New224() // x/crypto/sha3 139 return StringHasher(algorithm, text) 140 } 141 142 // SHA3_256 uses sha3-256 to hash string. 143 func SHA3_256(text string) string { 144 algorithm := sha3.New256() // x/crypto/sha3 145 return StringHasher(algorithm, text) 146 } 147 148 // SHA3_384 uses sha3-384 to hash string. 149 func SHA3_384(text string) string { 150 algorithm := sha3.New384() // x/crypto/sha3 151 return StringHasher(algorithm, text) 152 } 153 154 // SHA3_512 uses sha3-512 to hash string. 155 func SHA3_512(text string) string { 156 algorithm := sha3.New512() // x/crypto/sha3 157 return StringHasher(algorithm, text) 158 } 159 160 // ============= 161 // string hasher 162 // ============= 163 164 // Uint32Hasher uses hash.Hash32 to encode string to uint32. 165 func Uint32Hasher(algorithm hash.Hash32, text string) uint32 { 166 _, _ = algorithm.Write(xstring.FastStob(text)) 167 return algorithm.Sum32() 168 } 169 170 // Uint64Hasher uses hash.Hash64 to encode string to uint64. 171 func Uint64Hasher(algorithm hash.Hash64, text string) uint64 { 172 _, _ = algorithm.Write(xstring.FastStob(text)) 173 return algorithm.Sum64() 174 } 175 176 // StringHasher uses hash.Hash to encode string to string. 177 func StringHasher(algorithm hash.Hash, text string) string { 178 _, _ = algorithm.Write(xstring.FastStob(text)) 179 return HexEncodeToString(algorithm.Sum(nil)) 180 } 181 182 // =============== 183 // encode & decode 184 // =============== 185 186 // HexEncodeToBytes encodes bytes to hex bytes. 187 func HexEncodeToBytes(data []byte) []byte { 188 dst := make([]byte, hex.EncodedLen(len(data))) // encoding/hex 189 hex.Encode(dst, data) 190 return dst 191 } 192 193 // HexEncodeToString encodes bytes to hex string. 194 func HexEncodeToString(data []byte) string { 195 return xstring.FastBtos(HexEncodeToBytes(data)) 196 } 197 198 // HexDecodeFromBytes decodes bytes from hex bytes. 199 func HexDecodeFromBytes(data []byte) ([]byte, error) { 200 buf := make([]byte, hex.DecodedLen(len(data))) // encoding/hex 201 n, err := hex.Decode(buf, data) 202 return buf[:n], err 203 } 204 205 // HexDecodeFromString decodes bytes from hex string. 206 func HexDecodeFromString(data string) ([]byte, error) { 207 return HexDecodeFromBytes(xstring.FastStob(data)) 208 } 209 210 // Base32EncodeToBytes encodes bytes to base32 bytes. 211 func Base32EncodeToBytes(data []byte) []byte { 212 enc := base32.StdEncoding // encoding/base32 213 buf := make([]byte, enc.EncodedLen(len(data))) 214 enc.Encode(buf, data) 215 return buf 216 } 217 218 // Base32EncodeToString encodes bytes to base32 string. 219 func Base32EncodeToString(data []byte) string { 220 return xstring.FastBtos(Base32EncodeToBytes(data)) 221 } 222 223 // Base32DecodeFromBytes decodes bytes from base32 bytes. 224 func Base32DecodeFromBytes(data []byte) ([]byte, error) { 225 enc := base32.StdEncoding // encoding/base32 226 buf := make([]byte, enc.DecodedLen(len(data))) 227 n, err := enc.Decode(buf, data) 228 return buf[:n], err 229 } 230 231 // Base32DecodeFromString decodes bytes from base32 string. 232 func Base32DecodeFromString(data string) ([]byte, error) { 233 return Base32DecodeFromBytes(xstring.FastStob(data)) 234 } 235 236 // Base64EncodeToBytes encodes bytes to base64 bytes. 237 func Base64EncodeToBytes(data []byte) []byte { 238 enc := base64.StdEncoding // encoding/base64 239 buf := make([]byte, enc.EncodedLen(len(data))) 240 enc.Encode(buf, data) 241 return buf 242 } 243 244 // Base64EncodeToString encodes bytes to base64 string. 245 func Base64EncodeToString(data []byte) string { 246 return xstring.FastBtos(Base64EncodeToBytes(data)) 247 } 248 249 // Base64DecodeFromBytes decodes bytes from base64 bytes. 250 func Base64DecodeFromBytes(data []byte) ([]byte, error) { 251 enc := base64.StdEncoding // encoding/base64 252 buf := make([]byte, enc.DecodedLen(len(data))) 253 n, err := enc.Decode(buf, data) 254 return buf[:n], err 255 } 256 257 // Base64DecodeFromString decodes bytes from base64 string. 258 func Base64DecodeFromString(data string) ([]byte, error) { 259 return Base64DecodeFromBytes(xstring.FastStob(data)) 260 } 261 262 // ========================= 263 // pkcs padding and trimming 264 // ========================= 265 266 const ( 267 panicZeroBlockSize = "xcrypto: blockSize must larger than 0" 268 ) 269 270 // PKCS5Padding uses PKCS#5 and PKCS#7 to pad data to block aligned bytes. 271 func PKCS5Padding(data []byte, blockSize int) []byte { 272 if blockSize <= 0 { 273 panic(panicZeroBlockSize) 274 } 275 276 padLen := blockSize - len(data)%blockSize 277 padText := bytes.Repeat([]byte{byte(padLen)}, padLen) 278 return append(data, padText...) 279 } 280 281 // PKCS5Trimming uses PKCS#5 and PKCS#7 to trim data from block aligned bytes. 282 func PKCS5Trimming(data []byte) []byte { 283 length := len(data) 284 padLen := int(data[length-1]) 285 return data[:length-padLen] 286 } 287 288 // ============== 289 // bcrypt related 290 // ============== 291 292 const ( 293 BcryptMinCost int = 4 // The bcrypt minimum allowable cost. 294 BcryptMaxCost int = 31 // The bcrypt maximum allowable cost. 295 BcryptDefaultCost int = 10 // The bcrypt default cost, and this will actually be set if a cost is below BcryptMinCost. 296 ) 297 298 // BcryptEncrypt uses bcrypt to encrypt password using given cost. 299 func BcryptEncrypt(password []byte, cost int) ([]byte, error) { 300 return bcrypt.GenerateFromPassword(password, cost) // x/crypto/bcrypt 301 } 302 303 // BcryptEncryptWithDefaultCost uses bcrypt to encrypt password using BcryptDefaultCost. 304 func BcryptEncryptWithDefaultCost(password []byte) ([]byte, error) { 305 return bcrypt.GenerateFromPassword(password, BcryptDefaultCost) 306 } 307 308 // BcryptCompare compares hashed encrypted password and given password. 309 func BcryptCompare(password, encrypted []byte) (ok bool, err error) { 310 err = bcrypt.CompareHashAndPassword(encrypted, password) 311 if err == nil { 312 return true, nil 313 } 314 if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) { 315 return false, nil 316 } 317 return false, err 318 }