---
title: "Encrypt PDF Search Database on iOS | Nutrient SDK"
canonical_url: "https://www.nutrient.io/guides/ios/security/encryption-in-pdflibrary/"
md_url: "https://www.nutrient.io/guides/ios/security/encryption-in-pdflibrary.md"
last_updated: "2026-05-19T18:11:33.963Z"
description: "Learn to encrypt your SQLite database in iOS using PSPDFKit with SQLCipher or SQLite Encryption Extension for enhanced data security. Secure your application today!"
---

# Encrypt the PDF Search Database on iOS

By default, SQLite databases created by PSPDFKit aren’t encrypted, but they’re still protected by iOS data protection, just like all the data in an application is. If you need to add a level of security, there are SQLite extensions that enable database encryption. These extensions encrypt database content and SQLite metadata.

One such extension is the [SQLite Encryption Extension](https://www.sqlite.org/see/doc/trunk/www/index.wiki). This extension requires an SEE license.

Another alternative implementation is [SQLCipher](https://www.zetetic.net/sqlcipher/), which is an open source project with a [BSD-style license](https://www.zetetic.net/sqlcipher/license/). To integrate SQLCipher, follow the instructions for either the [commercial edition](https://www.zetetic.net/sqlcipher/commercial/) or the [community edition](https://www.zetetic.net/sqlcipher/sqlcipher-apple-community/).

You can read more about how PSPDFKit integrates with your custom SQLite library [in the relevant guide](https://www.nutrient.io/guides/ios/miscellaneous/custom-sqlite-library.md).

## Encrypting PSPDFKit Databases

SQLite database encryption is currently supported by [`PDFLibrary`](https://www.nutrient.io/api/ios/documentation/pspdfkit/pdflibrary). This guide outlines how to enable the encryption feature. If encryption is enabled, the main database will be encrypted.

### Step 1 — Registering a DatabaseEncryptionProvider Implementation

The standard SQLite library doesn’t support encryption out of the box. You therefore have to integrate a third-party option into your codebase. [`DatabaseEncryptionProvider`](https://www.nutrient.io/api/ios/documentation/pspdfkit/sdk/databaseencryptionprovider) acts as a bridge between this third-party code and [`PDFLibrary`](https://www.nutrient.io/api/ios/documentation/pspdfkit/pdflibrary). We’ll use [SQLCipher](https://www.zetetic.net/sqlcipher/) as an example, but the implementation should be similar — if not identical — for other providers.

To integrate SQLCipher, follow the instructions for either the [commercial edition](https://www.zetetic.net/sqlcipher/commercial/) or the [community edition](https://www.zetetic.net/sqlcipher/sqlcipher-apple-community/).

Once SQLCipher is correctly set up, you have to add an implementation of the [`DatabaseEncryptionProvider`](https://www.nutrient.io/api/ios/documentation/pspdfkit/sdk/databaseencryptionprovider) protocol. For SQLCipher, the implementation will look like this:

### SWIFT

```swift

class YourEncryptionProvider: NSObject, DatabaseEncryptionProvider {

    public func encryptDatabase(_ db: UnsafeMutableRawPointer, withKey keyData: Data) -> Bool {
        let data = keyData as NSData
        assert(data.length == 32, "Danger: key is 32 byte long, hence it will not be pbkdf2'ed by SQLCipher!")
        let error = sqlite3_key(OpaquePointer(db), data.bytes, Int32(data.length))
        return error == SQLITE_OK
    }

    public func reEncryptDatabase(_ db: UnsafeMutableRawPointer, withKey keyData: Data) -> Bool {
        let data = keyData as NSData
        assert(data.length == 32, "Danger: key is 32 byte long, hence it will not be pbkdf2'ed by SQLCipher!")
        let error = sqlite3_rekey(OpaquePointer(db), data.bytes, Int32(data.length))
        return error == SQLITE_OK
    }
}

```

### OBJECTIVE-C

```objc

@interface YourEncryptionProvider : NSObject <PSPDFDatabaseEncryptionProvider>
@end

@implementation YourEncryptionProvider

- (BOOL)encryptDatabase:(void *)db withKey:(NSData *)keyData {
  NSAssert([keyData length] == 32, @"Danger: key is 32 byte long, hence it will not be pbkdf2'ed by SQLCipher!");
  int err = sqlite3_key(db, [keyData bytes], (int)[keyData length]);
  return (err == SQLITE_OK);
}

- (BOOL)reEncryptDatabase:(void *)db withKey:(NSData *)keyData {
  NSAssert([keyData length] == 32, @"Danger: key is 32 byte long, hence it will not be pbkdf2'ed by SQLCipher!");
  int err = sqlite3_rekey(db, [keyData bytes], (int)[keyData length]);
  return (err == SQLITE_OK);
}
@end

```

Finally, you must register your encryption provider with PSPDFKit. To do so, set the [`databaseEncryptionProvider`](https://www.nutrient.io/api/ios/documentation/pspdfkit/sdk/databaseencryptionprovider) property on [`SDK`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/pspdfkit/sdk/application). You have to do this early on. We recommend the following setup code:

### SWIFT

```swift

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    SDK.setLicenseKey("YOUR_LICENSE_KEY_GOES_HERE")
    SDK.sharedInstance.databaseEncryptionProvider = YourEncryptionProvider()

    return true
}

```

### OBJECTIVE-C

```objc

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [PSPDFKitGlobal setLicenseKey:@"YOUR_LICENSE_KEY_GOES_HERE"];
  PSPDFKitGlobal.sharedInstance.databaseEncryptionProvider = [YourEncryptionProvider new];

  return YES;
}

```

That’s it. PSPDFKit is now configured to support encryption.

### Step 2 — Using an Encrypted PDFLibrary

To use an encrypted [`PDFLibrary`](https://www.nutrient.io/api/ios/documentation/pspdfkit/pdflibrary), call the [`PDFLibrary.encryptedLibrary(withPath:encryptionKeyProvider:error:)`](https://www.nutrient.io/api/ios/documentation/pspdfkit/pdflibrary/encryptedlibrary(withpath:encryptionkeyprovider:error:)) factory method. The first argument is a path to a directory of your choice. The second parameter is the so-called encryption key provider. An encryption key provider is a simple block that returns the key in the form of an `NSData` instance. The provider block will be called whenever the library needs access to the encryption key. This ensures we only keep the encryption key in memory for a short amount of time. Your encryption key provider implementation should always fetch the key from secure storage, e.g. Apple’s keychain. Your key provider implementation should also be free from side effects in the sense that it should always return the same key on every call.

> **❗Important:** Depending on the driver you chose, there might be different requirements for the key provided by the encryption key provider block!

PSPDFKit doesn’t process the key in any way, rather it passes it directly to your [`DatabaseEncryptionProvider`](https://www.nutrient.io/api/ios/documentation/pspdfkit/sdk/databaseencryptionprovider) implementation. For example, if you use SQLCipher, your key will be treated as a passphrase. By default, SQLCipher will derive a key by using PBKDF2 with 64,000 iterations. However, if the key is exactly 32-bytes long, it’ll be used directly as the encryption key. Other drivers might have similar pitfalls, so be cautious and read the applicable documentation!

The returned instance of the factory is either `nil` or an encrypted [`PDFLibrary`](https://www.nutrient.io/api/ios/documentation/pspdfkit/pdflibrary) instance. `nil` is returned if the path points to an existing library that either isn’t encrypted or is encrypted with a different key. Otherwise, a new instance of [`PDFLibrary`](https://www.nutrient.io/api/ios/documentation/pspdfkit/pdflibrary), with the [`PDFLibrary.isEncrypted`](https://www.nutrient.io/api/ios/documentation/pspdfkit/pdflibrary/isencrypted) flag set to `true`, will be returned. Once this is done, you can use the library as usual.

### Step 3 — Using an Encrypted Library by Default (Optional)

You can override the default library. To do so, create a library (either encrypted or unencrypted) and call `SDK.sharedInstance.library = yourCustomLibrary`. Note that you should do this early on, e.g. in `application(_:didFinishLaunchingWithOptions:)`. If you change the [`library`](https://www.nutrient.io/api/ios/documentation/pspdfkit/sdk/library) property later in your app’s lifecycle, some parts of [`SDK`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/pspdfkit/sdk/application) might still use the previous instance!

### Step 4 — Verifying the Encryption (Optional)

Always ensure your library is properly encrypted. An easy way to do this is the `hexdump` command. Run `hexdump -C /path/to/your/encrypted/library/index.sqlite`. If the database is encrypted, the output should contain no human-readable text. You can also use the `sqlite3` command to attempt to read from an encrypted library.
---

## Related pages

- [Indexing PDF Documents on iOS](/guides/ios/features/indexed-full-text-search.md)
- [Custom Tokenizers for PDF Search on iOS](/guides/ios/memory-and-storage/using-custom-tokenizers.md)
- [Adding a Custom SQLite Library for PDF Search on iOS](/guides/ios/miscellaneous/custom-sqlite-library.md)
- [Generate PDF Search Previews on iOS](/guides/ios/search/indexed-full-text-search/customize-results.md)
- [PDF Search Matching Options on iOS](/guides/ios/search/indexed-full-text-search/matching-options.md)
- [Index and Search PDFs Using iOS Spotlight](/guides/ios/search/indexed-full-text-search/spotlight-indexing.md)

