passforios/passKit/Crypto/GopenPgp.swift

98 lines
3.2 KiB
Swift
Raw Normal View History

//
// GopenPgp.swift
// passKit
//
// Created by Danny Moesch on 08.09.19.
// Copyright © 2019 Bob Sun. All rights reserved.
//
import Crypto
struct GopenPgp: PgpInterface {
private static let errorMapping: [String: Error] = [
2020-04-11 23:23:38 -07:00
"gopenpgp: error in unlocking key: openpgp: invalid data: private key checksum failure": AppError.WrongPassphrase,
"openpgp: incorrect key": AppError.KeyExpiredOrIncompatible,
]
2020-04-11 23:23:38 -07:00
private let publicKey: CryptoKey
private let privateKey: CryptoKey
init(publicArmoredKey: String, privateArmoredKey: String) throws {
2019-11-08 21:13:28 +01:00
var error: NSError?
2020-04-11 23:23:38 -07:00
guard let publicKey = CryptoNewKeyFromArmored(publicArmoredKey, &error),
let privateKey = CryptoNewKeyFromArmored(privateArmoredKey, &error) else {
guard error == nil else {
throw error!
}
throw AppError.KeyImport
}
2019-11-08 21:13:28 +01:00
self.publicKey = publicKey
self.privateKey = privateKey
}
2020-04-11 23:23:38 -07:00
func decrypt(encryptedData: Data, keyID: String, passphrase: String) throws -> Data? {
do {
2020-04-11 23:23:38 -07:00
let unlockedKey = try privateKey.unlock(passphrase.data(using: .utf8))
var error: NSError?
guard let keyRing = CryptoNewKeyRing(unlockedKey, &error) else {
guard error == nil else {
throw error!
}
throw AppError.Decryption
}
let message = createPgpMessage(from: encryptedData)
return try keyRing.decrypt(message, verifyKey: nil, verifyTime: 0).data
} catch {
throw Self.errorMapping[error.localizedDescription, default: error]
}
}
2020-04-11 23:23:38 -07:00
func encrypt(plainData: Data, keyID: String) throws -> Data {
var error: NSError?
guard let keyRing = CryptoNewKeyRing(publicKey, &error) else {
guard error == nil else {
throw error!
}
throw AppError.Encryption
}
let encryptedData = try keyRing.encrypt(CryptoNewPlainMessage(plainData.mutable as Data), privateKey: nil)
if Defaults.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?
2020-04-11 23:23:38 -07:00
let fingerprint = publicKey.getHexKeyID()
return String(fingerprint).uppercased()
}
var shortKeyId: String {
var error: NSError?
let fingerprint = publicKey.getHexKeyID()
return String(fingerprint.suffix(8)).uppercased()
}
private func createPgpMessage(from encryptedData: Data) -> CryptoPGPMessage? {
2019-09-30 00:12:54 +08:00
// Important note:
// Even if Defaults.encryptInArmored is true now, it could be different during the encryption.
2019-09-30 00:12:54 +08:00
var error: NSError?
let message = CryptoNewPGPMessageFromArmored(String(data: encryptedData, encoding: .ascii), &error)
if error == nil {
return message
}
return CryptoNewPGPMessage(encryptedData.mutable as Data)
}
}