@@ -31,6 +31,26 @@ extension Connection {
3131 try _key_v2 ( db: db, keyPointer: key. bytes, keySize: key. bytes. count)
3232 }
3333
34+ /// Same as `key(_ key: String, db: String = "main")`, running "PRAGMA cipher_migrate;"
35+ /// immediately after calling `sqlite3_key_v2`, which performs the migration of
36+ /// SQLCipher database created by older major version of SQLCipher, to be able to
37+ /// open this database with new major version of SQLCipher
38+ /// (e.g. to open database created by SQLCipher version 3.x.x with SQLCipher version 4.x.x).
39+ /// As "PRAGMA cipher_migrate;" is time-consuming, it is recommended to use this function
40+ /// only after failure of `key(_ key: String, db: String = "main")`, if older versions of
41+ /// your app may ise older version of SQLCipher
42+ /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_migrate
43+ /// and https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283
44+ /// for more details regarding SQLCipher upgrade
45+ public func keyAndMigrate( _ key: String , db: String = " main " ) throws {
46+ try _key_v2 ( db: db, keyPointer: key, keySize: key. utf8. count, migrate: true )
47+ }
48+
49+ /// Same as `[`keyAndMigrate(_ key: String, db: String = "main")` accepting byte array as key
50+ public func keyAndMigrate( _ key: Blob , db: String = " main " ) throws {
51+ try _key_v2 ( db: db, keyPointer: key. bytes, keySize: key. bytes. count, migrate: true )
52+ }
53+
3454 /// Change the key on an open database. If the current database is not encrypted, this routine
3555 /// will encrypt it.
3656 /// To change the key on an existing encrypted database, it must first be unlocked with the
@@ -45,8 +65,20 @@ extension Connection {
4565 }
4666
4767 // MARK: - private
48- private func _key_v2( db: String , keyPointer: UnsafePointer < UInt8 > , keySize: Int ) throws {
68+ private func _key_v2( db: String ,
69+ keyPointer: UnsafePointer < UInt8 > ,
70+ keySize: Int ,
71+ migrate: Bool = false ) throws {
4972 try check ( sqlite3_key_v2 ( handle, db, keyPointer, Int32 ( keySize) ) )
73+ if migrate {
74+ // Run "PRAGMA cipher_migrate;" immediately after `sqlite3_key_v2`
75+ // per recommendation of SQLCipher authors
76+ let migrateResult = try scalar ( " PRAGMA cipher_migrate; " )
77+ if ( migrateResult as? String ) != " 0 " {
78+ // "0" is the result of successfull migration
79+ throw Result . error ( message: " Error in cipher migration, result \( migrateResult. debugDescription) " , code: 1 , statement: nil )
80+ }
81+ }
5082 try cipher_key_check ( )
5183 }
5284
0 commit comments