// Copyright (C) 2018 The Go-SQLite3 Authors. // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. // The crypt functions provides several different implementations for the // default embedded sqlite_crypt function. // This function is uses a ceasar-cypher by default // and is used within the UserAuthentication module to encode // the password. // // The provided functions can be used as an overload to the sqlite_crypt // function through the use of the RegisterFunc on the connection. // // Because the functions can serv a purpose to an end-user // without using the UserAuthentication module // the functions are default compiled in. // // From SQLITE3 - user-auth.txt // The sqlite_user.pw field is encoded by a built-in SQL function // "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument // is the plaintext password supplied to the sqlite3_user_authenticate() // interface. The second argument is the sqlite_user.pw value and is supplied // so that the function can extract the "salt" used by the password encoder. // The result of sqlite_crypt(X,Y) is another blob which is the value that // ends up being stored in sqlite_user.pw. To verify credentials X supplied // by the sqlite3_user_authenticate() routine, SQLite runs: // // sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw) // // To compute an appropriate sqlite_user.pw value from a new or modified // password X, sqlite_crypt(X,NULL) is run. A new random salt is selected // when the second argument is NULL. // // The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher // which prevents passwords from being revealed by searching the raw database // for ASCII text, but is otherwise trivally broken. For better password // security, the database should be encrypted using the SQLite Encryption // Extension or similar technology. Or, the application can use the // sqlite3_create_function() interface to provide an alternative // implementation of sqlite_crypt() that computes a stronger password hash, // perhaps using a cryptographic hash function like SHA1. package sqlite3 import ( "crypto/sha1" "crypto/sha256" "crypto/sha512" ) // Force Implementation var ( _ CryptEncoder = (*sha1Encoder)(nil) _ CryptEncoder = (*sha256Encoder)(nil) _ CryptEncoder = (*sha384Encoder)(nil) _ CryptEncoder = (*sha512Encoder)(nil) _ CryptSaltedEncoder = (*ssha1Encoder)(nil) _ CryptSaltedEncoder = (*ssha256Encoder)(nil) _ CryptSaltedEncoder = (*ssha384Encoder)(nil) _ CryptSaltedEncoder = (*ssha512Encoder)(nil) ) // CryptEncoder provides the interface for implementing // a sqlite_crypt encoder. type CryptEncoder interface { Encode(pass []byte, hash interface{}) []byte } // CryptSaltedEncoder provides the interface for a encoder // to return its configured salt. type CryptSaltedEncoder interface { CryptEncoder Salt() string } type sha1Encoder struct{} func (e *sha1Encoder) Encode(pass []byte, hash interface{}) []byte { h := sha1.Sum(pass) return h[:] } // NewSHA1Encoder returns a new SHA1 Encoder. func NewSHA1Encoder() CryptEncoder { return &sha1Encoder{} } type ssha1Encoder struct { salt string } func (e *ssha1Encoder) Encode(pass []byte, hash interface{}) []byte { s := []byte(e.salt) p := append(pass, s...) h := sha1.Sum(p) return h[:] } func (e *ssha1Encoder) Salt() string { return e.salt } // NewSSHA1Encoder returns a new salted SHA1 Encoder. func NewSSHA1Encoder(salt string) CryptSaltedEncoder { return &ssha1Encoder{ salt: salt, } } type sha256Encoder struct{} func (e *sha256Encoder) Encode(pass []byte, hash interface{}) []byte { h := sha256.Sum256(pass) return h[:] } // NewSHA256Encoder returns a new SHA256 Encoder. func NewSHA256Encoder() CryptEncoder { return &sha256Encoder{} } type ssha256Encoder struct { salt string } func (e *ssha256Encoder) Encode(pass []byte, hash interface{}) []byte { s := []byte(e.salt) p := append(pass, s...) h := sha256.Sum256(p) return h[:] } func (e *ssha256Encoder) Salt() string { return e.salt } // NewSSHA256Encoder returns a new salted SHA256 Encoder. func NewSSHA256Encoder(salt string) CryptSaltedEncoder { return &ssha256Encoder{ salt: salt, } } type sha384Encoder struct{} func (e *sha384Encoder) Encode(pass []byte, hash interface{}) []byte { h := sha512.Sum384(pass) return h[:] } // NewSHA384Encoder returns a new SHA384 Encoder. func NewSHA384Encoder() CryptEncoder { return &sha384Encoder{} } type ssha384Encoder struct { salt string } func (e *ssha384Encoder) Encode(pass []byte, hash interface{}) []byte { s := []byte(e.salt) p := append(pass, s...) h := sha512.Sum384(p) return h[:] } func (e *ssha384Encoder) Salt() string { return e.salt } // NewSSHA384Encoder returns a new salted SHA384 Encoder. func NewSSHA384Encoder(salt string) CryptSaltedEncoder { return &ssha384Encoder{ salt: salt, } } type sha512Encoder struct{} func (e *sha512Encoder) Encode(pass []byte, hash interface{}) []byte { h := sha512.Sum512(pass) return h[:] } // NewSHA512Encoder returns a new SHA512 Encoder. func NewSHA512Encoder() CryptEncoder { return &sha512Encoder{} } type ssha512Encoder struct { salt string } func (e *ssha512Encoder) Encode(pass []byte, hash interface{}) []byte { s := []byte(e.salt) p := append(pass, s...) h := sha512.Sum512(p) return h[:] } func (e *ssha512Encoder) Salt() string { return e.salt } // NewSSHA384Encoder returns a new salted SHA512 Encoder. func NewSSHA512Encoder(salt string) CryptSaltedEncoder { return &ssha512Encoder{ salt: salt, } } // EOF