Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7337e65

Browse files
ADD: User Authentication Password Encoders
Allow user to choose how to encode passwords with connection string overrides of embedded `sqlite_crypt` function.
1 parent 9b30110 commit 7337e65

File tree

3 files changed

+422
-0
lines changed

3 files changed

+422
-0
lines changed

‎sqlite3.go‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,8 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
894894
authCreate := false
895895
authUser := ""
896896
authPass := ""
897+
authCrypt := ""
898+
authSalt := ""
897899
mutex := C.int(C.SQLITE_OPEN_FULLMUTEX)
898900
txlock := "BEGIN"
899901

@@ -929,6 +931,12 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
929931
if val := params.Get("_auth_pass"); val != "" {
930932
authPass = val
931933
}
934+
if val := params.Get("_auth_crypt"); val != "" {
935+
authCrypt = val
936+
}
937+
if val := params.Get("_auth_salt"); val != "" {
938+
authSalt = val
939+
}
932940

933941
// _loc
934942
if val := params.Get("_loc"); val != "" {
@@ -1287,6 +1295,56 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
12871295
// Create connection to SQLite
12881296
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
12891297

1298+
// Password Cipher has to be registerd before authentication
1299+
if len(authCrypt) > 0 {
1300+
switch strings.ToUpper(authCrypt) {
1301+
case "SHA1":
1302+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA1, true); err != nil {
1303+
return nil, fmt.Errorf("CryptEncoderSHA1: %s", err)
1304+
}
1305+
case "SSHA1":
1306+
if len(authSalt) == 0 {
1307+
return nil, fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt")
1308+
}
1309+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA1(authSalt), true); err != nil {
1310+
return nil, fmt.Errorf("CryptEncoderSSHA1: %s", err)
1311+
}
1312+
case "SHA256":
1313+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA256, true); err != nil {
1314+
return nil, fmt.Errorf("CryptEncoderSHA256: %s", err)
1315+
}
1316+
case "SSHA256":
1317+
if len(authSalt) == 0 {
1318+
return nil, fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt")
1319+
}
1320+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA256(authSalt), true); err != nil {
1321+
return nil, fmt.Errorf("CryptEncoderSSHA256: %s", err)
1322+
}
1323+
case "SHA384":
1324+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA384, true); err != nil {
1325+
return nil, fmt.Errorf("CryptEncoderSHA384: %s", err)
1326+
}
1327+
case "SSHA384":
1328+
if len(authSalt) == 0 {
1329+
return nil, fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt")
1330+
}
1331+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA384(authSalt), true); err != nil {
1332+
return nil, fmt.Errorf("CryptEncoderSSHA384: %s", err)
1333+
}
1334+
case "SHA512":
1335+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA512, true); err != nil {
1336+
return nil, fmt.Errorf("CryptEncoderSHA512: %s", err)
1337+
}
1338+
case "SSHA512":
1339+
if len(authSalt) == 0 {
1340+
return nil, fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt")
1341+
}
1342+
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA512(authSalt), true); err != nil {
1343+
return nil, fmt.Errorf("CryptEncoderSSHA512: %s", err)
1344+
}
1345+
}
1346+
}
1347+
12901348
// Preform Authentication
12911349
if err := conn.Authenticate(authUser, authPass); err != nil {
12921350
return nil, err

‎sqlite3_func_crypt.go‎

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
2+
//
3+
// Use of this source code is governed by an MIT-style
4+
// license that can be found in the LICENSE file.
5+
6+
package sqlite3
7+
8+
import (
9+
"crypto/sha1"
10+
"crypto/sha256"
11+
"crypto/sha512"
12+
)
13+
14+
// This file provides several different implementations for the
15+
// default embedded sqlite_crypt function.
16+
// This function is uses a ceasar-cypher by default
17+
// and is used within the UserAuthentication module to encode
18+
// the password.
19+
//
20+
// The provided functions can be used as an overload to the sqlite_crypt
21+
// function through the use of the RegisterFunc on the connection.
22+
//
23+
// Because the functions can serv a purpose to an end-user
24+
// without using the UserAuthentication module
25+
// the functions are default compiled in.
26+
//
27+
// From SQLITE3 - user-auth.txt
28+
// The sqlite_user.pw field is encoded by a built-in SQL function
29+
// "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
30+
// is the plaintext password supplied to the sqlite3_user_authenticate()
31+
// interface. The second argument is the sqlite_user.pw value and is supplied
32+
// so that the function can extract the "salt" used by the password encoder.
33+
// The result of sqlite_crypt(X,Y) is another blob which is the value that
34+
// ends up being stored in sqlite_user.pw. To verify credentials X supplied
35+
// by the sqlite3_user_authenticate() routine, SQLite runs:
36+
//
37+
// sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
38+
//
39+
// To compute an appropriate sqlite_user.pw value from a new or modified
40+
// password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
41+
// when the second argument is NULL.
42+
//
43+
// The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
44+
// which prevents passwords from being revealed by searching the raw database
45+
// for ASCII text, but is otherwise trivally broken. For better password
46+
// security, the database should be encrypted using the SQLite Encryption
47+
// Extension or similar technology. Or, the application can use the
48+
// sqlite3_create_function() interface to provide an alternative
49+
// implementation of sqlite_crypt() that computes a stronger password hash,
50+
// perhaps using a cryptographic hash function like SHA1.
51+
52+
// CryptEncoderSHA1 encodes a password with SHA1
53+
func CryptEncoderSHA1(pass []byte, hash interface{}) []byte {
54+
h := sha1.Sum(pass)
55+
return h[:]
56+
}
57+
58+
// CryptEncoderSSHA1 encodes a password with SHA1 with the
59+
// configured salt.
60+
func CryptEncoderSSHA1(salt string) func(pass []byte, hash interface{}) []byte {
61+
return func(pass []byte, hash interface{}) []byte {
62+
s := []byte(salt)
63+
p := append(pass, s...)
64+
h := sha1.Sum(p)
65+
return h[:]
66+
}
67+
}
68+
69+
// CryptEncoderSHA256 encodes a password with SHA256
70+
func CryptEncoderSHA256(pass []byte, hash interface{}) []byte {
71+
h := sha256.Sum256(pass)
72+
return h[:]
73+
}
74+
75+
// CryptEncoderSSHA256 encodes a password with SHA256
76+
// with the configured salt
77+
func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte {
78+
return func(pass []byte, hash interface{}) []byte {
79+
s := []byte(salt)
80+
p := append(pass, s...)
81+
h := sha256.Sum256(p)
82+
return h[:]
83+
}
84+
}
85+
86+
// CryptEncoderSHA384 encodes a password with SHA256
87+
func CryptEncoderSHA384(pass []byte, hash interface{}) []byte {
88+
h := sha512.Sum384(pass)
89+
return h[:]
90+
}
91+
92+
// CryptEncoderSSHA384 encodes a password with SHA256
93+
// with the configured salt
94+
func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte {
95+
return func(pass []byte, hash interface{}) []byte {
96+
s := []byte(salt)
97+
p := append(pass, s...)
98+
h := sha512.Sum384(p)
99+
return h[:]
100+
}
101+
}
102+
103+
// CryptEncoderSHA512 encodes a password with SHA256
104+
func CryptEncoderSHA512(pass []byte, hash interface{}) []byte {
105+
h := sha512.Sum512(pass)
106+
return h[:]
107+
}
108+
109+
// CryptEncoderSSHA512 encodes a password with SHA256
110+
// with the configured salt
111+
func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte {
112+
return func(pass []byte, hash interface{}) []byte {
113+
s := []byte(salt)
114+
p := append(pass, s...)
115+
h := sha512.Sum512(p)
116+
return h[:]
117+
}
118+
}
119+
120+
// EOF

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /