Separate encryption/decryption logic for different frameworks used
This commit is contained in:
parent
e2201ffa52
commit
730542d5bb
24 changed files with 428 additions and 414 deletions
57
passKit/Crypto/GopenPgp.swift
Normal file
57
passKit/Crypto/GopenPgp.swift
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// GopenPgp.swift
|
||||
// passKit
|
||||
//
|
||||
// Created by Danny Moesch on 08.09.19.
|
||||
// Copyright © 2019 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import Crypto
|
||||
|
||||
struct GopenPgp: PgpInterface {
|
||||
|
||||
private let publicKey: CryptoKeyRing
|
||||
private let privateKey: CryptoKeyRing
|
||||
|
||||
init(publicArmoredKey: String, privateArmoredKey: String) throws {
|
||||
guard let pgp = CryptoGetGopenPGP() else {
|
||||
throw AppError.KeyImport
|
||||
}
|
||||
publicKey = try pgp.buildKeyRingArmored(publicArmoredKey)
|
||||
privateKey = try pgp.buildKeyRingArmored(privateArmoredKey)
|
||||
}
|
||||
|
||||
func decrypt(encryptedData: Data, passphrase: String) throws -> Data? {
|
||||
try privateKey.unlock(withPassphrase: passphrase)
|
||||
let message = createPgpMessage(from: encryptedData)
|
||||
return try privateKey.decrypt(message, verifyKey: nil, verifyTime: 0).data
|
||||
}
|
||||
|
||||
func encrypt(plainData: Data) throws -> Data {
|
||||
let encryptedData = try publicKey.encrypt(CryptoNewPlainMessage(plainData.mutable as Data), privateKey: nil)
|
||||
if SharedDefaults[.encryptInArmored] {
|
||||
var error: NSError?
|
||||
let armor = encryptedData.getArmored(&error)
|
||||
guard error == nil else {
|
||||
throw error!
|
||||
}
|
||||
return armor.data(using: .ascii)!
|
||||
}
|
||||
return encryptedData.getBinary()!
|
||||
}
|
||||
|
||||
var keyId: String {
|
||||
var error: NSError?
|
||||
let fingerprint = publicKey.getFingerprint(&error)
|
||||
return error == nil ? String(fingerprint.suffix(8)).uppercased() : ""
|
||||
}
|
||||
|
||||
private func createPgpMessage(from encryptedData: Data) -> CryptoPGPMessage? {
|
||||
if SharedDefaults[.encryptInArmored] {
|
||||
var error: NSError?
|
||||
let message = CryptoNewPGPMessageFromArmored(String(data: encryptedData, encoding: .ascii), &error)
|
||||
return error == nil ? message : nil
|
||||
}
|
||||
return CryptoNewPGPMessage(encryptedData.mutable as Data)
|
||||
}
|
||||
}
|
||||
48
passKit/Crypto/ObjectivePgp.swift
Normal file
48
passKit/Crypto/ObjectivePgp.swift
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// ObjectivePgp.swift
|
||||
// passKit
|
||||
//
|
||||
// Created by Danny Moesch on 08.09.19.
|
||||
// Copyright © 2019 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import ObjectivePGP
|
||||
|
||||
struct ObjectivePgp: PgpInterface {
|
||||
|
||||
private let publicKey: Key
|
||||
private let privateKey: Key
|
||||
|
||||
private let keyring = ObjectivePGP.defaultKeyring
|
||||
|
||||
init(publicArmoredKey: String, privateArmoredKey: String) throws {
|
||||
guard let publicKeyData = publicArmoredKey.data(using: .ascii), let privateKeyData = privateArmoredKey.data(using: .ascii) else {
|
||||
throw AppError.KeyImport
|
||||
}
|
||||
let publicKeys = try ObjectivePGP.readKeys(from: publicKeyData)
|
||||
let privateKeys = try ObjectivePGP.readKeys(from: privateKeyData)
|
||||
keyring.import(keys: publicKeys)
|
||||
keyring.import(keys: privateKeys)
|
||||
guard let publicKey = publicKeys.first, let privateKey = privateKeys.first else {
|
||||
throw AppError.KeyImport
|
||||
}
|
||||
self.publicKey = publicKey
|
||||
self.privateKey = privateKey
|
||||
}
|
||||
|
||||
func decrypt(encryptedData: Data, passphrase: String) throws -> Data? {
|
||||
return try ObjectivePGP.decrypt(encryptedData, andVerifySignature: false, using: keyring.keys) { _ in passphrase }
|
||||
}
|
||||
|
||||
func encrypt(plainData: Data) throws -> Data {
|
||||
let encryptedData = try ObjectivePGP.encrypt(plainData, addSignature: false, using: keyring.keys, passphraseForKey: nil)
|
||||
if SharedDefaults[.encryptInArmored] {
|
||||
return Armor.armored(encryptedData, as: .message).data(using: .ascii)!
|
||||
}
|
||||
return encryptedData
|
||||
}
|
||||
|
||||
var keyId: String {
|
||||
return publicKey.keyID.shortIdentifier
|
||||
}
|
||||
}
|
||||
64
passKit/Crypto/PGPAgent.swift
Normal file
64
passKit/Crypto/PGPAgent.swift
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// PGPAgent.swift
|
||||
// passKit
|
||||
//
|
||||
// Created by Yishi Lin on 2019/7/17.
|
||||
// Copyright © 2019 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
public class PGPAgent {
|
||||
|
||||
public static let shared: PGPAgent = PGPAgent()
|
||||
|
||||
private let keyStore: KeyStore
|
||||
private var pgpInterface: PgpInterface?
|
||||
|
||||
public init(keyStore: KeyStore = AppKeychain.shared) {
|
||||
self.keyStore = keyStore
|
||||
}
|
||||
|
||||
public func initKeys() throws {
|
||||
guard let publicKey: String = keyStore.get(for: PgpKey.PUBLIC.getKeychainKey()),
|
||||
let privateKey: String = keyStore.get(for: PgpKey.PRIVATE.getKeychainKey()) else {
|
||||
throw AppError.KeyImport
|
||||
}
|
||||
do {
|
||||
pgpInterface = try GopenPgp(publicArmoredKey: publicKey, privateArmoredKey: privateKey)
|
||||
} catch {
|
||||
pgpInterface = try ObjectivePgp(publicArmoredKey: publicKey, privateArmoredKey: privateKey)
|
||||
}
|
||||
}
|
||||
|
||||
public func uninitKeys() {
|
||||
pgpInterface = nil
|
||||
}
|
||||
|
||||
public var keyId: String? {
|
||||
return pgpInterface?.keyId
|
||||
}
|
||||
|
||||
public func decrypt(encryptedData: Data, requestPGPKeyPassphrase: () -> String) throws -> Data? {
|
||||
try checkAndInit()
|
||||
let passphrase = keyStore.get(for: Globals.pgpKeyPassphrase) ?? requestPGPKeyPassphrase()
|
||||
return try pgpInterface!.decrypt(encryptedData: encryptedData, passphrase: passphrase)
|
||||
}
|
||||
|
||||
public func encrypt(plainData: Data) throws -> Data {
|
||||
try checkAndInit()
|
||||
guard let pgpInterface = pgpInterface else {
|
||||
throw AppError.Encryption
|
||||
}
|
||||
return try pgpInterface.encrypt(plainData: plainData)
|
||||
}
|
||||
|
||||
public var isPrepared: Bool {
|
||||
return keyStore.contains(key: PgpKey.PUBLIC.getKeychainKey())
|
||||
&& keyStore.contains(key: PgpKey.PRIVATE.getKeychainKey())
|
||||
}
|
||||
|
||||
private func checkAndInit() throws {
|
||||
if pgpInterface == nil || !keyStore.contains(key: Globals.pgpKeyPassphrase) {
|
||||
try initKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
16
passKit/Crypto/PgpInterface.swift
Normal file
16
passKit/Crypto/PgpInterface.swift
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// PgpInterface.swift
|
||||
// passKit
|
||||
//
|
||||
// Created by Danny Moesch on 08.09.19.
|
||||
// Copyright © 2019 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
protocol PgpInterface {
|
||||
|
||||
func decrypt(encryptedData: Data, passphrase: String) throws -> Data?
|
||||
|
||||
func encrypt(plainData: Data) throws -> Data
|
||||
|
||||
var keyId: String { get }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue