@@ -224,6 +224,14 @@ static void setTextMode(FILE *file, int isOutput){
224224/* True if the timer is enabled */
225225static int enableTimer = 0;
226226
227+ #ifdef SQLITE_HAS_CODEC
228+ /* Database encryption support
229+ * Types were defined according to sqlite3_key() prototype.
230+ */
231+ static void *encryption_key = NULL;
232+ static int encryption_key_length = 0;
233+ #endif
234+
227235/* Return the current wall-clock time */
228236static sqlite3_int64 timeOfDay(void){
229237 static sqlite3_vfs *clockVfs = 0;
@@ -12664,6 +12672,14 @@ static void open_db(ShellState *p, int openFlags){
1266412672 }
1266512673 }
1266612674 globalDb = p->db;
12675+
12676+ #ifdef SQLITE_HAS_CODEC
12677+ if (encryption_key != NULL) {
12678+ sqlite3_activate_see("7bb07b8d471d642e");
12679+ sqlite3_key(p->db, encryption_key, encryption_key_length);
12680+ }
12681+ #endif
12682+
1266712683 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
1266812684 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
1266912685 p->zDbFilename, sqlite3_errmsg(p->db));
@@ -18388,6 +18404,9 @@ static const char zOptions[] =
1838818404#ifdef SQLITE_ENABLE_VFSTRACE
1838918405 " -vfstrace enable tracing of all VFS calls\n"
1839018406#endif
18407+ #ifdef SQLITE_HAS_CODEC
18408+ " -key hexvalue set encryption key (hexadecimal, no quotes)\n"
18409+ #endif
1839118410#ifdef SQLITE_HAVE_ZLIB
1839218411 " -zip open the file as a ZIP Archive\n"
1839318412#endif
@@ -18684,6 +18703,56 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
1868418703#endif
1868518704 }else if( strcmp(z,"-readonly")==0 ){
1868618705 data.openMode = SHELL_OPEN_READONLY;
18706+
18707+ }else if (strcmp(argv[i], "-key") == 0) {
18708+ #ifdef SQLITE_HAS_CODEC
18709+ /* Process hex key from command-line.
18710+ ** Message to SQLite developers: your parsers are NOT robust!
18711+ */
18712+ unsigned int idx;
18713+ unsigned int tmpLength;
18714+
18715+ i++;
18716+ /* compute key length */
18717+ idx = i;
18718+ while ((argv[i][idx] != ' ') && (argv[i][idx] != '\x00')) {
18719+ char c = (argv[i][idx]);
18720+ if (!((isdigit(c)) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')))) {
18721+ fprintf(stderr, "Expecting hexadecimal values for encryption key!\r\n");
18722+ return 1;
18723+ }
18724+ idx++;
18725+ }
18726+ tmpLength = idx;
18727+ if ((tmpLength % 2) != 0) {
18728+ fprintf(stderr, "Expecting an even number of characters for encryption key!\r\n");
18729+ return 1;
18730+ }
18731+
18732+ /* allocate key memory */
18733+ encryption_key_length = tmpLength / 2;
18734+ encryption_key = malloc(encryption_key_length);
18735+ if (encryption_key == NULL) {
18736+ fprintf(stderr, "Out of memory!\r\n");
18737+ return 1;
18738+ }
18739+
18740+ /* convert hex string into values */
18741+ idx = 0;
18742+ while ((argv[i][idx] != ' ') && (argv[i][idx] != '\x00')) {
18743+ char hex[3];
18744+ hex[0] = (argv[i][idx++]);
18745+ hex[1] = (argv[i][idx++]);
18746+ hex[2] = '\x00';
18747+
18748+ ((unsigned char*)encryption_key)[(idx - 2) / 2] = (unsigned char)(0xFF & strtoul(hex, NULL, 16));
18749+ }
18750+ #else
18751+ fprintf(stderr, "Sorry, encryption support is not available\r\n");
18752+ fprintf(stderr, "HINT: define 'SQLITE_HAS_CODEC' at compile time\r\n");
18753+ return 1;
18754+ #endif
18755+
1868718756#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
1868818757 }else if( strncmp(z, "-A",2)==0 ){
1868918758 /* All remaining command-line arguments are passed to the ".archive"
@@ -18879,6 +18948,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
1887918948 if( bail_on_error ) return rc;
1888018949 }
1888118950 }
18951+
18952+ #ifdef SQLITE_HAS_CODEC
18953+ }
18954+ else if (strcmp(z, "-key") == 0) {
18955+ /* encryption key has already been set */
18956+ i++;
18957+ #endif
18958+
1888218959#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
1888318960 }else if( strncmp(z, "-A", 2)==0 ){
1888418961 if( nCmd>0 ){
@@ -18985,6 +19062,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
1898519062 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
1898619063 free(argvToFree);
1898719064#endif
19065+
19066+ #ifdef SQLITE_HAS_CODEC
19067+ if (encryption_key != NULL) {
19068+ free(encryption_key);
19069+ encryption_key = NULL;
19070+ }
19071+ #endif
19072+
1898819073 /* Clear the global data structure so that valgrind will detect memory
1898919074 ** leaks */
1899019075 memset(&data, 0, sizeof(data));
0 commit comments