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  }