github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/ext/hash/hash.go (about)

     1  // Package hash provides cryptographic hash functions.
     2  //
     3  // Provided functions:
     4  //   - md4(data)
     5  //   - md5(data)
     6  //   - sha1(data)
     7  //   - sha3(data, size) (default size 256)
     8  //   - sha224(data)
     9  //   - sha256(data, size) (default size 256)
    10  //   - sha384(data)
    11  //   - sha512(data, size) (default size 512)
    12  //   - blake2s(data)
    13  //   - blake2b(data, size) (default size 512)
    14  //   - ripemd160(data)
    15  //
    16  // Each SQL function will only be registered if the corresponding
    17  // [crypto.Hash] function is available.
    18  // To ensure a specific hash function is available,
    19  // import the implementing package.
    20  package hash
    21  
    22  import (
    23  	"crypto"
    24  
    25  	"github.com/ncruces/go-sqlite3"
    26  )
    27  
    28  // Register registers cryptographic hash functions for a database connection.
    29  func Register(db *sqlite3.Conn) {
    30  	flags := sqlite3.DETERMINISTIC | sqlite3.INNOCUOUS
    31  
    32  	if crypto.MD4.Available() {
    33  		db.CreateFunction("md4", 1, flags, md4Func)
    34  	}
    35  	if crypto.MD5.Available() {
    36  		db.CreateFunction("md5", 1, flags, md5Func)
    37  	}
    38  	if crypto.SHA1.Available() {
    39  		db.CreateFunction("sha1", 1, flags, sha1Func)
    40  	}
    41  	if crypto.SHA3_512.Available() {
    42  		db.CreateFunction("sha3", 1, flags, sha3Func)
    43  		db.CreateFunction("sha3", 2, flags, sha3Func)
    44  	}
    45  	if crypto.SHA256.Available() {
    46  		db.CreateFunction("sha224", 1, flags, sha224Func)
    47  		db.CreateFunction("sha256", 1, flags, sha256Func)
    48  		db.CreateFunction("sha256", 2, flags, sha256Func)
    49  	}
    50  	if crypto.SHA512.Available() {
    51  		db.CreateFunction("sha384", 1, flags, sha384Func)
    52  		db.CreateFunction("sha512", 1, flags, sha512Func)
    53  		db.CreateFunction("sha512", 2, flags, sha512Func)
    54  	}
    55  	if crypto.BLAKE2s_256.Available() {
    56  		db.CreateFunction("blake2s", 1, flags, blake2sFunc)
    57  	}
    58  	if crypto.BLAKE2b_512.Available() {
    59  		db.CreateFunction("blake2b", 1, flags, blake2bFunc)
    60  		db.CreateFunction("blake2b", 2, flags, blake2bFunc)
    61  	}
    62  	if crypto.RIPEMD160.Available() {
    63  		db.CreateFunction("ripemd160", 1, flags, ripemd160Func)
    64  	}
    65  }
    66  
    67  func md4Func(ctx sqlite3.Context, arg ...sqlite3.Value) {
    68  	hashFunc(ctx, arg[0], crypto.MD4)
    69  }
    70  
    71  func md5Func(ctx sqlite3.Context, arg ...sqlite3.Value) {
    72  	hashFunc(ctx, arg[0], crypto.MD5)
    73  }
    74  
    75  func sha1Func(ctx sqlite3.Context, arg ...sqlite3.Value) {
    76  	hashFunc(ctx, arg[0], crypto.SHA1)
    77  }
    78  
    79  func ripemd160Func(ctx sqlite3.Context, arg ...sqlite3.Value) {
    80  	hashFunc(ctx, arg[0], crypto.RIPEMD160)
    81  }
    82  
    83  func hashFunc(ctx sqlite3.Context, arg sqlite3.Value, fn crypto.Hash) {
    84  	var data []byte
    85  	switch arg.Type() {
    86  	case sqlite3.NULL:
    87  		return
    88  	case sqlite3.BLOB:
    89  		data = arg.RawBlob()
    90  	default:
    91  		data = arg.RawText()
    92  	}
    93  
    94  	h := fn.New()
    95  	h.Write(data)
    96  	ctx.ResultBlob(h.Sum(nil))
    97  }