From 47a909ccc1ceab8d195ef9eb1a063e8cbbb6924d Mon Sep 17 00:00:00 2001 From: Oliver Wiese <oliver.wiese@fu-berlin.de> Date: Wed, 27 Sep 2017 10:45:40 +0200 Subject: [PATCH] update ObjectivePGP --- NSData+PGPUtils.h | 27 - NSData+PGPUtils.m | 358 ----- NSData+compression.h | 20 - NSValue+PGPUtils.h | 15 - NSValue+PGPUtils.m | 24 - ObjectivePGP.h | 64 - ObjectivePGP.m | 1175 ----------------- PGPArmor.h | 31 - PGPCryptoCFB.h | 25 - PGPCryptoUtils.h | 18 - PGPKey.h | 71 - PGPKey.m | 496 ------- PGPKeyID.h | 26 - PGPKeyID.m | 104 -- PGPLiteralPacket.h | 28 - PGPMPI.h | 26 - PGPMPI.m | 101 -- PGPOnePassSignaturePacket.h | 20 - PGPPacket.h | 34 - PGPPacket.m | 317 ----- PGPPublicKeyEncryptedSessionKeyPacket.h | 22 - PGPPublicKeyPacket.h | 39 - PGPPublicKeyPacket.m | 324 ----- PGPPublicKeyRSA.h | 24 - PGPPublicKeyRSA.m | 248 ---- PGPS2K.h | 28 - PGPS2K.m | 220 --- PGPSecretKeyPacket.h | 33 - PGPSecretKeyPacket.m | 444 ------- PGPSignaturePacket.h | 68 - PGPSignaturePacket.m | 806 ----------- PGPSignatureSubpacket.h | 33 - PGPSubKey.h | 23 - PGPSubKey.m | 51 - ...llyEncryptedIntegrityProtectedDataPacket.h | 20 - PGPTypes.h | 180 --- PGPUser.h | 28 - PGPUserAttributePacket.m | 82 -- PGPUserIDPacket.h | 17 - PGPUserIDPacket.m | 49 - enzevalos_iphone.xcodeproj/project.pbxproj | 629 +++++---- enzevalos_iphone/CryptoObject.swift | 49 + enzevalos_iphone/Cryptography.swift | 22 + enzevalos_iphone/DecryptedData.swift | 43 - enzevalos_iphone/Encryption.swift | 120 -- enzevalos_iphone/EncryptionHandler.swift | 33 - enzevalos_iphone/EncryptionType.swift | 44 - .../EnzevalosEncryptionHandler.swift | 176 --- enzevalos_iphone/KeyViewController.swift | 2 - enzevalos_iphone/KeyWrapper.swift | 35 - .../ObjectivePGP/CryptoBox/PGPCryptoHash.h | 26 + .../ObjectivePGP/CryptoBox/PGPCryptoHash.m | 75 ++ .../ObjectivePGP/CryptoBox/PGPCryptoUtils.h | 26 + .../ObjectivePGP/CryptoBox/PGPCryptoUtils.m | 59 +- .../ObjectivePGP/CryptoBox/PGPDSA.h | 31 + .../ObjectivePGP/CryptoBox/PGPDSA.m | 156 +++ .../ObjectivePGP/CryptoBox/PGPKeyMaterial.h | 25 + .../ObjectivePGP/CryptoBox/PGPKeyMaterial.m | 13 + .../ObjectivePGP/CryptoBox/PGPRSA.h | 35 + .../ObjectivePGP/CryptoBox/PGPRSA.m | 272 ++++ enzevalos_iphone/ObjectivePGP/Info.plist | 24 + .../ObjectivePGP/ObjectivePGP-Prefix.pch | 3 + enzevalos_iphone/ObjectivePGP/ObjectivePGP.h | 51 + .../ObjectivePGP/ObjectivePGPObject.h | 169 +++ .../ObjectivePGP/ObjectivePGPObject.m | 905 +++++++++++++ enzevalos_iphone/ObjectivePGP/PGPArmor.h | 35 + .../ObjectivePGP/PGPArmor.m | 75 +- .../ObjectivePGP/PGPBigNum+Private.h | 26 + enzevalos_iphone/ObjectivePGP/PGPBigNum.h | 21 + enzevalos_iphone/ObjectivePGP/PGPBigNum.m | 54 + enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.h | 29 + .../ObjectivePGP/PGPCryptoCFB.m | 148 +-- .../ObjectivePGP/PGPExportableProtocol.h | 19 + .../ObjectivePGP/PGPFingerprint.h | 12 +- .../ObjectivePGP/PGPFingerprint.m | 47 +- enzevalos_iphone/ObjectivePGP/PGPFoundation.h | 24 + enzevalos_iphone/ObjectivePGP/PGPFoundation.m | 24 + .../ObjectivePGP/PGPKey+Private.h | 21 + enzevalos_iphone/ObjectivePGP/PGPKey.h | 44 + enzevalos_iphone/ObjectivePGP/PGPKey.m | 145 ++ .../ObjectivePGP/PGPKeyGenerator.h | 29 + .../ObjectivePGP/PGPKeyGenerator.m | 296 +++++ enzevalos_iphone/ObjectivePGP/PGPKeyID.h | 38 + enzevalos_iphone/ObjectivePGP/PGPKeyID.m | 94 ++ enzevalos_iphone/ObjectivePGP/PGPLogging.h | 33 + enzevalos_iphone/ObjectivePGP/PGPMPI.h | 47 + enzevalos_iphone/ObjectivePGP/PGPMPI.m | 119 ++ .../ObjectivePGP/PGPMacros+Private.h | 51 + enzevalos_iphone/ObjectivePGP/PGPMacros.h | 25 + .../ObjectivePGP/PGPPKCSEme.h | 4 +- .../ObjectivePGP/PGPPKCSEme.m | 22 +- .../ObjectivePGP/PGPPKCSEmsa.h | 4 +- .../ObjectivePGP/PGPPKCSEmsa.m | 111 +- .../ObjectivePGP/PGPPacketFactory.h | 10 +- .../ObjectivePGP/PGPPacketFactory.m | 61 +- enzevalos_iphone/ObjectivePGP/PGPPartialKey.h | 70 + enzevalos_iphone/ObjectivePGP/PGPPartialKey.m | 498 +++++++ .../ObjectivePGP/PGPPartialSubKey.h | 27 + .../ObjectivePGP/PGPPartialSubKey.m | 52 + enzevalos_iphone/ObjectivePGP/PGPS2K.h | 36 + enzevalos_iphone/ObjectivePGP/PGPS2K.m | 263 ++++ enzevalos_iphone/ObjectivePGP/PGPTypes.h | 188 +++ enzevalos_iphone/ObjectivePGP/PGPUser.h | 35 + .../ObjectivePGP/PGPUser.m | 116 +- .../Packets/PGPCompressedPacket.h | 10 +- .../Packets/PGPCompressedPacket.m | 47 +- .../ObjectivePGP/Packets/PGPLiteralPacket.h | 29 + .../ObjectivePGP/Packets/PGPLiteralPacket.m | 48 +- .../PGPModificationDetectionCodePacket.h | 2 +- .../PGPModificationDetectionCodePacket.m | 27 +- .../Packets/PGPOnePassSignaturePacket.h | 27 + .../Packets/PGPOnePassSignaturePacket.m | 44 +- .../ObjectivePGP/Packets/PGPPacket+Private.h | 20 + .../ObjectivePGP/Packets/PGPPacket.h | 32 + .../ObjectivePGP/Packets/PGPPacket.m | 374 ++++++ .../ObjectivePGP/Packets/PGPPacketProtocol.h | 16 + .../PGPPublicKeyEncryptedSessionKeyPacket.h | 27 + .../PGPPublicKeyEncryptedSessionKeyPacket.m | 172 +-- .../Packets/PGPPublicKeyPacket+Private.h | 24 + .../ObjectivePGP/Packets/PGPPublicKeyPacket.h | 41 + .../ObjectivePGP/Packets/PGPPublicKeyPacket.m | 299 +++++ .../Packets/PGPPublicSubKeyPacket.h | 4 +- .../Packets/PGPPublicSubKeyPacket.m | 3 +- .../Packets/PGPSecretKeyPacket+Private.h | 25 + .../ObjectivePGP/Packets/PGPSecretKeyPacket.h | 36 + .../ObjectivePGP/Packets/PGPSecretKeyPacket.m | 401 ++++++ .../Packets/PGPSecretSubKeyPacket.h | 0 .../Packets/PGPSecretSubKeyPacket.m | 7 +- .../Packets/PGPSignaturePacket+Private.h | 29 + .../ObjectivePGP/Packets/PGPSignaturePacket.h | 76 ++ .../ObjectivePGP/Packets/PGPSignaturePacket.m | 851 ++++++++++++ .../Packets/PGPSignatureSubpacket+Private.h | 15 + .../Packets/PGPSignatureSubpacket.h | 35 + .../Packets/PGPSignatureSubpacket.m | 390 +++--- .../PGPSignatureSubpacketCreationTime.h | 31 + .../PGPSignatureSubpacketCreationTime.m | 59 + .../Packets/PGPSignatureSubpacketHeader.h | 22 + .../Packets/PGPSignatureSubpacketHeader.m | 13 + .../PGPSymmetricallyEncryptedDataPacket.h | 2 +- .../PGPSymmetricallyEncryptedDataPacket.m | 31 +- ...llyEncryptedIntegrityProtectedDataPacket.h | 25 + ...llyEncryptedIntegrityProtectedDataPacket.m | 226 ++-- .../ObjectivePGP/Packets/PGPTrustPacket.h | 5 +- .../ObjectivePGP/Packets/PGPTrustPacket.m | 14 +- .../Packets/PGPUserAttributePacket.h | 3 +- .../Packets/PGPUserAttributePacket.m | 89 ++ .../Packets/PGPUserAttributeSubpacket.h | 5 +- .../Packets/PGPUserAttributeSubpacket.m | 0 .../ObjectivePGP/Packets/PGPUserIDPacket.h | 26 + .../ObjectivePGP/Packets/PGPUserIDPacket.m | 55 + .../ObjectivePGP/Utils/NSData+PGPUtils.h | 33 + .../ObjectivePGP/Utils/NSData+PGPUtils.m | 198 +++ .../ObjectivePGP/Utils/NSData+compression.h | 18 + .../ObjectivePGP/Utils/NSData+compression.m | 176 ++- .../Utils/NSMutableArray+PGPUtils.h | 19 + .../Utils/NSMutableArray+PGPUtils.m | 23 + .../Utils/NSMutableData+PGPUtils.h | 19 + .../Utils/NSMutableData+PGPUtils.m | 23 + enzevalos_iphone/PGPEncryption.swift | 676 ---------- enzevalos_iphone/PGPKeyManagement.swift | 319 ----- enzevalos_iphone/PGPKeyWrapper.swift | 222 ---- .../PGPTemporaryDecryptionObject.h | 21 - .../PGPTemporaryDecryptionObject.m | 27 - .../PGPTemporaryDecryptionObject.swift | 21 - enzevalos_iphone/SwiftPGP.swift | 179 +++ .../enzevalos_iphone-Bridging-Header.h | 10 +- 166 files changed, 8675 insertions(+), 8721 deletions(-) delete mode 100644 NSData+PGPUtils.h delete mode 100644 NSData+PGPUtils.m delete mode 100755 NSData+compression.h delete mode 100644 NSValue+PGPUtils.h delete mode 100644 NSValue+PGPUtils.m delete mode 100644 ObjectivePGP.h delete mode 100644 ObjectivePGP.m delete mode 100644 PGPArmor.h delete mode 100644 PGPCryptoCFB.h delete mode 100644 PGPCryptoUtils.h delete mode 100644 PGPKey.h delete mode 100644 PGPKey.m delete mode 100644 PGPKeyID.h delete mode 100644 PGPKeyID.m delete mode 100644 PGPLiteralPacket.h delete mode 100644 PGPMPI.h delete mode 100644 PGPMPI.m delete mode 100644 PGPOnePassSignaturePacket.h delete mode 100644 PGPPacket.h delete mode 100644 PGPPacket.m delete mode 100644 PGPPublicKeyEncryptedSessionKeyPacket.h delete mode 100644 PGPPublicKeyPacket.h delete mode 100644 PGPPublicKeyPacket.m delete mode 100644 PGPPublicKeyRSA.h delete mode 100644 PGPPublicKeyRSA.m delete mode 100644 PGPS2K.h delete mode 100644 PGPS2K.m delete mode 100644 PGPSecretKeyPacket.h delete mode 100644 PGPSecretKeyPacket.m delete mode 100644 PGPSignaturePacket.h delete mode 100644 PGPSignaturePacket.m delete mode 100644 PGPSignatureSubpacket.h delete mode 100644 PGPSubKey.h delete mode 100644 PGPSubKey.m delete mode 100644 PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h delete mode 100644 PGPTypes.h delete mode 100644 PGPUser.h delete mode 100644 PGPUserAttributePacket.m delete mode 100644 PGPUserIDPacket.h delete mode 100644 PGPUserIDPacket.m create mode 100644 enzevalos_iphone/CryptoObject.swift create mode 100644 enzevalos_iphone/Cryptography.swift delete mode 100644 enzevalos_iphone/DecryptedData.swift delete mode 100644 enzevalos_iphone/Encryption.swift delete mode 100644 enzevalos_iphone/EncryptionHandler.swift delete mode 100644 enzevalos_iphone/EncryptionType.swift delete mode 100644 enzevalos_iphone/EnzevalosEncryptionHandler.swift delete mode 100644 enzevalos_iphone/KeyWrapper.swift create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.h create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.m create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.h rename PGPCryptoUtils.m => enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.m (57%) create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.h create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.m create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.h create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.m create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.h create mode 100644 enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.m create mode 100644 enzevalos_iphone/ObjectivePGP/Info.plist rename ObjectivePGP-Prefix.pch => enzevalos_iphone/ObjectivePGP/ObjectivePGP-Prefix.pch (89%) create mode 100644 enzevalos_iphone/ObjectivePGP/ObjectivePGP.h create mode 100644 enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.h create mode 100644 enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPArmor.h rename PGPArmor.m => enzevalos_iphone/ObjectivePGP/PGPArmor.m (80%) create mode 100644 enzevalos_iphone/ObjectivePGP/PGPBigNum+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPBigNum.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPBigNum.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.h rename PGPCryptoCFB.m => enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.m (58%) create mode 100644 enzevalos_iphone/ObjectivePGP/PGPExportableProtocol.h rename PGPFingerprint.h => enzevalos_iphone/ObjectivePGP/PGPFingerprint.h (50%) rename PGPFingerprint.m => enzevalos_iphone/ObjectivePGP/PGPFingerprint.m (54%) create mode 100644 enzevalos_iphone/ObjectivePGP/PGPFoundation.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPFoundation.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPKey+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPKey.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPKey.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPKeyID.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPKeyID.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPLogging.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPMPI.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPMPI.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPMacros+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPMacros.h rename PGPPKCSEme.h => enzevalos_iphone/ObjectivePGP/PGPPKCSEme.h (54%) rename PGPPKCSEme.m => enzevalos_iphone/ObjectivePGP/PGPPKCSEme.m (78%) rename PGPPKCSEmsa.h => enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.h (62%) rename PGPPKCSEmsa.m => enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.m (53%) rename PGPPacketFactory.h => enzevalos_iphone/ObjectivePGP/PGPPacketFactory.h (59%) rename PGPPacketFactory.m => enzevalos_iphone/ObjectivePGP/PGPPacketFactory.m (77%) create mode 100644 enzevalos_iphone/ObjectivePGP/PGPPartialKey.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPPartialKey.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPS2K.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPS2K.m create mode 100644 enzevalos_iphone/ObjectivePGP/PGPTypes.h create mode 100644 enzevalos_iphone/ObjectivePGP/PGPUser.h rename PGPUser.m => enzevalos_iphone/ObjectivePGP/PGPUser.m (59%) rename PGPCompressedPacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.h (65%) rename PGPCompressedPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.m (74%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.h rename PGPLiteralPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.m (79%) rename PGPModificationDetectionCodePacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.h (86%) rename PGPModificationDetectionCodePacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.m (56%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.h rename PGPOnePassSignaturePacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.m (61%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPacket+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.m create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPacketProtocol.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.h rename PGPPublicKeyEncryptedSessionKeyPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.m (58%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.m rename PGPPublicSubKeyPacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.h (100%) rename PGPPublicSubKeyPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.m (92%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.m rename PGPSecretSubKeyPacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPSecretSubKeyPacket.h (100%) rename PGPSecretSubKeyPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPSecretSubKeyPacket.m (91%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.m create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket+Private.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.h rename PGPSignatureSubpacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.m (51%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.m create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.m rename PGPSymmetricallyEncryptedDataPacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.h (85%) rename PGPSymmetricallyEncryptedDataPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.m (72%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h rename PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m (54%) rename PGPTrustPacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.h (85%) rename PGPTrustPacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.m (72%) rename PGPUserAttributePacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.h (72%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.m rename PGPUserAttributeSubpacket.h => enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributeSubpacket.h (82%) rename PGPUserAttributeSubpacket.m => enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributeSubpacket.m (100%) create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.h create mode 100644 enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.m create mode 100644 enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.h create mode 100644 enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.m create mode 100644 enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.h rename NSData+compression.m => enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.m (60%) mode change 100755 => 100644 create mode 100644 enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.h create mode 100644 enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.m create mode 100644 enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.h create mode 100644 enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.m delete mode 100644 enzevalos_iphone/PGPEncryption.swift delete mode 100644 enzevalos_iphone/PGPKeyManagement.swift delete mode 100644 enzevalos_iphone/PGPKeyWrapper.swift delete mode 100644 enzevalos_iphone/PGPTemporaryDecryptionObject.h delete mode 100644 enzevalos_iphone/PGPTemporaryDecryptionObject.m delete mode 100644 enzevalos_iphone/PGPTemporaryDecryptionObject.swift create mode 100644 enzevalos_iphone/SwiftPGP.swift diff --git a/NSData+PGPUtils.h b/NSData+PGPUtils.h deleted file mode 100644 index 124cd231..00000000 --- a/NSData+PGPUtils.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// NSData+Bytes.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" - -@interface NSData (PGPUtils) - -- (UInt16) pgp_Checksum; -- (UInt32) pgp_CRC24; -- (NSData*) pgp_MD5; -- (NSData*) pgp_SHA1; -- (NSData*) pgp_SHA224; -- (NSData*) pgp_SHA256; -- (NSData*) pgp_SHA384; -- (NSData*) pgp_SHA512; -- (NSData*) pgp_RIPEMD160; - -- (NSData *) pgp_HashedWithAlgorithm:(PGPHashAlgorithm)hashAlgorithm; -- (NSData *) pgp_encryptBlockWithSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm sessionKeyData:(NSData *)sessionKeyData; - -@end diff --git a/NSData+PGPUtils.m b/NSData+PGPUtils.m deleted file mode 100644 index e8adf853..00000000 --- a/NSData+PGPUtils.m +++ /dev/null @@ -1,358 +0,0 @@ -// -// NSData+PGPUtils.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "NSData+PGPUtils.h" -#import "PGPCryptoUtils.h" - -#import <CommonCrypto/CommonCrypto.h> - -#include <openssl/ripemd.h> -#include <openssl/cast.h> -#include <openssl/idea.h> -#include <openssl/aes.h> -#include <openssl/sha.h> -#include <openssl/des.h> -#include <openssl/camellia.h> -#include <openssl/blowfish.h> - - -@implementation NSData (PGPUtils) - -/** - * Calculates a 16bit sum of a string by adding each character * codes modulus 65535 - * - * @return checksum - */ -- (UInt16) pgp_Checksum -{ - UInt32 s = 0; - const UInt8 *bytes = self.bytes; - for (NSUInteger i = 0; i < self.length; i++) { - s = (s + (UInt8)bytes[i]); - } - s = s % 65536; - return (UInt16)s; -} - -#define CRC24_POLY 0x1864cfbL -#define CRC24_INIT 0xB704CEL - -- (UInt32) pgp_CRC24 -{ - UInt32 crc = CRC24_INIT; - NSUInteger len = self.length; - const UInt8 *octets = self.bytes; - int i; - while (len--) { - crc ^= (*octets++) << 16; - for (i = 0; i < 8; i++) { - crc <<= 1; - if (crc & 0x1000000) - crc ^= CRC24_POLY; - } - } - return crc & 0xFFFFFFL; -} - -- (NSData*) pgp_MD5 -{ - if (!self) - return self; - - CC_MD5_CTX *ctx = calloc(1, sizeof(CC_MD5_CTX)); - - CC_MD5_Init(ctx); - CC_MD5_Update(ctx, self.bytes, (CC_LONG)self.length); - UInt8 *out = calloc(CC_MD5_DIGEST_LENGTH, sizeof(UInt8)); - if (!out) { - free(ctx); - return nil; - } - CC_MD5_Final(out, ctx); - - NSData *outData = [NSData dataWithBytes:out length:CC_MD5_DIGEST_LENGTH]; - - free(out); - free(ctx); - return outData; -} - -- (NSData *) pgp_SHA1 -{ - if (!self) - return self; - -// unsigned char digest[CC_SHA1_DIGEST_LENGTH]; -// CC_SHA1(self.bytes, self.length, digest); -// NSData *outData = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; - - CC_SHA1_CTX *ctx = calloc(1, sizeof(CC_SHA1_CTX)); - if (!ctx) { - return nil; - } - - UInt8 *outBuf = calloc(CC_SHA1_DIGEST_LENGTH, 1); - if (!outBuf) { - free(ctx); - return nil; - } - CC_SHA1_Init(ctx); - CC_SHA1_Update(ctx, self.bytes, (CC_LONG)self.length); - CC_SHA1_Final(outBuf, ctx); - - NSData *outData = [NSData dataWithBytes:outBuf length:CC_SHA1_DIGEST_LENGTH]; - - free(outBuf); - free(ctx); - return outData; -} - -- (NSData*) pgp_SHA224 -{ - if (!self) - return self; - - CC_SHA256_CTX *ctx = calloc(1, sizeof(CC_SHA256_CTX)); - if (!ctx) { - return nil; - } - - CC_SHA224_Init(ctx); - CC_SHA224_Update(ctx, self.bytes, (CC_LONG)self.length); - UInt8 *out = calloc(CC_SHA224_DIGEST_LENGTH, sizeof(UInt8)); - if (!out) { - free(ctx); - return nil; - } - CC_SHA224_Final(out, ctx); - - NSData *outData = [NSData dataWithBytes:out length:CC_SHA224_DIGEST_LENGTH]; - - free(out); - free(ctx); - return outData; -} - -- (NSData*) pgp_SHA256 -{ - if (!self) - return self; - - CC_SHA256_CTX *ctx = calloc(1, sizeof(CC_SHA256_CTX)); - if (!ctx) { - return nil; - } - - CC_SHA256_Init(ctx); - CC_SHA256_Update(ctx, self.bytes, (CC_LONG)self.length); - UInt8 *out = calloc(CC_SHA256_DIGEST_LENGTH, sizeof(UInt8)); - if (!out) { - free(ctx); - return nil; - } - CC_SHA256_Final(out, ctx); - - NSData *outData = [NSData dataWithBytes:out length:CC_SHA256_DIGEST_LENGTH]; - - free(out); - free(ctx); - return outData; -} - -- (NSData*) pgp_SHA384 -{ - if (!self) - return self; - - CC_SHA512_CTX *ctx = calloc(1, sizeof(CC_SHA512_CTX)); - if (!ctx) { - return nil; - } - - CC_SHA384_Init(ctx); - CC_SHA384_Update(ctx, self.bytes, (CC_LONG)self.length); - UInt8 *out = calloc(CC_SHA384_DIGEST_LENGTH, sizeof(UInt8)); - if (!out) { - free(ctx); - return nil; - } - CC_SHA384_Final(out, ctx); - - NSData *outData = [NSData dataWithBytes:out length:CC_SHA384_DIGEST_LENGTH]; - - free(out); - free(ctx); - return outData; -} - -- (NSData*) pgp_SHA512 -{ - if (!self) - return self; - - CC_SHA512_CTX *ctx = calloc(1, sizeof(CC_SHA512_CTX)); - if (!ctx) { - return nil; - } - - CC_SHA512_Init(ctx); - CC_SHA512_Update(ctx, self.bytes, (CC_LONG)self.length); - UInt8 *outBuf = calloc(CC_SHA512_DIGEST_LENGTH, sizeof(UInt8)); - if (!outBuf) { - free(ctx); - return nil; - } - CC_SHA512_Final(outBuf, ctx); - - NSData *outData = [NSData dataWithBytes:outBuf length:CC_SHA512_DIGEST_LENGTH]; - - free(outBuf); - free(ctx); - return outData; -} - -- (NSData*) pgp_RIPEMD160 -{ - if (!self) - return self; - - RIPEMD160_CTX *ctx = calloc(1, sizeof(RIPEMD160_CTX)); - if (!ctx) { - return nil; - } - - RIPEMD160_Init(ctx); - RIPEMD160_Update(ctx, self.bytes, self.length); - UInt8 *out = calloc(RIPEMD160_DIGEST_LENGTH, sizeof(UInt8)); - if (!out) { - return nil; - } - RIPEMD160_Final(out, ctx); - - NSData *outData = [NSData dataWithBytes:out length:RIPEMD160_DIGEST_LENGTH]; - - free(out); - free(ctx); - return outData; -} - -- (NSData *) pgp_HashedWithAlgorithm:(PGPHashAlgorithm)hashAlgorithm -{ - NSData *hashData = nil; - switch (hashAlgorithm) { - case PGPHashMD5: - hashData = [self pgp_MD5]; - break; - case PGPHashSHA1: - hashData = [self pgp_SHA1]; - break; - case PGPHashSHA224: - hashData = [self pgp_SHA224]; - break; - case PGPHashSHA256: - hashData = [self pgp_SHA256]; - break; - case PGPHashSHA384: - hashData = [self pgp_SHA384]; - break; - case PGPHashSHA512: - hashData = [self pgp_SHA512]; - break; - case PGPHashRIPEMD160: - hashData = [self pgp_RIPEMD160]; - break; - - default: - NSAssert(false, @"hash algorithm not supported"); - break; - } - return hashData; -} - -#pragma mark - Encryption - -- (NSData *) pgp_encryptBlockWithSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm sessionKeyData:(NSData *)sessionKeyData -{ - NSAssert(sessionKeyData,@"Missing key data"); - - if (!sessionKeyData) { - return nil; - } - - NSUInteger keySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:symmetricAlgorithm]; - - NSData *ret = nil; - - switch (symmetricAlgorithm) { - case PGPSymmetricCAST5: - { - CAST_KEY *encrypt_key = calloc(1, sizeof(CAST_KEY)); - CAST_set_key(encrypt_key, (unsigned int)keySize, sessionKeyData.bytes); - UInt8 *outBuf = calloc(self.length, sizeof(UInt8)); - CAST_ecb_encrypt(self.bytes, outBuf, encrypt_key, CAST_ENCRYPT); - ret = [NSData dataWithBytes:&outBuf length:self.length]; - - free(outBuf); - free(encrypt_key); - } - break; - case PGPSymmetricAES256: - case PGPSymmetricAES128: - case PGPSymmetricAES192: - { - AES_KEY *encrypt_key = calloc(1, sizeof(AES_KEY)); - AES_set_encrypt_key(sessionKeyData.bytes, keySize * 8.0, encrypt_key); - - UInt8 *outBuf = calloc(self.length, sizeof(UInt8)); - AES_encrypt(self.bytes, outBuf, encrypt_key); - ret = [NSData dataWithBytes:&outBuf length:self.length]; - - free(outBuf); - free(encrypt_key); - } - break; - case PGPSymmetricIDEA: - { - IDEA_KEY_SCHEDULE *encrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE)); - idea_set_encrypt_key(sessionKeyData.bytes, encrypt_key); - - UInt8 *outBuf = calloc(self.length, sizeof(UInt8)); - idea_ecb_encrypt(self.bytes, outBuf, encrypt_key); - ret = [NSData dataWithBytes:&outBuf length:self.length]; - - free(outBuf); - free(encrypt_key); - } - break; - case PGPSymmetricTripleDES: - { - // Very unsure if this is working, need some tests later - const void *key = sessionKeyData.bytes; - - DES_key_schedule *keys3 = calloc(3, sizeof(DES_key_schedule)); - for (int n = 0; n < 3; ++n) { - DES_set_key((DES_cblock *)(void *)(key + n * 8), &keys3[n]); - } - - DES_cblock *outBuf = calloc(self.length, sizeof(DES_cblock)); - DES_ecb3_encrypt((void *)(unsigned long)(const void *)(self.bytes), outBuf, &keys3[0], &keys3[1], &keys3[2], DES_ENCRYPT); - ret = [NSData dataWithBytes:&outBuf length:self.length]; - - free(outBuf); - free(keys3); - } - break; - default: - [NSException raise:@"PGPNotSupported" format:@"Encryption unsupported, cant encrypt data"]; - break; - } - return ret; -} - - -@end diff --git a/NSData+compression.h b/NSData+compression.h deleted file mode 100755 index 3cdc5de0..00000000 --- a/NSData+compression.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// NSData+zlib.h -// -// rfc1950 (zlib format) - -#import <Foundation/Foundation.h> -#import <zlib.h> -#import "BZipCompression.h" - -extern NSString* const ZlibErrorDomain; - -@interface NSData (compression) - -- (NSData *)zlibCompressed:(NSError * __autoreleasing *)error; -- (NSData *)zlibDecompressed:(NSError * __autoreleasing *)error compressionType:(int)compressionType; - -- (NSData *)bzip2Decompressed:(NSError * __autoreleasing *)error; -- (NSData *)bzip2Compressed:(NSError * __autoreleasing *)error; - -@end diff --git a/NSValue+PGPUtils.h b/NSValue+PGPUtils.h deleted file mode 100644 index 7c72db0e..00000000 --- a/NSValue+PGPUtils.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// NSValue+PGPUtils.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 18/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> - -@interface NSValue (PGPUtils) - -- (BOOL) pgp_objCTypeIsEqualTo:(const char *)type; - -@end diff --git a/NSValue+PGPUtils.m b/NSValue+PGPUtils.m deleted file mode 100644 index 643c324d..00000000 --- a/NSValue+PGPUtils.m +++ /dev/null @@ -1,24 +0,0 @@ -// -// NSValue+PGPUtils.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 18/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "NSValue+PGPUtils.h" - -@implementation NSValue (PGPUtils) - -- (BOOL) pgp_objCTypeIsEqualTo:(const char *)type -{ - if (!type || strlen(type) == 0) - return NO; - - if (strcmp([self objCType], type) == 0) { - return YES; - } - return NO; -} - -@end diff --git a/ObjectivePGP.h b/ObjectivePGP.h deleted file mode 100644 index 04e8c98f..00000000 --- a/ObjectivePGP.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// ObjectivePGP.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 03/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" -#import "PGPKey.h" -#import "PGPUser.h" - -#import "PGPTemporaryDecryptionObject.h" - -@interface ObjectivePGP : NSObject - -/** - * Array of PGPKey - */ -@property (strong, nonatomic, nonnull) NSArray<PGPKey *> *keys; - -// Import keys -- (NSArray * __nullable) importKeysFromFile:(NSString * __nonnull)path allowDuplicates:(BOOL)duplicates; -- (NSArray * __nullable) importKeysFromData:(NSData * __nonnull)data allowDuplicates:(BOOL)duplicates; -- (BOOL) importKey:(nonnull NSString *)shortKeyStringIdentifier fromFile:(nonnull NSString *)path; -- (NSArray * __nullable) importPublicKeyFromHeader: (NSString * __nonnull) data allowDuplicates:(BOOL)duplicates; - -// Read keys -- (nullable NSArray<PGPKey *> *) keysFromData:(nonnull NSData *)fileData; -- (nullable NSArray<PGPKey *> *) keysFromFile:(nonnull NSString *)path; - -// Export keys -- (BOOL) exportKeysOfType:(PGPKeyType)type toFile:(nonnull NSString *)path error:(NSError * __autoreleasing __nullable * __nullable)error; - -- (BOOL) exportKeys:(nonnull NSArray<PGPKey *> *)keys toFile:(nonnull NSString *)path error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) exportKey:(nonnull PGPKey *)key armored:(BOOL)armored; -- (nullable NSString *) exportKeyWithoutArmor:(nonnull PGPKey *)key; - - -- (nullable PGPKey *) getKeyForIdentifier:(nonnull NSString *)keyIdentifier type:(PGPKeyType)keyType; -- (nullable PGPKey *) getKeyForKeyID:(nonnull PGPKeyID *)searchKeyID type:(PGPKeyType)keyType; -- (nullable NSArray<PGPKey *> *) getKeysForUserID:(nonnull NSString *)userID; -- (nonnull NSArray<PGPKey *> *) getKeysOfType:(PGPKeyType)keyType; - -- (nullable NSData *) signData:(nonnull NSData *)dataToSign usingSecretKey:(nonnull PGPKey *)secretKey passphrase:(nullable NSString *)passphrase error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) signData:(nonnull NSData *)dataToSign usingSecretKey:(nonnull PGPKey *)secretKey passphrase:(nullable NSString *)passphrase detached:(BOOL)detached error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) signData:(nonnull NSData *)dataToSign withKeyForUserID:(nonnull NSString *)userID passphrase:(nullable NSString *)passphrase error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) signData:(nonnull NSData *)dataToSign withKeyForUserID:(nonnull NSString *)userID passphrase:(nullable NSString *)passphrase detached:(BOOL)detached error:(NSError * __autoreleasing __nullable * __nullable)error; - -- (BOOL) verifyData:(nonnull NSData *)signedDataPackets error:(NSError * __autoreleasing __nullable * __nullable)error; -- (BOOL) verifyData:(nonnull NSData *)signedData withSignature:(nonnull NSData *)signatureData error:(NSError * __autoreleasing __nullable * __nullable)error; -- (BOOL) verifyData:(nonnull NSData *)signedData withSignature:(nonnull NSData *)signatureData usingKey:(nonnull PGPKey *)publicKey error:(NSError * __autoreleasing __nullable * __nullable)error; - -- (nullable NSData *) encryptData:(nonnull NSData *)dataToEncrypt usingPublicKey:(nonnull PGPKey *)publicKey armored:(BOOL)armored error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) encryptData:(nonnull NSData *)dataToEncrypt usingPublicKeys:(nonnull NSArray *)publicKeys armored:(BOOL)armored error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) encryptData:(nonnull NSData *)dataToEncrypt usingPublicKeys:(nonnull NSArray *)publicKeys signWithSecretKey:(nullable PGPKey *)secretKey passphrase:(nullable NSString *)passphrase armored:(BOOL)armored error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) decryptData:(nonnull NSData *)messageDataToDecrypt passphrase:(nullable NSString *)passphrase error:(NSError * __autoreleasing __nullable * __nullable)error; -- (nullable NSData *) decryptData:(nonnull NSData *)messageDataToDecrypt passphrase:(nullable NSString *)passphrase verifyWithPublicKey:(nullable PGPKey *)publicKey signed:(nullable BOOL*)isSigned valid:(nullable BOOL*)isValid integrityProtected:(nullable BOOL*)isIntegrityProtected error:(NSError * __autoreleasing __nullable * __nullable)error; - -- (nonnull PGPTemporaryDecryptionObject *) decryptDataFirstPart:(nonnull NSData *)messageDataToDecrypt passphrase:(nullable NSString *)passphrase integrityProtected:(nullable BOOL*)isIntegrityProtected error:(NSError * __autoreleasing __nullable * __nullable)error; -- (BOOL *_Nonnull) decryptDataSecondPart:(nonnull PGPTemporaryDecryptionObject *)temporaryDecryptionObject verifyWithPublicKey:(nullable PGPKey *)publicKey signed:(nullable BOOL*)isSigned valid:(nullable BOOL*)isValid error:(NSError * __autoreleasing __nullable * __nullable)error; - -@end diff --git a/ObjectivePGP.m b/ObjectivePGP.m deleted file mode 100644 index e90fbd02..00000000 --- a/ObjectivePGP.m +++ /dev/null @@ -1,1175 +0,0 @@ -// -// ObjectivePGP.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 03/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "ObjectivePGP.h" -#import "PGPPacketFactory.h" -#import "PGPKey.h" -#import "PGPSubKey.h" -#import "PGPSignaturePacket.h" -#import "PGPPacketFactory.h" -#import "PGPUserIDPacket.h" -#import "PGPPublicKeyPacket.h" -#import "PGPSecretKeyPacket.h" -#import "PGPLiteralPacket.h" -#import "PGPUser.h" -#import "PGPOnePassSignaturePacket.h" -#import "PGPModificationDetectionCodePacket.h" -#import "PGPLiteralPacket.h" -#import "PGPCompressedPacket.h" -#import "PGPArmor.h" -#import "PGPCryptoUtils.h" -#import "PGPPublicKeyEncryptedSessionKeyPacket.h" -#import "PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h" -#import "PGPMPI.h" - -#import "NSData+PGPUtils.h" - - -@implementation ObjectivePGP - -- (NSArray<PGPKey *> *)keys -{ - if (!_keys) { - _keys = [NSArray<PGPKey *> array]; - } - return _keys; -} - -#pragma mark - Search - -// full user identifier -- (nullable NSArray<PGPKey *> *) getKeysForUserID:(nonnull NSString *)userID -{ - NSMutableArray *foundKeysArray = [NSMutableArray array]; - [self.keys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - PGPKey *key = obj; - for (PGPUser *user in key.users) { - if ([user.userID isEqualToString:userID]) { - [foundKeysArray addObject:key]; - } - } - }]; - return foundKeysArray.count > 0 ? [foundKeysArray copy] : nil; -} - -- (nullable PGPKey *) getKeyForKeyID:(nonnull PGPKeyID *)searchKeyID type:(PGPKeyType)keyType -{ - if (!searchKeyID) { - return nil; - } - - __block PGPKey *foundKey = nil; - [[self getKeysOfType:keyType] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - PGPKey *key = obj; - if ([key.keyID isEqualToKeyID:searchKeyID]) { - foundKey = key; - *stop = YES; - } - - [key.subKeys enumerateObjectsUsingBlock:^(id objsub, NSUInteger idxsub, BOOL *stopsub) { - PGPSubKey *subKey = objsub; - if ([subKey.keyID isEqualToKeyID:searchKeyID]) { - foundKey = key; - *stopsub = YES; - *stop = YES; - } - - }]; - }]; - return foundKey; -} - -// 16 or 8 chars identifier -//TODO: rename to getKeyForFingerprint or something -- (PGPKey *) getKeyForIdentifier:(NSString *)keyIdentifier type:(PGPKeyType)keyType -{ - if (keyIdentifier.length < 8 && keyIdentifier.length > 16) - return nil; - - __block PGPKey *foundKey = nil; - [[self getKeysOfType:keyType] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - PGPKey *key = obj; - PGPPublicKeyPacket *primaryPacket = (PGPPublicKeyPacket *)key.primaryKeyPacket; - if (keyIdentifier.length == 16 && [[primaryPacket.keyID.longKeyString uppercaseString] isEqualToString:[keyIdentifier uppercaseString]]) { - foundKey = key; - *stop = YES; - return; - } else if (keyIdentifier.length == 8 && [[primaryPacket.keyID.shortKeyString uppercaseString] isEqualToString:[keyIdentifier uppercaseString]]) { - foundKey = key; - *stop = YES; - return; - } - - [[key subKeys] enumerateObjectsUsingBlock:^(id subobj, NSUInteger subidx, BOOL *substop) { - PGPSubKey *subKey = subobj; - PGPPublicKeyPacket *subprimaryPacket = (PGPPublicKeyPacket *)subKey.primaryKeyPacket; - if (keyIdentifier.length == 16 && [[subprimaryPacket.keyID.longKeyString uppercaseString] isEqualToString:[keyIdentifier uppercaseString]]) { - foundKey = key; - *substop = YES; - *stop = YES; - } else if (keyIdentifier.length == 8 && [[subprimaryPacket.keyID.shortKeyString uppercaseString] isEqualToString:[keyIdentifier uppercaseString]]) { - foundKey = key; - *substop = YES; - *stop = YES; - } - }]; - }]; - return foundKey; -} - -- (nonnull NSArray<PGPKey *> *) getKeysOfType:(PGPKeyType)keyType -{ - NSMutableArray *keysArray = [NSMutableArray array]; - for (PGPKey *key in self.keys) { - if (key.type == keyType) - [keysArray addObject:key]; - } - return [keysArray copy]; -} - -#pragma mark - Save - -- (BOOL) exportKeysOfType:(PGPKeyType)type toFile:(NSString *)path error:(NSError * __autoreleasing *)error -{ - return [self exportKeys:[self getKeysOfType:type] toFile:path error:error]; -} - -- (BOOL) exportKeys:(NSArray *)keys toFile:(NSString *)path error:(NSError * __autoreleasing *)error -{ - BOOL result = YES; - for (PGPKey *key in keys) { - result = result && [self appendKey:key toKeyring:path error:error]; - } - return result; -} - - -- (BOOL) appendKey:(PGPKey *)key toKeyring:(NSString *)path error:(NSError * __autoreleasing *)error -{ - NSFileManager *fm = [NSFileManager defaultManager]; - - if (!path) { - return NO; - } - - NSData *keyData = [key export:error]; - if (*error) { - return NO; - } - - BOOL result = NO; - if (![fm fileExistsAtPath:path]) { - NSDictionary *attributes = nil; -#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED - attributes = @{NSFileProtectionKey: NSFileProtectionComplete, NSFilePosixPermissions: @(0600)}; -#else - attributes = @{NSFilePosixPermissions: @(0600)}; -#endif - result = [fm createFileAtPath:path contents:keyData attributes:attributes]; - } else { - @try { - NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:path]; - [fileHandle seekToEndOfFile]; - [fileHandle writeData:keyData]; - [fileHandle closeFile]; - result = YES; - } - @catch (NSException *exception) { - result = NO; - } - } - return result; -} - -- (NSString *) exportKeyWithoutArmor: (PGPKey *)key -{ - NSData* data = [self exportKey: key armored:true]; - if (data == nil){ - return nil; - } - NSString* armoredString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - - NSScanner *scanner = [[NSScanner alloc] initWithString:armoredString]; - scanner.charactersToBeSkipped = nil; - - // check header line - NSString *headerLine = nil; - [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&headerLine]; - if (![headerLine isEqualToString:@"-----BEGIN PGP MESSAGE-----"] && - ![headerLine isEqualToString:@"-----BEGIN PGP PUBLIC KEY BLOCK-----"] && - ![headerLine isEqualToString:@"-----BEGIN PGP PRIVATE KEY BLOCK-----"] && - ![headerLine isEqualToString:@"-----BEGIN PGP SECRET KEY BLOCK-----"] && // PGP 2.x generates the header "BEGIN PGP SECRET KEY BLOCK" instead of "BEGIN PGP PRIVATE KEY BLOCK" - ![headerLine isEqualToString:@"-----BEGIN PGP SIGNATURE-----"] && - ![headerLine hasPrefix:@"-----BEGIN PGP MESSAGE, PART"]) - { - return nil; - } - - // consume newline - [scanner scanString:@"\r" intoString:nil]; - [scanner scanString:@"\n" intoString:nil]; - - NSString *line = nil; - - if (![scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:nil]) { - // Scan headers (Optional) - [scanner scanUpToCharactersFromSet:[[NSCharacterSet newlineCharacterSet] invertedSet] intoString:nil]; - - while ([scanner scanCharactersFromSet:[[NSCharacterSet newlineCharacterSet] invertedSet] intoString:&line]) - { - // consume newline - [scanner scanString:@"\r" intoString:nil]; - [scanner scanString:@"\n" intoString:nil]; - } - } - - // skip blank line - [scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:nil]; - - // read base64 data - BOOL base64Section = YES; - NSMutableString *base64String = [NSMutableString string]; - while (base64Section && [scanner scanCharactersFromSet:[[NSCharacterSet newlineCharacterSet] invertedSet] intoString:&line]) { - // consume newline - [scanner scanString:@"\r" intoString:nil]; - [scanner scanString:@"\n" intoString:nil]; - - if ([line hasPrefix:@"="]) { - scanner.scanLocation = scanner.scanLocation - (line.length + 2); - base64Section = NO; - } else { - [base64String appendFormat:@"%@\n", line]; - } - } - - - return base64String; - -} - -- (NSData *) exportKey:(PGPKey *)key armored:(BOOL)armored -{ - NSAssert(key, @"Missing parameter"); - if (!key) { - return nil; - } - - NSError *exportError = nil; - NSData *keyData = [key export:&exportError]; - if (!keyData || exportError) { - NSLog(@"%@",exportError); - return nil; - } - - if (armored) { - return [PGPArmor armoredData:keyData as:PGPArmorTypePublicKey]; - } else { - return keyData; - } - return nil; -} - -#pragma mark - Encrypt & Decrypt - -- (NSData *) decryptData:(NSData *)messageDataToDecrypt passphrase:(NSString *)passphrase error:(NSError * __autoreleasing *)error -{ - return [self decryptData:messageDataToDecrypt passphrase:passphrase verifyWithPublicKey:nil signed:nil valid:nil integrityProtected:nil error:error]; -} - -- (NSData *) decryptData:(NSData *)messageDataToDecrypt passphrase:(NSString *)passphrase verifyWithPublicKey:(PGPKey *)publicKey signed:(BOOL*)isSigned valid:(BOOL*)isValid integrityProtected:(BOOL*)isIntegrityProtected error:(NSError * __autoreleasing *)error -{ - NSArray *binaryMessages = [self convertArmoredMessage2BinaryBlocksWhenNecessary:messageDataToDecrypt]; - NSData *binaryMessageToDecrypt = binaryMessages.count > 0 ? binaryMessages.firstObject : nil; - NSAssert(binaryMessageToDecrypt != nil, @"Invalid input data"); - if (!binaryMessageToDecrypt) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Invalid input data"}]; - } - return nil; - } - - // parse packets - NSArray *packets = [self readPacketsFromData:binaryMessageToDecrypt]; - - PGPSymmetricAlgorithm sessionKeyAlgorithm = 0; - PGPSecretKeyPacket *decryptionSecretKeyPacket = nil; // found secret key to used to decrypt - - // 1. search for valid and known (do I have specified key?) ESK - PGPPublicKeyEncryptedSessionKeyPacket *eskPacket = nil; - for (PGPPacket *packet in packets) { - if (packet.tag == PGPPublicKeyEncryptedSessionKeyPacketTag) { - PGPPublicKeyEncryptedSessionKeyPacket *pkESKPacket = (PGPPublicKeyEncryptedSessionKeyPacket *)packet; - PGPKey *decryptionSecretKey = [self getKeyForKeyID:pkESKPacket.keyID type:PGPKeySecret]; - if (!decryptionSecretKey) { - continue; - } - - decryptionSecretKeyPacket = (PGPSecretKeyPacket *)[decryptionSecretKey decryptionKeyPacketWithID:pkESKPacket.keyID error:error]; - - // decrypt key with passphrase if encrypted - if (decryptionSecretKeyPacket.isEncryptedWithPassword) { - - if (!passphrase) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorPassphraseRequired userInfo:@{NSLocalizedDescriptionKey: @"Password is required for key"}]; - } - return nil; - } - - decryptionSecretKeyPacket = [decryptionSecretKeyPacket decryptedKeyPacket:passphrase error:error]; - if (error && *error) { - return nil; - } - } - eskPacket = pkESKPacket; - } - } - - if (error && *error) { - return nil; - } - - //NSAssert(eskPacket, @"Valid PublicKeyEncryptedSessionKeyPacket not found"); - if (!eskPacket) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Valid PublicKeyEncryptedSessionKeyPacket not found"}]; - } - return nil; - } - - NSAssert(decryptionSecretKeyPacket, @"Decryption secret key packet not found"); - if (!decryptionSecretKeyPacket) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Unable to find secret key"}]; - } - return nil; - } - - - NSData *sessionKeyData = [eskPacket decryptSessionKeyData:decryptionSecretKeyPacket sessionKeyAlgorithm:&sessionKeyAlgorithm error:error]; - NSAssert(sessionKeyAlgorithm > 0, @"Invalid session key algorithm"); - - NSAssert(sessionKeyData, @"Missing session key data"); - if (!sessionKeyData) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Missing session key data"}]; - } - return nil; - } - - // 2 - for (PGPPacket *packet in packets) { - switch (packet.tag) { - case PGPSymmetricallyEncryptedIntegrityProtectedDataPacketTag: - { - // decrypt PGPSymmetricallyEncryptedIntegrityProtectedDataPacket - PGPSymmetricallyEncryptedIntegrityProtectedDataPacket *symEncryptedDataPacket = (PGPSymmetricallyEncryptedIntegrityProtectedDataPacket *)packet; - packets = [symEncryptedDataPacket decryptWithSecretKeyPacket:decryptionSecretKeyPacket sessionKeyAlgorithm:sessionKeyAlgorithm sessionKeyData:sessionKeyData isIntegrityProtected:isIntegrityProtected error:error]; - if (!packets) { - return nil; - } - } - break; - default: - - break; - } - } - - PGPLiteralPacket *literalPacket; - PGPSignaturePacket *signaturePacket; - NSData *plaintextData = nil; - for (PGPPacket *packet in packets) - { - switch (packet.tag) { - case PGPCompressedDataPacketTag: - case PGPOnePassSignaturePacketTag: - // ignore here - break; - case PGPLiteralDataPacketTag: - literalPacket = (PGPLiteralPacket *)packet; - plaintextData = literalPacket.literalRawData; - break; - case PGPSignaturePacketTag: - signaturePacket = (PGPSignaturePacket *)packet; - break; - default: - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Unknown packet (expected literal or compressed)"}]; - } - return nil; - break; - } - } - - BOOL _signed = signaturePacket != nil; - BOOL _valid = NO; - if (signaturePacket && publicKey) - { - _valid = [self verifyData:plaintextData withSignature:signaturePacket.packetData usingKey:publicKey error:nil]; - } - if (isSigned) - { - *isSigned = _signed; - } - if (isValid) - { - *isValid = _valid; - } - return plaintextData; -} - -//--------------------- Jakob ------------------------- - -- (PGPTemporaryDecryptionObject *) decryptDataFirstPart:(NSData *)messageDataToDecrypt passphrase:(NSString *)passphrase integrityProtected:(BOOL*)isIntegrityProtected error:(NSError * __autoreleasing *)error -{ - NSArray *binaryMessages = [self convertArmoredMessage2BinaryBlocksWhenNecessary:messageDataToDecrypt]; - NSData *binaryMessageToDecrypt = binaryMessages.count > 0 ? binaryMessages.firstObject : nil; - //printf("jakob auskommentierte Assertion line 218 ObjectivePGP.m"); - - //NSAssert(binaryMessageToDecrypt != nil, @"Invalid input data"); - if (!binaryMessageToDecrypt) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Invalid input data"}]; - } - return nil; - } - - // parse packets - NSArray *packets = [self readPacketsFromData:binaryMessageToDecrypt]; - - PGPSymmetricAlgorithm sessionKeyAlgorithm = 0; - PGPSecretKeyPacket *decryptionSecretKeyPacket = nil; // found secret key to used to decrypt - - // 1. search for valid and known (do I have specified key?) ESK - PGPPublicKeyEncryptedSessionKeyPacket *eskPacket = nil; - for (PGPPacket *packet in packets) { - if (packet.tag == PGPPublicKeyEncryptedSessionKeyPacketTag) { - PGPPublicKeyEncryptedSessionKeyPacket *pkESKPacket = (PGPPublicKeyEncryptedSessionKeyPacket *)packet; - PGPKey *decryptionSecretKey = [self getKeyForKeyID:pkESKPacket.keyID type:PGPKeySecret]; - if (!decryptionSecretKey) { - continue; - } - - decryptionSecretKeyPacket = (PGPSecretKeyPacket *)[decryptionSecretKey decryptionKeyPacketWithID:pkESKPacket.keyID error:error]; - - // decrypt key with passphrase if encrypted - if (decryptionSecretKeyPacket.isEncryptedWithPassword) { - - if (!passphrase) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorPassphraseRequired userInfo:@{NSLocalizedDescriptionKey: @"Password is required for key"}]; - } - return nil; - } - - decryptionSecretKeyPacket = [decryptionSecretKeyPacket decryptedKeyPacket:passphrase error:error]; - if (error && *error) { - return nil; - } - } - eskPacket = pkESKPacket; - } - } - - if (error && *error) { - return nil; - } - - //printf("jakob auskommentierte Assertion in line 267 ObjectivePGP.m"); - //NSAssert(eskPacket, @"Valid PublicKeyEncryptedSessionKeyPacket not found"); - if (!eskPacket) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Valid PublicKeyEncryptedSessionKeyPacket not found"}]; - } - return nil; - } - - NSAssert(decryptionSecretKeyPacket, @"Decryption secret key packet not found"); - if (!decryptionSecretKeyPacket) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Unable to find secret key"}]; - } - return nil; - } - - - NSData *sessionKeyData = [eskPacket decryptSessionKeyData:decryptionSecretKeyPacket sessionKeyAlgorithm:&sessionKeyAlgorithm error:error]; - NSAssert(sessionKeyAlgorithm > 0, @"Invalid session key algorithm"); - - NSAssert(sessionKeyData, @"Missing session key data"); - if (!sessionKeyData) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Missing session key data"}]; - } - return nil; - } - - // 2 - for (PGPPacket *packet in packets) { - switch (packet.tag) { - case PGPSymmetricallyEncryptedIntegrityProtectedDataPacketTag: - { - // decrypt PGPSymmetricallyEncryptedIntegrityProtectedDataPacket - PGPSymmetricallyEncryptedIntegrityProtectedDataPacket *symEncryptedDataPacket = (PGPSymmetricallyEncryptedIntegrityProtectedDataPacket *)packet; - packets = [symEncryptedDataPacket decryptWithSecretKeyPacket:decryptionSecretKeyPacket sessionKeyAlgorithm:sessionKeyAlgorithm sessionKeyData:sessionKeyData isIntegrityProtected:isIntegrityProtected error:error]; - if (!packets) { - return nil; - } - } - break; - default: - - break; - } - } - - PGPLiteralPacket *literalPacket; - PGPSignaturePacket *signaturePacket; - //PGPOnePassSignaturePacket *onePassPacket; - NSData *plaintextData = nil; - for (PGPPacket *packet in packets) - { - switch (packet.tag) { - case PGPCompressedDataPacketTag: - //break; - case PGPOnePassSignaturePacketTag: - //onePassPacket = (PGPOnePassSignaturePacket *)packet; - break; - case PGPLiteralDataPacketTag: - literalPacket = (PGPLiteralPacket *)packet; - plaintextData = literalPacket.literalRawData; - break; - case PGPSignaturePacketTag: - signaturePacket = (PGPSignaturePacket *)packet; - break; - default: - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Unknown packet (expected literal or compressed)"}]; - } - return nil; - break; - } - } - - PGPTemporaryDecryptionObject* returnValue = [[PGPTemporaryDecryptionObject alloc] init:signaturePacket plaintextData:plaintextData]; - return returnValue; -} - -- (BOOL *) decryptDataSecondPart:(PGPTemporaryDecryptionObject *)temporaryDecryptionObject verifyWithPublicKey:(PGPKey *)publicKey signed:(BOOL*)isSigned valid:(BOOL*)isValid error:(NSError * __autoreleasing *)error -{ - - BOOL _signed = temporaryDecryptionObject.signaturePacket != nil; - BOOL _valid = NO; - if (temporaryDecryptionObject.signaturePacket && publicKey) - { - _valid = [self verifyData:temporaryDecryptionObject.plaintextData withSignature:temporaryDecryptionObject.signaturePacket.packetData usingKey:publicKey error:nil]; - } - if (isSigned) - { - *isSigned = _signed; - } - if (isValid) - { - *isValid = _valid; - } - return isSigned; -} - -//--------------------- Jakob ------------------------- - -- (NSData *) encryptData:(NSData *)dataToEncrypt usingPublicKey:(PGPKey *)publicKey armored:(BOOL)armored error:(NSError * __autoreleasing *)error -{ - return [self encryptData:dataToEncrypt usingPublicKeys:@[publicKey] armored:armored error:error]; -} - -- (NSData *) encryptData:(NSData *)dataToEncrypt usingPublicKeys:(NSArray *)publicKeys armored:(BOOL)armored error:(NSError * __autoreleasing *)error -{ - return [self encryptData:dataToEncrypt usingPublicKeys:publicKeys signWithSecretKey:nil passphrase:nil armored:armored error:error]; -} - -- (NSData *) encryptData:(NSData *)dataToEncrypt usingPublicKeys:(NSArray *)publicKeys signWithSecretKey:(PGPKey *)secretKey passphrase:(NSString *)passphrase armored:(BOOL)armored error:(NSError * __autoreleasing *)error -{ - // Message.prototype.encrypt = function(keys) { - NSMutableData *encryptedMessage = [NSMutableData data]; - - //PGPPublicKeyEncryptedSessionKeyPacket goes here - PGPSymmetricAlgorithm preferredSymmeticAlgorithm = [PGPKey preferredSymmetricAlgorithmForKeys:publicKeys]; - - // Random bytes as a string to be used as a key - NSUInteger keySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:preferredSymmeticAlgorithm]; - uint8_t buf[keySize]; - if (SecRandomCopyBytes(kSecRandomDefault, keySize, buf) == -1) { - return nil; - } - NSMutableData *sessionKeyData = [NSMutableData dataWithBytes:buf length:keySize]; - - for (PGPKey *publicKey in publicKeys) { - // Encrypted Message :- Encrypted Data | ESK Sequence, Encrypted Data. - // Encrypted Data :- Symmetrically Encrypted Data Packet | Symmetrically Encrypted Integrity Protected Data Packet - // ESK :- Public-Key Encrypted Session Key Packet | Symmetric-Key Encrypted Session Key Packet. - - // ESK - PGPPublicKeyPacket *encryptionKeyPacket = (PGPPublicKeyPacket *)[publicKey encryptionKeyPacket:error]; - if (encryptionKeyPacket) { - // var pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey(); - PGPPublicKeyEncryptedSessionKeyPacket *eskKeyPacket = [[PGPPublicKeyEncryptedSessionKeyPacket alloc] init]; - eskKeyPacket.keyID = encryptionKeyPacket.keyID; - eskKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.publicKeyAlgorithm; - [eskKeyPacket encrypt:encryptionKeyPacket sessionKeyData:sessionKeyData sessionKeyAlgorithm:preferredSymmeticAlgorithm error:error]; - NSAssert(!(*error), @"Missing literal data"); - if (*error) { - return nil; - } - [encryptedMessage appendData:[eskKeyPacket exportPacket:error]]; - if (*error) { - return nil; - } - } - } - - NSData *content; - // sign data if requested - if (secretKey) - { - content = [self signData:dataToEncrypt usingSecretKey:secretKey passphrase:passphrase hashAlgorithm:PGPHashSHA512 detached:NO error:error]; - if (*error) { - return nil; - } - - } - else - { - // Prepare literal packet - PGPLiteralPacket *literalPacket = [PGPLiteralPacket literalPacket:PGPLiteralPacketBinary withData:dataToEncrypt]; - literalPacket.filename = nil; - literalPacket.timestamp = [NSDate date]; - NSAssert(!(*error), @"Missing literal data"); - if (*error) { - return nil; - } - NSData *literalPacketData = [literalPacket exportPacket:error]; - if (*error) { - return nil; - } - - PGPCompressedPacket *compressedPacket = [[PGPCompressedPacket alloc] initWithData:literalPacketData type:PGPCompressionBZIP2]; - content = [compressedPacket exportPacket:error]; - if (*error) { - return nil; - } - } - - PGPSymmetricallyEncryptedIntegrityProtectedDataPacket *symEncryptedDataPacket = [[PGPSymmetricallyEncryptedIntegrityProtectedDataPacket alloc] init]; - [symEncryptedDataPacket encrypt:content - symmetricAlgorithm:preferredSymmeticAlgorithm - sessionKeyData:sessionKeyData - error: error]; - - if (*error) { - return nil; - } - - [encryptedMessage appendData:[symEncryptedDataPacket exportPacket:error]]; - if (*error) { - return nil; - } - - if (armored) { - return [PGPArmor armoredData:encryptedMessage as:PGPArmorTypeMessage]; - } - - return [encryptedMessage copy]; -} - -#pragma mark - Sign & Verify - -- (NSData *) signData:(NSData *)dataToSign withKeyForUserID:(NSString *)userID passphrase:(NSString *)passphrase error:(NSError * __autoreleasing *)error -{ - return [self signData:dataToSign withKeyForUserID:userID passphrase:passphrase detached:YES error:error]; -} - -- (NSData *) signData:(NSData *)dataToSign withKeyForUserID:(NSString *)userID passphrase:(NSString *)passphrase detached:(BOOL)detached error:(NSError * __autoreleasing *)error -{ - PGPKey *key = [[self getKeysForUserID:userID] lastObject]; - NSAssert(key, @"Key is missing"); - - if (!key) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Key is missing"}]; - } - return nil; - } - - return [self signData:dataToSign usingSecretKey:key passphrase:passphrase error:error]; -} - -- (NSData *) signData:(NSData *)dataToSign usingSecretKey:(PGPKey *)secretKey passphrase:(NSString *)passphrase error:(NSError * __autoreleasing *)error -{ - return [self signData:dataToSign usingSecretKey:secretKey passphrase:passphrase detached:YES error:error]; -} - -- (NSData *) signData:(NSData *)dataToSign usingSecretKey:(PGPKey *)secretKey passphrase:(NSString *)passphrase detached:(BOOL)detached error:(NSError * __autoreleasing *)error -{ - //TODO: configurable defaults for prefered hash - return [self signData:dataToSign usingSecretKey:secretKey passphrase:passphrase hashAlgorithm:PGPHashSHA512 detached:detached error:error]; -} - -- (NSData *) signData:(NSData *)dataToSign usingSecretKey:(PGPKey *)secretKey passphrase:(NSString *)passphrase hashAlgorithm:(PGPHashAlgorithm)preferedHashAlgorithm detached:(BOOL)detached error:(NSError * __autoreleasing *)error -{ - PGPSignaturePacket *signaturePacket = [PGPSignaturePacket signaturePacket:PGPSignatureBinaryDocument - hashAlgorithm:preferedHashAlgorithm]; - - [signaturePacket signData:dataToSign secretKey:secretKey passphrase:passphrase userID:nil error:error]; - NSError *exportError = nil; - NSData *signaturePacketData = [signaturePacket exportPacket:&exportError]; - NSAssert(!exportError,@"Error on export packet"); - if (exportError) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Error on export packet"}]; - } - return nil; - } - - // Signed Message :- Signature Packet, Literal Message - NSMutableData *signedMessage = [NSMutableData data]; - if (!detached) { - // OnePass - PGPOnePassSignaturePacket *onePassPacket = [[PGPOnePassSignaturePacket alloc] init]; - onePassPacket.signatureType = signaturePacket.type; - onePassPacket.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; - onePassPacket.hashAlgorith = signaturePacket.hashAlgoritm; - - onePassPacket.keyID = [signaturePacket issuerKeyID]; - - onePassPacket.notNested = YES; - NSError *onePassExportError = nil; - [signedMessage appendData:[onePassPacket exportPacket:&onePassExportError]]; - NSAssert(!onePassExportError, @"Missing one password data"); - if (onePassExportError) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing one password data"}]; - } - return nil; - } - - // Literal - PGPLiteralPacket *literalPacket = [PGPLiteralPacket literalPacket:PGPLiteralPacketBinary withData:dataToSign]; - literalPacket.filename = nil; - literalPacket.timestamp = [NSDate date]; - - NSError *literalExportError = nil; - [signedMessage appendData:[literalPacket exportPacket:&literalExportError]]; - NSAssert(!literalExportError, @"Missing literal data"); - if (literalExportError) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing literal data"}]; - } - return nil; - } - -// // Compressed -// NSError *literalExportError = nil; -// PGPCompressedPacket *compressedPacket = [[PGPCompressedPacket alloc] initWithData:[literalPacket exportPacket:&literalExportError] type:PGPCompressionBZIP2]; -// NSAssert(!literalExportError, @"Missing literal data"); -// if (literalExportError) { -// if (error) { -// *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing literal data"}]; -// } -// return nil; -// } -// -// NSError *compressedExportError = nil; -// [signedMessage appendData:[compressedPacket exportPacket:&compressedExportError]]; -// NSAssert(!compressedExportError, @"Missing compressed data"); -// if (compressedExportError) { -// if (error) { -// *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing compressed data"}]; -// } -// return nil; -// } - } - [signedMessage appendData:signaturePacketData]; - return [signedMessage copy]; -} - -- (BOOL) verifyData:(NSData *)signedData withSignature:(NSData *)signatureData error:(NSError * __autoreleasing *)error -{ - if (!signedData || !signatureData) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing input data"}]; - } - return NO; - } - - // search for key in keys - id packet = [PGPPacketFactory packetWithData:signatureData offset:0 nextPacketOffset:NULL]; - if (![packet isKindOfClass:[PGPSignaturePacket class]]) { - NSAssert(false, @"need signature"); - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing signature packet"}]; - } - return NO; - } - - PGPSignaturePacket *signaturePacket = packet; - PGPKeyID *issuerKeyID = [signaturePacket issuerKeyID]; - - PGPKey *issuerKey = [self findKeyForKeyID:issuerKeyID]; - if (!issuerKey) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing issuer"}]; - } - return NO; - } - - return [self verifyData:signedData withSignature:signatureData usingKey:issuerKey error:error]; -} - -- (BOOL) verifyData:(NSData *)signedData withSignature:(NSData *)signatureData usingKey:(PGPKey *)publicKey error:(NSError * __autoreleasing *)error -{ - if (!publicKey || !signatureData || !signatureData) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Invalid input data"}]; - } - return NO; - } - - id packet = [PGPPacketFactory packetWithData:signatureData offset:0 nextPacketOffset:NULL]; - if (![packet isKindOfClass:[PGPSignaturePacket class]]) { - NSAssert(false, @"need signature"); - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing signature"}]; - } - return NO; - } - - PGPSignaturePacket *signaturePacket = packet; - BOOL verified = [signaturePacket verifyData:signedData withKey:publicKey userID:nil error:error]; - - return verified; -} - -- (BOOL) verifyData:(NSData *)signedDataPackets error:(NSError * __autoreleasing *)error -{ - // this is propably not the best solution when it comes to memory consumption - // because literal data is copied more than once (first at parse phase, then when is come to build signature packet data - // I belive this is unecessary but require more work. Schedule to v2.0 - @autoreleasepool { - // search for signature packet - NSMutableArray *accumulatedPackets = [NSMutableArray array]; - NSUInteger offset = 0; - NSUInteger nextPacketOffset; - //TODO: dont parse data here, get raw data and pass to verifyData:withsignature: - while (offset < signedDataPackets.length) { - - PGPPacket *packet = [PGPPacketFactory packetWithData:signedDataPackets offset:offset nextPacketOffset:&nextPacketOffset]; - if (packet) { - [accumulatedPackets addObject:packet]; - } - - offset += nextPacketOffset; - } - - PGPSignaturePacket *signaturePacket = nil; - PGPLiteralPacket *literalDataPacket = nil; - - for (PGPPacket *packet in accumulatedPackets) { - if (packet.tag == PGPSignaturePacketTag) { - signaturePacket = (PGPSignaturePacket *)packet; - } - if (packet.tag == PGPLiteralDataPacketTag) { - literalDataPacket = (PGPLiteralPacket *)packet; - } - } - - NSAssert(signaturePacket && literalDataPacket, @"Missing signature packet or literal data packet"); - if (!signaturePacket || !literalDataPacket) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing signature packet or literal data packet"}]; - } - return NO; - } - - // do not build signature, use data that was readed from signedDataPackets - // to build final data and avoid unecesarry copying data dataWithBytesNoCopy:length:freeWhenDone: is used - // signaturePacket and literalDataPacket is strong in this scope so will not be released - // before verification process end. - NSMutableData *signaturePacketData = [NSMutableData data]; - [signaturePacketData appendData:[NSData dataWithBytesNoCopy:(void *)signaturePacket.headerData.bytes length:signaturePacket.headerData.length freeWhenDone:NO]]; - [signaturePacketData appendData:[NSData dataWithBytesNoCopy:(void *)signaturePacket.bodyData.bytes length:signaturePacket.bodyData.length freeWhenDone:NO]]; - - return [self verifyData:literalDataPacket.literalRawData withSignature:signaturePacketData error:error]; - } -} - -#pragma mark - Parse keyring - -/** - * Load keyring file (secring or pubring) - * - * @param path Path to file - * - * @return YES on success - */ -- (NSArray * __nullable) importKeysFromFile:(NSString * __nonnull)path allowDuplicates:(BOOL)allowDuplicates -{ - if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { - return nil; - } - - return [self importKeysFromData:[NSData dataWithContentsOfFile:path] allowDuplicates:allowDuplicates]; -} - -- (NSArray * __nullable) importKeysFromData:(NSData * __nonnull)data allowDuplicates:(BOOL)allowDuplicates -{ - NSArray *loadedKeys = [self keysFromData:data]; - if (!allowDuplicates) { - NSMutableSet *keysSet = [NSMutableSet setWithArray:self.keys]; - [keysSet addObjectsFromArray:loadedKeys]; - self.keys = [keysSet allObjects]; - } else { - self.keys = [self.keys arrayByAddingObjectsFromArray:loadedKeys]; - } - return loadedKeys; -} - -- (BOOL) importKey:(NSString *)shortKeyStringIdentifier fromFile:(NSString *)path -{ - NSString *fullPath = [path stringByExpandingTildeInPath]; - - NSArray *loadedKeys = [self keysFromFile:fullPath]; - if (loadedKeys.count == 0) { - return NO; - } - - __block BOOL foundKey = NO; - [loadedKeys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - PGPKey *key = obj; - - if ([key.primaryKeyPacket isKindOfClass:[PGPPublicKeyPacket class]]) { - PGPPublicKeyPacket *keyPacket = (PGPPublicKeyPacket *)key.primaryKeyPacket; - if ([[keyPacket.keyID.shortKeyString uppercaseString] isEqualToString:[shortKeyStringIdentifier uppercaseString]]) - { - self.keys = [self.keys arrayByAddingObject:key]; - foundKey = YES; - *stop = YES; - } - } - }]; - - return foundKey; -} - -- (NSArray * __nullable) importPublicKeyFromHeader: (NSString * __nonnull) data allowDuplicates:(BOOL)allowDuplicates -{ - NSMutableDictionary *headers = [@{@"Comment": @"Created with ObjectivePGP", - @"Charset": @"UTF-8"} mutableCopy]; - NSMutableString *headerString = [NSMutableString stringWithString:@"-----"]; - NSMutableString *footerString = [NSMutableString stringWithString:@"-----"]; - [headerString appendString:@"BEGIN PGP PUBLIC KEY BLOCK"]; - [footerString appendString:@"END PGP PUBLIC KEY BLOCK"]; - [headerString appendString:@"-----\n"]; - [footerString appendString:@"-----\n"]; - NSMutableString *armoredMessage = [NSMutableString string]; - // - An Armor Header Line, appropriate for the type of data - [armoredMessage appendString:headerString]; - - // - Armor Headers - for (NSString *key in headers.allKeys) { - [armoredMessage appendFormat:@"%@: %@\n", key, headers[key]]; - } - // - A blank (zero-length, or containing only whitespace) line - [armoredMessage appendString:@"\n"]; - [armoredMessage appendString:data]; - [armoredMessage appendString:@"\n"]; - - // - An Armor Checksum - NSData* binaryData = [[NSData alloc] initWithBase64EncodedString:data options:NSDataBase64DecodingIgnoreUnknownCharacters]; - UInt32 checksum = [binaryData pgp_CRC24]; - UInt8 c[3]; // 24 bit - c[0] = checksum >> 16; - c[1] = checksum >> 8; - c[2] = checksum; - NSData *checksumData = [NSData dataWithBytes:&c length:sizeof(c)]; - [armoredMessage appendString:@"="]; - [armoredMessage appendString:[checksumData base64EncodedStringWithOptions:(NSDataBase64Encoding76CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed)]]; - [armoredMessage appendString:@"\n"]; - - // - The Armor Tail, which depends on the Armor Header Line - [armoredMessage appendString:footerString]; - - NSData *armoredData = [armoredMessage dataUsingEncoding:NSASCIIStringEncoding]; - - return [self importKeysFromData: armoredData allowDuplicates:allowDuplicates]; - - - -} -- (NSArray<PGPKey *> * __nullable) keysFromFile:(NSString * __nonnull)path -{ - NSString *fullPath = [path stringByExpandingTildeInPath]; - - BOOL isDirectory = NO; - if (![[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory]) { - return nil; - } - - if (isDirectory) { - return nil; - } - - NSError *error = nil; - NSData *fileData = [NSData dataWithContentsOfFile:fullPath options:NSDataReadingMappedIfSafe | NSDataReadingUncached error:&error]; - if (!fileData || error) { - return nil; - } - - return [self keysFromData:fileData]; -} - -- (NSArray * __nullable) keysFromData:(NSData * __nonnull)fileData -{ - NSAssert(fileData.length > 0, @"Empty data"); - - NSArray *binRingData = [self convertArmoredMessage2BinaryBlocksWhenNecessary:fileData]; - NSAssert(binRingData.count > 0, @"Invalid input data"); - if (binRingData.count == 0) { - return @[]; - } - - NSMutableSet *keys = [[NSMutableSet alloc] init]; - for (NSData *data in binRingData) { - NSArray *parsedKeys = [self readKeysFromData:data]; - [keys addObjectsFromArray:parsedKeys]; - } - - return keys.allObjects; -} - -#pragma mark - Private - -- (NSArray *) readPacketsFromData:(NSData *)keyringData -{ - NSMutableArray *accumulatedPackets = [NSMutableArray array]; - NSUInteger offset = 0; - NSUInteger nextPacketOffset = 0; - - while (offset < keyringData.length) { - - PGPPacket *packet = [PGPPacketFactory packetWithData:keyringData offset:offset nextPacketOffset:&nextPacketOffset]; - if (packet) { - [accumulatedPackets addObject:packet]; - } - - offset += nextPacketOffset; - } - - return [accumulatedPackets copy]; -} - -/** - * Parse PGP packets data - * - * @param messageData PGP Message data with packets - * - * @return Array of PGPKey - */ -- (NSArray *) readKeysFromData:(NSData *)messageData -{ - NSMutableArray *keys = [NSMutableArray array]; - NSMutableArray *accumulatedPackets = [NSMutableArray array]; - NSUInteger offset = 0; - - while (offset < messageData.length) { - - NSUInteger nextPacketOffset; - PGPPacket *packet = [PGPPacketFactory packetWithData:messageData offset:offset nextPacketOffset:&nextPacketOffset]; - if (packet) { - //NSLog(@"Packet tag: @%hhu", packet.tag); - if ((accumulatedPackets.count > 1) && ((packet.tag == PGPPublicKeyPacketTag) || (packet.tag == PGPSecretKeyPacketTag))) { - PGPKey *key = [[PGPKey alloc] initWithPackets:accumulatedPackets]; - [keys addObject:key]; - [accumulatedPackets removeAllObjects]; - } - [accumulatedPackets addObject:packet]; - } - offset += nextPacketOffset; - } - - if (accumulatedPackets.count > 1) { - PGPKey *key = [[PGPKey alloc] initWithPackets:accumulatedPackets]; - [keys addObject:key]; - [accumulatedPackets removeAllObjects]; - } - - return [keys copy]; -} - -- (PGPKey *) findKeyForKeyID:(PGPKeyID *)keyID -{ - PGPKey *foundKey = nil; - for (PGPKey *key in self.keys) { - for (PGPPublicKeyPacket *keyPacket in key.allKeyPackets) { - if (![keyPacket isKindOfClass:[PGPPublicKeyPacket class]]) { - continue; - } - - if ([keyPacket.keyID isEqualToKeyID:keyID]) { - foundKey = key; - goto found_key_label; - } - } - } - -found_key_label: - return foundKey; -} - -- (NSArray *)convertArmoredMessage2BinaryBlocksWhenNecessary:(NSData *)binOrArmorData { - NSData *binRingData = binOrArmorData; - // detect if armored, check for strin -----BEGIN PGP - if ([PGPArmor isArmoredData:binRingData]) { - NSError *deadmorError = nil; - NSString *armoredString = [[NSString alloc] initWithData:binRingData encoding:NSUTF8StringEncoding]; - - // replace \n to \r\n - // propably unecessary since armore code care about \r\n or \n as newline sentence - armoredString = [armoredString stringByReplacingOccurrencesOfString:@"\r\n" withString:@"\n"]; - armoredString = [armoredString stringByReplacingOccurrencesOfString:@"\n" withString:@"\r\n"]; - - NSMutableArray *extractedStrings = [[NSMutableArray alloc] init]; - NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:@"(-----)(BEGIN|END)[ ](PGP)[A-Z ]*(-----)" options:NSRegularExpressionDotMatchesLineSeparators error:nil]; - __block NSInteger offset = 0; - [regex enumerateMatchesInString:armoredString options:0 range:NSMakeRange(0, armoredString.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) { - NSString *substring = [armoredString substringWithRange:result.range]; - if ([substring containsString:@"END"]) { - NSInteger endIndex = result.range.location + result.range.length; - [extractedStrings addObject:[armoredString substringWithRange:NSMakeRange(offset, endIndex - offset)]]; - } else if ([substring containsString:@"BEGIN"]) { - offset = result.range.location; - } - }]; - - NSMutableArray *extractedData = [[NSMutableArray alloc] init]; - - for (NSString *extractedString in extractedStrings) { - binRingData = [PGPArmor readArmoredData:extractedString error:&deadmorError]; - if (deadmorError) { - return @[]; - } else { - [extractedData addObject:binRingData]; - } - } - - return extractedData; - } - return @[binRingData]; -} - -@end diff --git a/PGPArmor.h b/PGPArmor.h deleted file mode 100644 index 10dab176..00000000 --- a/PGPArmor.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// PGPArmor.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 18/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> - -typedef NS_ENUM(NSUInteger, PGPArmorType) -{ - PGPArmorTypeMessage = 1, - PGPArmorTypePublicKey = 2, - PGPArmorTypeSecretKey = 3, - PGPArmorTypeMultipartMessagePartXOfY = 4, - PGPArmorTypeMultipartMessagePartX = 5, - PGPArmorTypeSignature = 6, - PGPArmorCleartextSignedMessage = 7, //TODO: -----BEGIN PGP SIGNED MESSAGE----- -}; - -@interface PGPArmor : NSObject - -+ (NSData *) armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType part:(NSUInteger)part of:(NSUInteger)ofParts; -+ (NSData *) armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType; - -+ (NSData *) readArmoredData:(NSString *)armoredString error:(NSError * __autoreleasing *)error; - -+ (BOOL) isArmoredData:(NSData *)data; - -@end diff --git a/PGPCryptoCFB.h b/PGPCryptoCFB.h deleted file mode 100644 index d9461acc..00000000 --- a/PGPCryptoCFB.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// PGPCryptoCFB.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 05/06/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" -#import "PGPS2K.h" - -@interface PGPCryptoCFB : NSObject - -+ (NSData *) decryptData:(NSData *)encryptedData - sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase - symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm - iv:(NSData *)ivData; - -+ (NSData *) encryptData:(NSData *)encryptedData - sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase - symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm - iv:(NSData *)ivData; - -@end diff --git a/PGPCryptoUtils.h b/PGPCryptoUtils.h deleted file mode 100644 index 2aa329bf..00000000 --- a/PGPCryptoUtils.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// PGPCryptoUtils.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 12/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" - -@interface PGPCryptoUtils : NSObject - -+ (NSUInteger) blockSizeOfSymmetricAlhorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm; -+ (NSUInteger) keySizeOfSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm; -+ (NSUInteger) hashSizeOfHashAlhorithm:(PGPHashAlgorithm)hashAlgorithm; - -@end diff --git a/PGPKey.h b/PGPKey.h deleted file mode 100644 index 7298a2a7..00000000 --- a/PGPKey.h +++ /dev/null @@ -1,71 +0,0 @@ -// -// PGPTransferableKey.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 13/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" -#import "PGPPacket.h" -#import "PGPKeyID.h" -#import "PGPSignaturePacket.h" - -typedef NS_ENUM(NSUInteger, PGPKeyType) { - PGPKeyUnknown = 0, - PGPKeySecret = 1, - PGPKeyPublic = 2 -}; - -@class PGPSecretKeyPacket; - -@interface PGPKey : NSObject - -@property (assign, readonly ) PGPKeyType type; -@property (strong, nonatomic) PGPPacket *primaryKeyPacket; -@property (assign, readonly ) BOOL isEncrypted; -@property (strong, nonatomic) NSMutableArray *users; // PGPUser -@property (strong, nonatomic) NSMutableArray *subKeys; -@property (strong, nonatomic) NSMutableArray *directSignatures; -@property (strong, nonatomic) PGPPacket *revocationSignature; - -@property (nonatomic, readonly) PGPKeyID *keyID; - -- (instancetype) initWithPackets:(NSArray *)packets; - -/** - * Decrypts all secret key and subkey packets - * Note: After decryption encrypted packets are replaced with new decrypted instances on key. - * Warning: It is not good idea to keep decrypted key around - * - * @param passphrase Password - * @param error error - * - * @return YES on success. - */ -- (BOOL) decrypt:(NSString *)passphrase error:(NSError *__autoreleasing *)error; - -/** - * Signing key packet - * - * @return PGPSecureKeyPacket that can be used to signing - */ -- (PGPPacket *) signingKeyPacket; -- (PGPPacket *) signingKeyPacketWithKeyID:(PGPKeyID *)keyID; -- (PGPPacket *) encryptionKeyPacket:(NSError * __autoreleasing *)error; -- (PGPSecretKeyPacket *) decryptionKeyPacketWithID:(PGPKeyID *)keyID error:(NSError * __autoreleasing *)error; - - -- (NSArray *) allKeyPackets; -- (PGPSymmetricAlgorithm) preferredSymmetricAlgorithm; -+ (PGPSymmetricAlgorithm) preferredSymmetricAlgorithmForKeys:(NSArray *)keys; - -/** - * Export to transferable key packets sequence - * - * @return Data - */ -- (NSData *) export:(NSError *__autoreleasing *)error; - -@end diff --git a/PGPKey.m b/PGPKey.m deleted file mode 100644 index 6ea61349..00000000 --- a/PGPKey.m +++ /dev/null @@ -1,496 +0,0 @@ -// -// PGPTransferableKey.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 13/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPKey.h" -#import "PGPPublicKeyPacket.h" -#import "PGPSecretKeyPacket.h" -#import "PGPUser.h" -#import "PGPSignaturePacket.h" -#import "PGPSignatureSubpacket.h" -#import "PGPPublicSubKeyPacket.h" -#import "PGPSecretSubKeyPacket.h" -#import "PGPUserAttributePacket.h" -#import "PGPUserAttributeSubpacket.h" -#import "PGPSubKey.h" -#import "NSValue+PGPUtils.h" - -@implementation PGPKey - -- (instancetype) initWithPackets:(NSArray *)packets -{ - if (self = [self init]) { - [self loadPackets:packets]; - } - return self; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"Type %@, %@ primary key: %@",self.type == PGPKeyPublic ? @"public" : @"secret", [super description], self.primaryKeyPacket]; -} - -- (BOOL)isEqual:(id)object -{ - if (self == object) - return YES; - - if (![object isKindOfClass:[PGPKey class]]) { - return NO; - } - - //TODO: check all properties - PGPKey *objectKey = (PGPKey *)object; - return [self.keyID isEqual:objectKey.keyID] && (self.type == objectKey.type); -} - -- (NSUInteger)hash -{ -#ifndef NSUINTROTATE -#define NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger)) -#define NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (NSUINT_BIT - howmuch))) -#endif - - NSUInteger hash = [self.primaryKeyPacket hash]; - hash = NSUINTROTATE(hash, NSUINT_BIT / 2) ^ self.type; - hash = NSUINTROTATE(hash, NSUINT_BIT / 2) ^ [self.users hash]; - hash = NSUINTROTATE(hash, NSUINT_BIT / 2) ^ [self.subKeys hash]; - hash = NSUINTROTATE(hash, NSUINT_BIT / 2) ^ [self.directSignatures hash]; - hash = NSUINTROTATE(hash, NSUINT_BIT / 2) ^ [self.revocationSignature hash]; - hash = NSUINTROTATE(hash, NSUINT_BIT / 2) ^ [self.keyID hash]; - - return hash; -} - -- (NSMutableArray *)users -{ - if (!_users) { - _users = [NSMutableArray array]; - } - return _users; -} - -- (NSMutableArray *)subKeys -{ - if (!_subKeys) { - _subKeys = [NSMutableArray array]; - } - return _subKeys; -} - -- (NSMutableArray *)directSignatures -{ - if (!_directSignatures) { - _directSignatures = [NSMutableArray array]; - } - return _directSignatures; -} - -- (BOOL)isEncrypted -{ - if (self.type == PGPKeySecret) { - PGPSecretKeyPacket *secretPacket = (PGPSecretKeyPacket *)self.primaryKeyPacket; - return secretPacket.isEncryptedWithPassword; - } - return NO; -} - -- (PGPKeyType)type -{ - PGPKeyType t = PGPKeyUnknown; - - switch (self.primaryKeyPacket.tag) { - case PGPPublicKeyPacketTag: - case PGPPublicSubkeyPacketTag: - t = PGPKeyPublic; - break; - case PGPSecretKeyPacketTag: - case PGPSecretSubkeyPacketTag: - t = PGPKeySecret; - default: - break; - } - - return t; -} - -- (PGPKeyID *)keyID -{ - PGPPublicKeyPacket *primaryKeyPacket = (PGPPublicKeyPacket *)self.primaryKeyPacket; - PGPKeyID *keyID = [[PGPKeyID alloc] initWithFingerprint:primaryKeyPacket.fingerprint]; - return keyID; -} - -- (void) loadPackets:(NSArray *)packets -{ - // based on packetlist2structure - PGPKeyID *primaryKeyID = nil; - PGPSubKey *subKey = nil; - PGPUser *user = nil; - - for (PGPPacket *packet in packets) { - switch (packet.tag) { - case PGPPublicKeyPacketTag: - primaryKeyID = [(PGPPublicKeyPacket *)packet keyID]; - self.primaryKeyPacket = packet; - break; - case PGPSecretKeyPacketTag: - primaryKeyID = [(PGPSecretKeyPacket *)packet keyID]; - self.primaryKeyPacket = packet; - break; - case PGPUserAttributePacketTag: - if (!user) { - continue; - } - user.userAttribute = (PGPUserAttributePacket *)packet; - break; - case PGPUserIDPacketTag: - { - PGPUser *parsedUser = [[PGPUser alloc] initWithUserIDPacket:(PGPUserIDPacket *)packet]; - if (!user) { - user = parsedUser; - } - [self.users addObject:parsedUser]; - } - break; - case PGPPublicSubkeyPacketTag: - case PGPSecretSubkeyPacketTag: - user = nil; - subKey = [[PGPSubKey alloc] initWithPacket:packet]; - [self.subKeys addObject:subKey]; - break; - case PGPSignaturePacketTag: - { - PGPSignaturePacket *signaturePacket = (PGPSignaturePacket *)packet; - switch (signaturePacket.type) { - case PGPSignatureGenericCertificationUserIDandPublicKey: - case PGPSignatureCasualCertificationUserIDandPublicKey: - case PGPSignaturePositiveCertificationUserIDandPublicKey: - case PGPSignaturePersonalCertificationUserIDandPublicKey: - if (!user) { - continue; - } - if ([signaturePacket.issuerKeyID isEqual:primaryKeyID]) { - user.selfCertifications = [user.selfCertifications arrayByAddingObject:packet]; - } else { - user.otherSignatures = [user.otherSignatures arrayByAddingObject:packet]; - } - break; - case PGPSignatureCertificationRevocation: - if (user) { - user.revocationSignatures = [user.revocationSignatures arrayByAddingObject:packet]; - } else { - [self.directSignatures addObject:packet]; - } - break; - case PGPSignatureDirectlyOnKey: - [self.directSignatures addObject:packet]; - break; - case PGPSignatureSubkeyBinding: - if (!subKey) { - continue; - } - subKey.bindingSignature = (PGPSignaturePacket *)packet; - break; - case PGPSignatureKeyRevocation: - self.revocationSignature = (PGPSignaturePacket *)packet; - break; - case PGPSignatureSubkeyRevocation: - if (!subKey) { - continue; - } - subKey.revocationSignature = (PGPSignaturePacket *)packet; - break; - default: - break; - } - } - break; - default: - break; - } - } -} - -// signature packet that is available for signing data -- (PGPPacket *) signingKeyPacket -{ - // It's private key for sign and public for verify as so thi can't be checked here - - NSAssert(self.type == PGPKeySecret, @"Need secret key to sign"); - if (self.type == PGPKeyPublic) { - NSLog(@"Need secret key to sign\n %@",[NSThread callStackSymbols]); - return nil; - } - - // check primary user self certificates - PGPSignaturePacket *primaryUserSelfCertificate = nil; - [self primaryUserAndSelfCertificate:&primaryUserSelfCertificate]; - if (primaryUserSelfCertificate) - { - if (primaryUserSelfCertificate.canBeUsedToSign) { - return self.primaryKeyPacket; - } - } - - for (PGPSubKey *subKey in self.subKeys) { - PGPSignaturePacket *signaturePacket = subKey.bindingSignature; - if (signaturePacket.canBeUsedToSign) { - return subKey.primaryKeyPacket; - } - } - - return nil; -} - -// signature packet that is available for verifying signature with a keyID -- (PGPPacket *) signingKeyPacketWithKeyID:(PGPKeyID *)keyID -{ - // check primary user self certificates - PGPSignaturePacket *primaryUserSelfCertificate = nil; - [self primaryUserAndSelfCertificate:&primaryUserSelfCertificate]; - if (primaryUserSelfCertificate) - { - if ([self.keyID isEqualToKeyID:keyID]) - { - if (primaryUserSelfCertificate.canBeUsedToSign) { - return self.primaryKeyPacket; - } - } - } - - for (PGPSubKey *subKey in self.subKeys) { - if ([subKey.keyID isEqualToKeyID:keyID]) - { - PGPSignaturePacket *signaturePacket = subKey.bindingSignature; - if (signaturePacket.canBeUsedToSign) { - return subKey.primaryKeyPacket; - } - } - } - - return nil; -} - -// signature packet that is available for signing data -- (PGPPacket *) encryptionKeyPacket:(NSError * __autoreleasing *)error -{ - NSAssert(self.type == PGPKeyPublic, @"Need public key to encrypt"); - if (self.type == PGPKeySecret) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Wrong key type, require public key"}]; - } - NSLog(@"Need public key to encrypt"); - return nil; - } - - for (PGPSubKey *subKey in self.subKeys) { - PGPSignaturePacket *signaturePacket = subKey.bindingSignature; - if (signaturePacket.canBeUsedToEncrypt) { - return subKey.primaryKeyPacket; - } - } - - // check primary user self certificates - PGPSignaturePacket *primaryUserSelfCertificate = nil; - [self primaryUserAndSelfCertificate:&primaryUserSelfCertificate]; - if (primaryUserSelfCertificate) - { - if (primaryUserSelfCertificate.canBeUsedToEncrypt) { - return self.primaryKeyPacket; - } - } - - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Encryption key not found"}]; - } - - return nil; -} - -- (PGPSecretKeyPacket *) decryptionKeyPacketWithID:(PGPKeyID *)keyID error:(NSError * __autoreleasing *)error -{ - NSAssert(self.type == PGPKeySecret, @"Need secret key to encrypt"); - if (self.type == PGPKeyPublic) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Wrong key type, require secret key"}]; - } - NSLog(@"Need public key to encrypt"); - return nil; - } - - for (PGPSubKey *subKey in self.subKeys) { - PGPSignaturePacket *signaturePacket = subKey.bindingSignature; - if (signaturePacket.canBeUsedToEncrypt && [((PGPSecretKeyPacket *)subKey.primaryKeyPacket).keyID isEqualToKeyID:keyID]) { - return (PGPSecretKeyPacket *)subKey.primaryKeyPacket; - } - } - - if ([((PGPSecretKeyPacket *)self.primaryKeyPacket).keyID isEqualToKeyID:keyID]) - { - // assume primary key is always cabable - return (PGPSecretKeyPacket *)self.primaryKeyPacket; - } - return nil; -} - -// Note: After decryption encrypted packets are replaced with new decrypted instances on key. -- (BOOL) decrypt:(NSString *)passphrase error:(NSError *__autoreleasing *)error -{ - if ([self.primaryKeyPacket isKindOfClass:[PGPSecretKeyPacket class]]) { - PGPSecretKeyPacket *secretPacket = (PGPSecretKeyPacket *)self.primaryKeyPacket; - self.primaryKeyPacket = [secretPacket decryptedKeyPacket:passphrase error:error]; - if (*error) { - return NO; - } - } - - for (PGPSubKey *subKey in self.subKeys) { - if ([subKey.primaryKeyPacket isKindOfClass:[PGPSecretKeyPacket class]]) { - PGPSecretKeyPacket *secretPacket = (PGPSecretKeyPacket *)subKey.primaryKeyPacket; - self.primaryKeyPacket = [secretPacket decryptedKeyPacket:passphrase error:error]; - if (*error) { - return NO; - } - } - } - return YES; -} - -- (NSData *) export:(NSError *__autoreleasing *)error -{ - NSMutableData *result = [NSMutableData data]; - - for (PGPPacket * packet in [self allPacketsArray]) { - [result appendData:[packet exportPacket:error]]; //TODO: decode secret key first - if (error) { - NSAssert(*error == nil,@"Error while export public key"); - if (*error) { - return nil; - } - } - } - return [result copy]; -} - -#pragma mark - Verification - -// Returns primary user with self certificate -- (PGPUser *) primaryUserAndSelfCertificate:(PGPSignaturePacket * __autoreleasing *)selfCertificateOut -{ - PGPUser *foundUser = nil; - - for (PGPUser *user in self.users) { - if (!user.userID || user.userID.length == 0) { - continue; - } - - PGPSignaturePacket *selfCertificate = [user validSelfCertificate:self]; - if (!selfCertificate) { - continue; - } - - if (selfCertificate.isPrimaryUserID) { - foundUser = user; - } else if (!foundUser) { - foundUser = user; - } - *selfCertificateOut = selfCertificate; - } - return foundUser; -} - -#pragma mark - Preferences - -- (PGPSymmetricAlgorithm) preferredSymmetricAlgorithm -{ - return [[self class] preferredSymmetricAlgorithmForKeys:@[self]]; -} - -+ (PGPSymmetricAlgorithm) preferredSymmetricAlgorithmForKeys:(NSArray *)keys -{ - // 13.2. Symmetric Algorithm Preferences - // Since TripleDES is the MUST-implement algorithm, if it is not explicitly in the list, it is tacitly at the end. - - NSMutableArray *preferecesArray = [NSMutableArray array]; - for (PGPKey *key in keys) { - NSMutableArray *keyAlgorithms = [NSMutableArray array]; - - PGPSignaturePacket *selfCertificate = nil; - PGPUser *primaryUser = [key primaryUserAndSelfCertificate:&selfCertificate]; - if (primaryUser && selfCertificate) { - PGPSignatureSubpacket *subpacket = [[selfCertificate subpacketsOfType:PGPSignatureSubpacketTypePreferredSymetricAlgorithm] firstObject]; - NSArray *preferencesArray = subpacket.value; - for (NSValue *preferedValue in preferencesArray) { - if ([preferedValue pgp_objCTypeIsEqualTo:@encode(PGPSymmetricAlgorithm)]) { - PGPSymmetricAlgorithm algorithm = PGPSymmetricPlaintext; - [preferedValue getValue:&algorithm]; - [keyAlgorithms addObject:@(algorithm)]; - } - } - } - - if (keyAlgorithms.count > 0) { - [preferecesArray addObject:keyAlgorithms]; - } - } - - // intersect - if (preferecesArray.count > 0) { - NSMutableOrderedSet *set = [NSMutableOrderedSet orderedSetWithArray:preferecesArray[0]]; - for (NSArray *prefArray in preferecesArray) { - [set intersectSet:[NSSet setWithArray:prefArray]]; - } - return [set[0] unsignedIntValue]; - } - - return PGPSymmetricTripleDES; -} - -#pragma mark - Private - -/** - * Ordered list of packets. Trust Packet is not exported. - * - * @return array - */ -- (NSArray *)allPacketsArray -{ - //TODO: handle trust packet somehow. The Trust packet is used only within keyrings and is not normally exported. - NSMutableArray *arr = [NSMutableArray array]; - - [arr addObject:self.primaryKeyPacket]; - - if (self.revocationSignature) { - [arr addObject:self.revocationSignature]; - } - - for (id packet in self.directSignatures) { - [arr addObject:packet]; - } - - for (PGPUser *user in self.users) { - [arr addObjectsFromArray:[user allPackets]]; - } - - for (PGPSubKey *subKey in self.subKeys) { - [arr addObjectsFromArray:[subKey allPackets]]; - } - - return [arr copy]; -} - -- (NSArray *)allKeyPackets -{ - NSMutableArray *arr = [NSMutableArray arrayWithObject:self.primaryKeyPacket]; - for (PGPSubKey *subKey in self.subKeys) { - [arr addObject:subKey.primaryKeyPacket]; - } - return [arr copy]; -} - -@end diff --git a/PGPKeyID.h b/PGPKeyID.h deleted file mode 100644 index a546c690..00000000 --- a/PGPKeyID.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// PGPKeyID.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 06/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPFingerprint.h" - -@interface PGPKeyID : NSObject - -@property (readonly, nonatomic) NSData *longKey; -@property (readonly, nonatomic) NSString *longKeyString; -@property (readonly, nonatomic) NSData *shortKey; -@property (readonly, nonatomic) NSString *shortKeyString; - -- (instancetype) initWithFingerprint:(PGPFingerprint *)fingerprint; -- (instancetype) initWithLongKey:(NSData *)longKeyData; - -- (BOOL) isEqualToKeyID:(PGPKeyID *)keyID; - -- (NSData *)exportKeyData; - -@end diff --git a/PGPKeyID.m b/PGPKeyID.m deleted file mode 100644 index e0fc0e08..00000000 --- a/PGPKeyID.m +++ /dev/null @@ -1,104 +0,0 @@ -// -// PGPKeyID.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 06/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// -// Fingerprint: 4772 3A3C EE12 760F 7DC8 4AE0 1B63 BCB7 E810 38C6 -// Long Key ID: 1B63 BCB7 E810 38C6 <- this -// Short Key ID: E810 38C6 - -#import "PGPKeyID.h" - -@implementation PGPKeyID - -- (instancetype) initWithFingerprint:(PGPFingerprint *)fingerprint -{ - if (!fingerprint) - return nil; - - if (self = [self initWithLongKey:[fingerprint.hashedData subdataWithRange:(NSRange){fingerprint.hashLength - 8,8}]]) { - - } - - return self; -} - -- (instancetype) initWithLongKey:(NSData *)longKeyData -{ - if (longKeyData.length != 8) { - return nil; - } - - if (self = [self init]) { - _longKey = longKeyData; - } - return self; -} - -- (NSString *)description -{ - return [self longKeyString]; -} - -- (NSData *)exportKeyData -{ - return [_longKey copy]; -} - -- (BOOL)isEqual:(id)object -{ - if (self == object) { - return YES; - } - - if ([self class] != [object class]) { - return NO; - } - - PGPKeyID *other = object; - return [self.longKey isEqualToData:other.longKey]; -} - -- (BOOL) isEqualToKeyID:(PGPKeyID *)keyID -{ - return [self isEqual:keyID]; -} - -- (NSUInteger)hash -{ - const NSUInteger prime = 31; - NSUInteger result = 1; - result = prime * result + [_longKey hash]; - return result; -} - -- (NSData *)shortKey -{ - return [self.longKey subdataWithRange:(NSRange){4,4}]; -} - -- (NSString *)shortKeyString -{ - NSData *sKey = self.shortKey; - NSMutableString *sbuf = [NSMutableString stringWithCapacity:sKey.length * 2]; - const unsigned char *buf = sKey.bytes; - for (NSUInteger i = 0; i < sKey.length; ++i) { - [sbuf appendFormat:@"%02X", (unsigned int)buf[i]]; - } - return [sbuf copy]; -} - -- (NSString *)longKeyString -{ - NSData *lKey = self.longKey; - NSMutableString *sbuf = [NSMutableString stringWithCapacity:lKey.length * 2]; - const unsigned char *buf = lKey.bytes; - for (NSUInteger i = 0; i < lKey.length; ++i) { - [sbuf appendFormat:@"%02X", (unsigned int)buf[i]]; - } - return [sbuf copy]; -} - -@end diff --git a/PGPLiteralPacket.h b/PGPLiteralPacket.h deleted file mode 100644 index d5bffdd7..00000000 --- a/PGPLiteralPacket.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// PGPLiteralPacket.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 24/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPacket.h" - -typedef NS_ENUM(UInt8, PGPLiteralPacketFormat) { - PGPLiteralPacketBinary = 'b', - PGPLiteralPacketText = 't', - PGPLiteralPacketTextUTF8 = 'u' -}; - -@interface PGPLiteralPacket : PGPPacket - -@property (assign) PGPLiteralPacketFormat format; -@property (strong) NSDate *timestamp; -@property (strong) NSString *filename; - -@property (strong) NSData *literalRawData; - -- (instancetype) initWithData:(NSData *)rawData; -+ (PGPLiteralPacket *) literalPacket:(PGPLiteralPacketFormat)format withData:(NSData *)rawData; - -@end diff --git a/PGPMPI.h b/PGPMPI.h deleted file mode 100644 index 7f1a84f5..00000000 --- a/PGPMPI.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// OpenPGPMPI.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import <openssl/bn.h> - -@interface PGPMPI : NSObject - -@property (strong) NSString *identifier; -@property (assign, readonly) BIGNUM *bignumRef; -/** - * Total bytes, header + body - */ -@property (assign, readonly) NSUInteger packetLength; - -- (instancetype) initWithMPIData:(NSData *)mpiData atPosition:(NSUInteger)position; -- (instancetype) initWithData:(NSData *)dataToMPI; -- (NSData *) exportMPI; -- (NSData *) bodyData; - -@end diff --git a/PGPMPI.m b/PGPMPI.m deleted file mode 100644 index c2a0491e..00000000 --- a/PGPMPI.m +++ /dev/null @@ -1,101 +0,0 @@ -// -// OpenPGPMPI.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// -// Multiprecision integers (also called MPIs) are unsigned integers used -// to hold large integers such as the ones used in cryptographic -// calculations. - -#import "PGPMPI.h" - -@interface PGPMPI () -@property (assign, readwrite) BIGNUM *bignumRef; -@property (assign, readwrite) NSUInteger packetLength; -@end - -@implementation PGPMPI - -- (instancetype) initWithData:(NSData *)dataToMPI -{ - if (self = [self init]) { - _bignumRef = BN_bin2bn(dataToMPI.bytes, dataToMPI.length & INT_MAX, NULL); - _packetLength = dataToMPI.length + 2; - } - return self; -} - -// parse mpi "packet" -- (instancetype) initWithMPIData:(NSData *)mpiData atPosition:(NSUInteger)position -{ - if (self = [self init]) { - UInt16 bitsBE = 0; - [mpiData getBytes:&bitsBE range:(NSRange){position,2}]; - UInt16 bits = CFSwapInt16BigToHost(bitsBE); - NSUInteger mpiBytesLength = (bits + 7) / 8; - - NSData *intdata = [mpiData subdataWithRange:(NSRange){position + 2, mpiBytesLength}]; - _bignumRef = BN_bin2bn(intdata.bytes, intdata.length & INT_MAX, NULL); - // Additinal rule: The size of an MPI is ((MPI.length + 7) / 8) + 2 octets. - _packetLength = intdata.length + 2; - } - return self; -} - -- (NSData *)bodyData -{ - NSAssert(self.bignumRef, @"Missing bignumRef"); - - if (!self.bignumRef) - return nil; - - BIGNUM *mpi_BN = BN_dup(self.bignumRef); - NSInteger mpi_BN_length = (BN_num_bits(mpi_BN) + 7) / 8; - UInt8 *bn_bin = calloc(mpi_BN_length, sizeof(UInt8)); - NSUInteger len = BN_bn2bin(mpi_BN, bn_bin); - BN_free(mpi_BN); - - NSData *data = [NSData dataWithBytes:bn_bin length:len]; - free(bn_bin); - return data; -} - -- (NSData *) exportMPI -{ - if (!self.bignumRef) { - return nil; - } - - NSMutableData *outData = [NSMutableData data]; - - // length - UInt16 bits = BN_num_bits(self.bignumRef); - UInt16 bitsBE = CFSwapInt16HostToBig(bits); - [outData appendBytes:&bitsBE length:2]; - - // mpi - UInt8 *buf = calloc(BN_num_bytes(self.bignumRef), sizeof(UInt8)); - UInt16 bytes = (bits + 7) / 8; - BN_bn2bin(self.bignumRef, buf); - [outData appendBytes:buf length:bytes]; - free(buf); - - return [outData copy]; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@, \"%@\", %@ bytes, total: %@ bytes", [super description], self.identifier, @(BN_num_bytes(self.bignumRef)), @(_packetLength)]; -} - -- (void)dealloc -{ - if (self.bignumRef != NULL) { - BN_clear_free(self.bignumRef); - _bignumRef = nil; - } -} - -@end diff --git a/PGPOnePassSignaturePacket.h b/PGPOnePassSignaturePacket.h deleted file mode 100644 index 73ec8950..00000000 --- a/PGPOnePassSignaturePacket.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PGPOnePassSignaturePacket.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 29/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPacket.h" - -@class PGPKeyID; - -@interface PGPOnePassSignaturePacket : PGPPacket -@property (assign) UInt8 version; // The current version is 3. -@property (assign) PGPSignatureType signatureType; -@property (assign) PGPHashAlgorithm hashAlgorith; -@property (assign) PGPPublicKeyAlgorithm publicKeyAlgorithm; -@property (assign) PGPKeyID *keyID; // 8 -@property (assign) BOOL notNested; -@end diff --git a/PGPPacket.h b/PGPPacket.h deleted file mode 100644 index 679c36a7..00000000 --- a/PGPPacket.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// PGPPacket.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 06/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" - -extern const UInt32 UnknownLength; - -@interface PGPPacket : NSObject <NSCopying> - -@property (copy, readonly) NSData *headerData; -@property (copy, readonly) NSData *bodyData; -@property (assign) BOOL indeterminateLength; // should not be used, but gpg use it - -@property (assign, readonly) PGPPacketTag tag; -@property (readonly) NSData *packetData; - -- (instancetype) init NS_DESIGNATED_INITIALIZER; -- (instancetype) initWithHeader:(NSData *)headerData body:(NSData *)bodyData; - -+ (NSData *) parsePacketHeader:(NSData*)data headerLength:(UInt32 *)headerLength nextPacketOffset:(NSUInteger *)nextPacketOffset packetTag:(PGPPacketTag *)tag indeterminateLength:(BOOL*)indeterminateLength; -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error; - -- (NSData *) exportPacket:(NSError *__autoreleasing *)error; - -- (NSData *) buildHeaderData:(NSData *)bodyData; -+ (NSData *) buildNewFormatLengthDataForData:(NSData *)bodyData; - -@end \ No newline at end of file diff --git a/PGPPacket.m b/PGPPacket.m deleted file mode 100644 index cd8f1c22..00000000 --- a/PGPPacket.m +++ /dev/null @@ -1,317 +0,0 @@ -// -// PGPPacket.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 06/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPacket.h" -#import "NSData+PGPUtils.h" - -const UInt32 UnknownLength = UINT32_MAX; - -@interface PGPPacket () -@property (copy, readwrite) NSData *headerData; -@property (copy, readwrite) NSData *bodyData; -@end - -@implementation PGPPacket - -- (instancetype)init -{ - if (self = [super init]) { - - } - return self; -} - -- (instancetype)initWithHeader:(NSData *)headerData body:(NSData *)bodyData -{ - if (self = [self init]) { - NSError *error = nil; - _headerData = headerData; - _bodyData = bodyData; - [self parsePacketBody:self.bodyData error:&error]; - if (error) { - return nil; - } - } - return self; -} - - -- (NSUInteger)hash -{ -#ifndef NSUINTROTATE - #define NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger)) - #define NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (NSUINT_BIT - howmuch))) -#endif - - NSUInteger hash = [self.headerData hash]; - hash = NSUINTROTATE(hash, NSUINT_BIT / 2) ^ [self.bodyData hash]; - return hash; -} - - -- (NSUInteger) parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - NSAssert(packetBody.length == self.bodyData.length, @"length mismach"); - return 0; -} - -- (NSData *) exportPacket:(NSError *__autoreleasing *)error -{ - [NSException raise:@"MissingExportMethod" format:@"export: selector not overriden"]; - return nil; -} - -#pragma mark - Packet header - -// 4.2. Packet Headers -/** - * Parse header - * - * @param headerData header data - * - * @return Body data, headerLength, packetTag, nextPacketOffset and if body has indeterminateLength - */ -+ (NSData *) parsePacketHeader:(NSData*)data headerLength:(UInt32 *)headerLength nextPacketOffset:(NSUInteger *)nextPacketOffset packetTag:(PGPPacketTag *)tag indeterminateLength:(BOOL*)indeterminateLength -{ - UInt8 headerByte = 0; - [data getBytes:&headerByte range:(NSRange){0,1}]; - - - BOOL isPGPHeader = !!(headerByte & PGPHeaderPacketTagAllwaysSet); - BOOL isNewFormat = !!(headerByte & PGPHeaderPacketTagNewFormat); - BOOL isPartialBodyLength = NO; - - if (!isPGPHeader) { - return nil; - } - UInt32 bodyLength; - if (isNewFormat) { - *headerLength = [self parseNewFormatHeaderPacket:data bodyLength:&bodyLength packetTag:tag partialBodyLength:&isPartialBodyLength]; - } else { - *headerLength = [self parseOldFormatHeaderPacket:data bodyLength:&bodyLength packetTag:tag]; - } - if (indeterminateLength) *indeterminateLength = NO; - if (bodyLength == UnknownLength) - { - bodyLength = (UInt32)data.length - *headerLength; - if (indeterminateLength) *indeterminateLength = YES; - } - if (nextPacketOffset != NULL) *nextPacketOffset = bodyLength + *headerLength; - if (isPartialBodyLength) - { - UInt32 offset = *headerLength; - NSMutableData *resultData = [NSMutableData dataWithData:[data subdataWithRange:(NSRange){offset, bodyLength}]]; - offset += bodyLength; - do - { - // assume new header format - PGPPacketTag nextTag; - UInt32 packetBodyLength; - UInt32 packetHeaderLength = [self parseNewFormatHeaderPacket:[data subdataWithRange:(NSRange){offset-1, data.length - (offset-1)}] bodyLength:&packetBodyLength packetTag:&nextTag partialBodyLength:&isPartialBodyLength] - 1; - offset += packetHeaderLength; - if (nextPacketOffset != NULL) *nextPacketOffset += packetHeaderLength + packetBodyLength; - [resultData appendData:[data subdataWithRange:(NSRange){offset, MIN(packetBodyLength, data.length-offset)}]]; - offset += packetBodyLength; - } - while (isPartialBodyLength); - return resultData; - } - return [data subdataWithRange:(NSRange){*headerLength, bodyLength}]; -} - -/** - * 4.2. Packet Headers - * - * @param packetData Packet header - * - * @return Header length - */ -+ (UInt32) parseNewFormatHeaderPacket:(NSData *)headerData bodyLength:(UInt32 *)length packetTag:(PGPPacketTag *)tag partialBodyLength:(BOOL *)isPartialBodyLength -{ - NSParameterAssert(headerData); - - UInt8 headerByte = 0; - [headerData getBytes:&headerByte length:1]; - // Bits 5-0 -- packet tag - UInt8 packetTag = (headerByte << 2); - packetTag = (packetTag >> 2); - *tag = packetTag; - - // body length - *isPartialBodyLength = NO; - UInt32 bodyLength = 0; - UInt32 headerLength = 2; - - UInt8 *lengthOctets = (UInt8 *)[headerData subdataWithRange:NSMakeRange(1, MIN(5, headerData.length))].bytes; - UInt8 firstOctet = lengthOctets[0]; - - if (lengthOctets[0] < 192) { - // 4.2.2.1. One-Octet Length - // bodyLen = 1st_octet; - bodyLength = lengthOctets[0]; - headerLength = 1 + 1; - } else if (lengthOctets[0] >= 192 && lengthOctets[0] < 224) { - // 4.2.2.2. Two-Octet Lengths - // bodyLen = ((1st_octet - 192) << 8) + (2nd_octet) + 192 - bodyLength = ((lengthOctets[0] - 192) << 8) + (lengthOctets[1]) + 192; - headerLength = 1 + 2; - } else if (lengthOctets[0] >= 224 && lengthOctets[0] < 255) { - // 4.2.2.4. Partial Body Length - // partialBodyLen = 1 << (1st_octet & 0x1F); - UInt32 partianBodyLength = 1 << (lengthOctets[0] & 0x1F); - bodyLength = partianBodyLength; - headerLength = 1 + 1; - *isPartialBodyLength = YES; - } else if (firstOctet == 255) { - // 4.2.2.3. Five-Octet Length - // bodyLen = (2nd_octet << 24) | (3rd_octet << 16) | - // (4th_octet << 8) | 5th_octet - bodyLength = (lengthOctets[1] << 24) | (lengthOctets[2] << 16) | (lengthOctets[3] << 8) | lengthOctets[4]; - headerLength = 1 + 5; - } - *length = bodyLength; - - NSAssert(bodyLength > 0, @"The packet is of indeterminate length"); - - return headerLength; -} - -// 4.2. Packet Headers -+ (UInt32) parseOldFormatHeaderPacket:(NSData *)headerData bodyLength:(UInt32 *)length packetTag:(PGPPacketTag *)tag -{ - NSParameterAssert(headerData); - - UInt8 headerByte = 0; - [headerData getBytes:&headerByte length:1]; - // Bits 5-2 -- packet tag - UInt8 packetTag = (headerByte << 2); - packetTag = (packetTag >> 4); - *tag = packetTag; - // Bits 1-0 -- length-type - UInt8 bodyLengthType = (headerByte << 6); - bodyLengthType = bodyLengthType >> 6; - - UInt32 headerLength = 1; - UInt32 bodyLength = 0; - switch (bodyLengthType) { - case 0: - { - NSRange range = (NSRange) {1,1}; - [headerData getBytes:&bodyLength range:range]; - headerLength = (UInt32)(1 + range.length); - } - break; - case 1: - { - UInt16 bLen = 0; - NSRange range = (NSRange) {1,2}; - [headerData getBytes:&bLen range:range]; - // value of a two-octet scalar is ((n[0] << 8) + n[1]). - bodyLength = CFSwapInt16BigToHost(bLen); - headerLength = (UInt32)(1 + range.length); - } - break; - case 2: - { - NSRange range = (NSRange) {1,4}; - [headerData getBytes:&bodyLength range:range]; - bodyLength = CFSwapInt32BigToHost(bodyLength); - headerLength = (UInt32)(1 + range.length); - } - break; - case 3: - { -#ifdef DEBUG - NSLog(@"(Old) The packet is of indeterminate length - partially supported"); -#endif - bodyLength = UnknownLength; - headerLength = 1; - } - break; - - default: - break; - } - - NSAssert(bodyLength > 0, @"Invalid packet length"); - *length = bodyLength; - - return headerLength; -} - -- (NSData *) buildHeaderData:(NSData *)bodyData -{ - //TODO: check all formats, untested - //4.2.2. New Format Packet Lengths - NSMutableData *data = [NSMutableData data]; - - // Bit 7 -- Always one - // Bit 6 -- New packet format if set - UInt8 packetTag = PGPHeaderPacketTagAllwaysSet | PGPHeaderPacketTagNewFormat; - - // Bits 5-0 -- packet tag - packetTag |= self.tag; - - // write ptag - [data appendBytes:&packetTag length:1]; - [data appendData:[PGPPacket buildNewFormatLengthDataForData:bodyData]]; - - return [data copy]; -} - -+ (NSData *)buildNewFormatLengthDataForData:(NSData *)bodyData -{ - NSMutableData *data = [NSMutableData data]; - // write length octets - UInt64 bodyLength = bodyData.length; - if (bodyLength < 192) { - // 1 octet - [data appendBytes:&bodyLength length:1]; - } else if (bodyLength >= 192 && bodyLength <= 8383) { - // 2 octet - UInt8 buf[2] = {0,0}; - UInt16 twoOctets = bodyLength; - buf[0] = (UInt8)((twoOctets - 192) >> 8) + 192; - buf[1] = (UInt8)(twoOctets - 192); - [data appendBytes:buf length:2]; - } else { - // 5 octet - UInt64 fiveOctets = bodyLength; - - UInt8 buf[5] = {0xFF,0,0,0,0}; - buf[1] = (UInt8)(fiveOctets >> 24); - buf[2] = (UInt8)(fiveOctets >> 16); - buf[3] = (UInt8)(fiveOctets >> 8); - buf[4] = (UInt8)(fiveOctets); - [data appendBytes:buf length:5]; - } - return [data copy]; - -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone -{ - PGPPacket *copy = [[[self class] allocWithZone:zone] init]; - copy->_bodyData = self.bodyData; - copy->_headerData = self.headerData; - return copy; -} - -#pragma mark - conversion - -- (NSData *)packetData -{ - NSMutableData *result = [NSMutableData data]; - [result appendData:self.headerData]; - [result appendData:self.bodyData]; - return result; -} - -@end diff --git a/PGPPublicKeyEncryptedSessionKeyPacket.h b/PGPPublicKeyEncryptedSessionKeyPacket.h deleted file mode 100644 index 6cc3858c..00000000 --- a/PGPPublicKeyEncryptedSessionKeyPacket.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// PGPPublicKeyEncryptedSessionKeyPacket.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 06/06/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPacket.h" - -@class PGPKeyID, PGPPublicKeyPacket, PGPSecretKeyPacket; - -@interface PGPPublicKeyEncryptedSessionKeyPacket : PGPPacket <NSCopying> -@property (assign) UInt8 version; -@property (strong) PGPKeyID *keyID; -@property (assign) PGPPublicKeyAlgorithm publicKeyAlgorithm; -@property (assign, getter = isEncrypted) BOOL encrypted; - -- (BOOL) encrypt:(PGPPublicKeyPacket *)publicKeyPacket sessionKeyData:(NSData *)sessionKeyData sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm error:(NSError * __autoreleasing *)error; -- (NSData *) decryptSessionKeyData:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm *)sessionKeyAlgorithm error:(NSError * __autoreleasing *)error; - -@end diff --git a/PGPPublicKeyPacket.h b/PGPPublicKeyPacket.h deleted file mode 100644 index 14079872..00000000 --- a/PGPPublicKeyPacket.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// OpenPGPPublicKey.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// -// Tag 6 - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" -#import "PGPPacketFactory.h" -#import "PGPKeyID.h" -#import "PGPFingerprint.h" - -@class PGPMPI; - -@interface PGPPublicKeyPacket : PGPPacket <NSCopying> - -@property (assign, readonly) UInt8 version; -@property (strong, readonly) NSDate* createDate; -@property (assign, readonly) UInt16 V3validityPeriod; // obsolete -@property (assign, readonly) PGPPublicKeyAlgorithm publicKeyAlgorithm; -@property (strong, readwrite) NSArray* publicMPIArray; - -@property (assign, readonly) NSUInteger keySize; - -@property (strong, nonatomic, readonly) PGPFingerprint* fingerprint; -@property (strong, nonatomic, readonly) PGPKeyID* keyID; - -- (NSData*)exportPacket:(NSError* __autoreleasing*)error; -- (NSData*)exportPublicPacketOldStyle; - -- (NSData*)buildPublicKeyBodyData:(BOOL)forceV4; - -- (PGPMPI*)publicMPI:(NSString*)identifier; -- (NSData*)encryptData:(NSData*)data withPublicKeyAlgorithm:(PGPPublicKeyAlgorithm)publicKeyAlgorithm; - -@end diff --git a/PGPPublicKeyPacket.m b/PGPPublicKeyPacket.m deleted file mode 100644 index cbc6929d..00000000 --- a/PGPPublicKeyPacket.m +++ /dev/null @@ -1,324 +0,0 @@ -// -// OpenPGPPublicKey.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPublicKeyPacket.h" -#import "PGPTypes.h" -#import "PGPMPI.h" -#import "NSData+PGPUtils.h" -#import "PGPPublicKeyRSA.h" - -#import <CommonCrypto/CommonCrypto.h> -#import <CommonCrypto/CommonDigest.h> -#import <CommonCrypto/CommonCryptor.h> - -#import <objc/runtime.h> - -@interface PGPPacket () -@property (copy, readwrite) NSData *headerData; -@property (copy, readwrite) NSData *bodyData; -@end - -@interface PGPPublicKeyPacket () -@property (strong, nonatomic, readwrite) PGPFingerprint *fingerprint; -@property (strong, nonatomic, readwrite) PGPKeyID *keyID; -@property (assign, readwrite) UInt16 V3validityPeriod; -@end - -@implementation PGPPublicKeyPacket - -- (PGPPacketTag)tag -{ - return PGPPublicKeyPacketTag; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ %@", [super description], self.keyID]; -} - -- (NSUInteger) keySize -{ - __block NSUInteger ks = 0; - [self.publicMPIArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - PGPMPI *mpi = obj; - if ([mpi.identifier isEqualToString:@"N"]) { - ks = (BN_num_bits(mpi.bignumRef) + 7) / 8; - // BN_num_bytes(rsa->n) - *stop = YES; - } - }]; - return ks; -} - -- (PGPMPI *) publicMPI:(NSString *)identifier -{ - __block PGPMPI *returnMPI = nil; - [self.publicMPIArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - PGPMPI *mpi = obj; - if ([mpi.identifier isEqualToString:identifier]) { - returnMPI = mpi; - *stop = YES; - } - }]; - - return returnMPI; -} - -#pragma mark - KeyID and Fingerprint - -/** - * 12.2. Key IDs and Fingerprints - * - * @return keyID - */ -- (PGPKeyID *)keyID -{ - if (!_keyID) { - _keyID = [[PGPKeyID alloc] initWithFingerprint:self.fingerprint]; - } - - return _keyID; -} - -/** - * 12.2. Key IDs and Fingerprints - * Calculate fingerprint - * - * @return Fingerprint data - */ -- (PGPFingerprint *)fingerprint -{ - if (!_fingerprint) { - _fingerprint = [[PGPFingerprint alloc] initWithData:[self exportPublicPacketOldStyle]]; - } - return _fingerprint; -} - -#pragma mark - Parse data - -/** - * 5.5.2. Public-Key Packet Formats - * - * @param packetBody Packet body - */ -- (NSUInteger) parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - NSUInteger position = [super parsePacketBody:packetBody error:error]; - - // A one-octet version number (2,3,4). - [packetBody getBytes:&_version range:(NSRange){position,1}]; - position = position + 1; - - NSAssert(self.version >= 3, @"To old packet version"); - - // A four-octet number denoting the time that the key was created. - UInt32 timestamp = 0; - [packetBody getBytes:×tamp range:(NSRange){position,4}]; - timestamp = CFSwapInt32BigToHost(timestamp); - _createDate = [NSDate dateWithTimeIntervalSince1970:timestamp]; - position = position + 4; - - //V3 keys are deprecated; an implementation MUST NOT generate a V3 key, but MAY accept it. - if (_version == 0x03) { - // A two-octet number denoting the time in days that this key is - // valid. If this number is zero, then it does not expire. - [packetBody getBytes:&_V3validityPeriod range:(NSRange){position,2}]; - _V3validityPeriod = CFSwapInt16BigToHost(_V3validityPeriod); - position = position + 2; - } - - // A one-octet number denoting the public-key algorithm of this key. - [packetBody getBytes:&_publicKeyAlgorithm range:(NSRange){position,1}]; - position = position + 1; - - // A series of multiprecision integers comprising the key material. - switch (self.publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - case PGPPublicKeyAlgorithmRSASignOnly: - { - // Algorithm-Specific Fields for RSA public keys: - // MPI of RSA public modulus n; - PGPMPI *mpiN = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiN.identifier = @"N"; - position = position + mpiN.packetLength; - - // MPI of RSA public encryption exponent e. - PGPMPI *mpiE = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiE.identifier = @"E"; - position = position + mpiE.packetLength; - - self.publicMPIArray = @[mpiN, mpiE]; - } - break; - case PGPPublicKeyAlgorithmDSA: - case PGPPublicKeyAlgorithmECDSA: - { - // - MPI of DSA prime p; - PGPMPI *mpiP = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiP.identifier = @"P"; - position = position + mpiP.packetLength; - - // - MPI of DSA group order q (q is a prime divisor of p-1); - PGPMPI *mpiQ = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiQ.identifier = @"Q"; - position = position + mpiQ.packetLength; - - // - MPI of DSA group generator g; - PGPMPI *mpiG = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiG.identifier = @"G"; - position = position + mpiG.packetLength; - - // - MPI of DSA public-key value y (= g**x mod p where x is secret). - PGPMPI *mpiY = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiY.identifier = @"Y"; - position = position + mpiY.packetLength; - - self.publicMPIArray = @[mpiP, mpiQ, mpiG, mpiY]; - } - break; - case PGPPublicKeyAlgorithmElgamal: - case PGPPublicKeyAlgorithmElgamalEncryptorSign: - { - // - MPI of Elgamal prime p; - PGPMPI *mpiP = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiP.identifier = @"P"; - position = position + mpiP.packetLength; - - // - MPI of Elgamal group generator g; - PGPMPI *mpiG = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiG.identifier = @"G"; - position = position + mpiG.packetLength; - - // - MPI of Elgamal public key value y (= g**x mod p where x is secret). - PGPMPI *mpiY = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiY.identifier = @"Y"; - position = position + mpiY.packetLength; - - self.publicMPIArray = @[mpiP, mpiG, mpiY]; - } - break; - default: - @throw [NSException exceptionWithName:@"Unknown Algorithm" reason:@"Given algorithm is not supported" userInfo:nil]; - break; - } - - return position; -} - -#pragma mark - Export data - -/** - * Packet data. Header with body data. - * - * @param error error - * - * @return data - */ -- (NSData *) exportPacket:(NSError *__autoreleasing *)error -{ - NSMutableData *data = [NSMutableData data]; - - NSData *bodyData = [self buildPublicKeyBodyData:NO]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - - // it wont match, because input data is OLD world, and we export in NEW world format - // NSAssert([headerData isEqualToData:self.headerData], @"Header not match"); - if ([self class] == [PGPPublicKeyPacket class]) { - NSAssert([bodyData isEqualToData:self.bodyData], @"Body not match"); - } - - return [data copy]; -} - -/** - * Build new style public key data - * - * @return public key data starting with version octet - */ -- (NSData *) buildPublicKeyBodyData:(BOOL)forceV4 -{ - NSMutableData *data = [NSMutableData dataWithCapacity:128]; - [data appendBytes:&_version length:1]; - - UInt32 timestamp = [self.createDate timeIntervalSince1970]; - UInt32 timestampBE = CFSwapInt32HostToBig(timestamp); - [data appendBytes:×tampBE length:4]; - - if (!forceV4 && _version == 0x03) { - // implementation MUST NOT generate a V3 key, but MAY accept it. - // however it have to be generated here to calculate the very same fingerprint - UInt16 V3ValidityPeriodBE = CFSwapInt16HostToBig(_V3validityPeriod); - [data appendBytes:&V3ValidityPeriodBE length:2]; - } - - [data appendBytes:&_publicKeyAlgorithm length:1]; - - // publicMPI is allways available, no need to decrypt - for (PGPMPI *mpi in self.publicMPIArray) { - [data appendData:[mpi exportMPI]]; - } - return [data copy]; -} - -// Old-style packet header for a key packet with two-octet length. -// Old but used by fingerprint and with signing -- (NSData *) exportPublicPacketOldStyle -{ - NSMutableData *data = [NSMutableData data]; - - NSData *publicKeyData = [self buildPublicKeyBodyData:NO]; - - NSUInteger length = publicKeyData.length; - UInt8 upper = length >> 8; - UInt8 lower = length & 0xff; - UInt8 headWithLength[3] = {0x99, upper, lower}; - [data appendBytes:&headWithLength length:3]; - [data appendData:publicKeyData]; - return [data copy]; -} - -#pragma mark - Encrypt & Decrypt - -- (NSData *) encryptData:(NSData *)data withPublicKeyAlgorithm:(PGPPublicKeyAlgorithm)publicKeyAlgorithm -{ - switch (publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - case PGPPublicKeyAlgorithmRSASignOnly: - { - // return ecnrypted m - return [PGPPublicKeyRSA publicEncrypt:data withPublicKeyPacket:self]; - } - break; - default: - //TODO: add algorithms - [NSException raise:@"PGPNotSupported" format:@"Algorith not supported"]; - break; - } - return nil; -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone -{ - PGPPublicKeyPacket *copy = (PGPPublicKeyPacket *)[super copyWithZone:zone]; - copy->_version = self.version; - copy->_createDate = self.createDate; - copy->_V3validityPeriod = self.V3validityPeriod; - copy->_publicKeyAlgorithm = self.publicKeyAlgorithm; - copy->_fingerprint = self.fingerprint; - copy->_keyID = self.keyID; - copy->_publicMPIArray = self.publicMPIArray; - return copy; -} - -@end diff --git a/PGPPublicKeyRSA.h b/PGPPublicKeyRSA.h deleted file mode 100644 index f2f13c6b..00000000 --- a/PGPPublicKeyRSA.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// PGPPublicKeyAlgorithmRSA.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 26/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> - -@class PGPSecretKeyPacket, PGPPublicKeyPacket; - -@interface PGPPublicKeyRSA : NSObject - -// encryption -+ (NSData *) publicEncrypt:(NSData *)toEncrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket; -+ (NSData *) privateDecrypt:(NSData *)toDecrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket; - - -// signature -+ (NSData *) publicDecrypt:(NSData *)toDecrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket; -+ (NSData *) privateEncrypt:(NSData *)toEncrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket; - -@end diff --git a/PGPPublicKeyRSA.m b/PGPPublicKeyRSA.m deleted file mode 100644 index 390331af..00000000 --- a/PGPPublicKeyRSA.m +++ /dev/null @@ -1,248 +0,0 @@ -// -// PGPPublicKeyAlgorithmRSA.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 26/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPublicKeyRSA.h" -#import "PGPPublicKeyPacket.h" -#import "PGPSecretKeyPacket.h" -#import "PGPKey.h" -#import "PGPMPI.h" -#import "PGPPKCSEmsa.h" - -#import <openssl/err.h> -#import <openssl/ssl.h> - -#import <openssl/rsa.h> -#import <openssl/bn.h> - -@implementation PGPPublicKeyRSA - -// encrypts the bytes -+ (NSData *) publicEncrypt:(NSData *)toEncrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket -{ - RSA *rsa = RSA_new(); - if (!rsa) { - return nil; - } - - rsa->n = BN_dup([[publicKeyPacket publicMPI:@"N"] bignumRef]); - rsa->e = BN_dup([[publicKeyPacket publicMPI:@"E"] bignumRef]); - - NSAssert(rsa->n && rsa->e, @"Missing N or E"); - if (!rsa->n || !rsa->e) { - return nil; - } - - uint8_t *encrypted_em = calloc(BN_num_bytes(rsa->n) & SIZE_T_MAX, 1); - int em_len = RSA_public_encrypt(toEncrypt.length & INT_MAX, toEncrypt.bytes, encrypted_em, rsa, RSA_NO_PADDING); - - if (em_len != publicKeyPacket.keySize) { - ERR_load_crypto_strings(); - SSL_load_error_strings(); - - unsigned long err_code = ERR_get_error(); - char *errBuf = calloc(512, sizeof(char)); - ERR_error_string(err_code, errBuf); -#ifdef DEBUG - NSLog(@"%@",[NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); -#endif - free(errBuf); - - free(encrypted_em); - RSA_free(rsa); - return nil; - } - - // decrypted encoded EME - NSData *encryptedEm = [NSData dataWithBytes:encrypted_em length:em_len]; - - RSA_free(rsa); - rsa->n = rsa->e = NULL; - free(encrypted_em); - - return encryptedEm; -} - -// decrypt bytes -+ (NSData *) privateDecrypt:(NSData *)toDecrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket -{ - RSA *rsa = RSA_new(); - if (!rsa) { - return nil; - } - - rsa->n = BN_dup([[secretKeyPacket publicMPI:@"N"] bignumRef]); - rsa->e = BN_dup([[secretKeyPacket publicMPI:@"E"] bignumRef]); - - rsa->d = BN_dup([[secretKeyPacket secretMPI:@"D"] bignumRef]); - rsa->p = BN_dup([[secretKeyPacket secretMPI:@"Q"] bignumRef]); /* p and q are round the other way in openssl */ - rsa->q = BN_dup([[secretKeyPacket secretMPI:@"P"] bignumRef]); - - if (rsa->d == NULL) { - return nil; - } - - if (RSA_check_key(rsa) != 1) { - ERR_load_crypto_strings(); - SSL_load_error_strings(); - - unsigned long err_code = ERR_get_error(); - char *errBuf = calloc(512, sizeof(char)); - ERR_error_string(err_code, errBuf); -#ifdef DEBUG - NSLog(@"%@",[NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); -#endif - free(errBuf); - - ERR_free_strings(); - return nil; - } - - UInt8 *outbuf = calloc(RSA_size(rsa), 1); - int t = RSA_private_decrypt(toDecrypt.length & INT_MAX , toDecrypt.bytes, outbuf, rsa, RSA_NO_PADDING); - if (t < 0) { - ERR_load_crypto_strings(); - SSL_load_error_strings(); - - unsigned long err_code = ERR_get_error(); - char *errBuf = calloc(512, sizeof(char)); - ERR_error_string(err_code, errBuf); -#ifdef DEBUG - NSLog(@"%@",[NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); -#endif - free(errBuf); - - ERR_free_strings(); - free(outbuf); - return nil; - } - - NSData *decryptedData = [NSData dataWithBytes:outbuf length:t]; - NSAssert(decryptedData, @"Missing data"); - - - free(outbuf); - RSA_free(rsa); - rsa->n = rsa->d = rsa->p = rsa->q = rsa->e = NULL; - - return decryptedData; -} - -// sign -+ (NSData *) privateEncrypt:(NSData *)toEncrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket -{ - RSA *rsa = RSA_new(); - if (!rsa) { - return nil; - } - - rsa->n = BN_dup([[secretKeyPacket publicMPI:@"N"] bignumRef]); - rsa->d = BN_dup([[secretKeyPacket secretMPI:@"D"] bignumRef]); - rsa->p = BN_dup([[secretKeyPacket secretMPI:@"Q"] bignumRef]); /* p and q are round the other way in openssl */ - rsa->q = BN_dup([[secretKeyPacket secretMPI:@"P"] bignumRef]); - rsa->e = BN_dup([[secretKeyPacket publicMPI:@"E"] bignumRef]); - - if (toEncrypt.length > secretKeyPacket.keySize) { - return nil; - } - - - /* If this isn't set, it's very likely that the programmer hasn't */ - /* decrypted the secret key. RSA_check_key segfaults in that case. */ - if (rsa->d == NULL) { - return nil; - } - - if (RSA_check_key(rsa) != 1) { - ERR_load_crypto_strings(); - SSL_load_error_strings(); - - unsigned long err_code = ERR_get_error(); - char *errBuf = calloc(512, sizeof(char)); - ERR_error_string(err_code, errBuf); - NSLog(@"%@",[NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); - free(errBuf); - - ERR_free_strings(); - return nil; - } - - - UInt8 *outbuf = calloc(RSA_size(rsa), 1); - int t = RSA_private_encrypt(toEncrypt.length & INT_MAX, (UInt8 *)toEncrypt.bytes, outbuf, rsa, RSA_NO_PADDING); - if (t < 0) { - ERR_load_crypto_strings(); - SSL_load_error_strings(); - - unsigned long err_code = ERR_get_error(); - char *errBuf = calloc(512, sizeof(char)); - ERR_error_string(err_code, errBuf); - NSLog(@"%@",[NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); - free(errBuf); - - ERR_free_strings(); - free(outbuf); - return nil; - } - - NSData *encryptedData = [NSData dataWithBytes:outbuf length:t]; - NSAssert(encryptedData, @"Missing calculated data"); - - - free(outbuf); - RSA_free(rsa); - rsa->n = rsa->d = rsa->p = rsa->q = rsa->e = NULL; - - return encryptedData; -} - -// recovers the message digest -+ (NSData *) publicDecrypt:(NSData *)toDecrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket -{ - RSA *rsa = RSA_new(); - if (!rsa) { - return nil; - } - - rsa->n = BN_dup([[publicKeyPacket publicMPI:@"N"] bignumRef]); - rsa->e = BN_dup([[publicKeyPacket publicMPI:@"E"] bignumRef]); - - NSAssert(rsa->n && rsa->e, @"Missing N or E"); - if (!rsa->n || !rsa->e) { - return nil; - } - - UInt8 *decrypted_em = calloc(RSA_size(rsa) - 11, 1); - int em_len = RSA_public_decrypt(toDecrypt.length & INT_MAX, toDecrypt.bytes, decrypted_em, rsa, RSA_NO_PADDING); - - if (em_len != publicKeyPacket.keySize) { - free(decrypted_em); - RSA_free(rsa); - - ERR_load_crypto_strings(); - SSL_load_error_strings(); - - unsigned long err_code = ERR_get_error(); - char *errBuf = calloc(512, sizeof(char)); - ERR_error_string(err_code, errBuf); - NSLog(@"%@",[NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); - free(errBuf); - - return nil; - } - - // decrypted PKCS emsa - NSData *decryptedEm = [NSData dataWithBytes:decrypted_em length:em_len]; - - RSA_free(rsa); - rsa->n = rsa->e = NULL; - free(decrypted_em); - - return decryptedEm; -} - -@end diff --git a/PGPS2K.h b/PGPS2K.h deleted file mode 100644 index 8c98e76c..00000000 --- a/PGPS2K.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// PGPS2K.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 07/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" - -@interface PGPS2K : NSObject - -@property (assign) PGPS2KSpecifier specifier; -@property (assign) PGPHashAlgorithm hashAlgorithm; -@property (retain, nonatomic) NSData *salt; // 8 bytes -@property (assign) UInt32 uncodedCount; -@property (assign, readonly) UInt32 codedCount; - -@property (assign) NSUInteger length; - -+ (PGPS2K *) string2KeyFromData:(NSData *)data atPosition:(NSUInteger)position; -- (NSUInteger) parseS2K:(NSData *)data atPosition:(NSUInteger)position; - -- (NSData *) produceSessionKeyWithPassphrase:(NSString *)passphrase keySize:(NSUInteger)keySize; -- (NSData *) export:(NSError *__autoreleasing*)error; - -@end diff --git a/PGPS2K.m b/PGPS2K.m deleted file mode 100644 index 72f87b84..00000000 --- a/PGPS2K.m +++ /dev/null @@ -1,220 +0,0 @@ -// -// PGPS2K.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 07/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// -// A string to key (S2K) specifier encodes a mechanism for producing a key to be used with a symmetric block cipher from a string of octets. -// - -#import "PGPS2K.h" -#import <CommonCrypto/CommonCrypto.h> -#import <CommonCrypto/CommonDigest.h> - -#import "PGPCryptoUtils.h" -#import "NSData+PGPUtils.h" - -static const unsigned int PGP_SALT_SIZE = 8; - -@implementation PGPS2K - -+ (PGPS2K *) string2KeyFromData:(NSData *)data atPosition:(NSUInteger)position -{ - PGPS2K *s2k = [[PGPS2K alloc] init]; - NSUInteger positionAfter = [s2k parseS2K:data atPosition:position]; - s2k.length = (positionAfter - position); - return s2k; -} - -- (NSData *)salt -{ - if (!_salt) { - NSMutableData *s = [NSMutableData data]; - for (int i = 0; i < 8; i++) { - Byte b = arc4random_uniform(255); - [s appendBytes:&b length:sizeof(b)]; - } - _salt = [s copy]; - } - return _salt; -} - -- (NSUInteger) parseS2K:(NSData *)data atPosition:(NSUInteger)startingPosition -{ - // S2K - - // string-to-key specifier is being given - NSUInteger position = startingPosition; - [data getBytes:&_specifier range:(NSRange) {position, 1}]; - position = position + 1; - - NSAssert(_specifier == PGPS2KSpecifierIteratedAndSalted || _specifier == PGPS2KSpecifierSalted || _specifier == PGPS2KSpecifierSimple, @"Bad s2k specifier"); - - // this is not documented, but now I need to read S2K key specified by s2kSpecifier - // 3.7.1.1. Simple S2K - - // Octet 1: hash algorithm - [data getBytes:&_hashAlgorithm range:(NSRange) {position,1}]; - position = position + 1; - - // Octets 2-9: 8-octet salt value - if (_specifier != PGPS2KSpecifierSimple) { - // read salt 8 bytes - _salt = [data subdataWithRange:(NSRange) {position, PGP_SALT_SIZE}]; - position = position + _salt.length; - } - - // Octet 10: count, a one-octet, coded value - if (_specifier == PGPS2KSpecifierIteratedAndSalted) { - [data getBytes:&_uncodedCount range:(NSRange) {position, 1}]; - position = position + 1; - } - - return position; -} - -- (UInt32) codedCount -{ - UInt32 expbias = 6; - return ((UInt32)16 + (_uncodedCount & 15)) << ((_uncodedCount >> 4) + expbias); -} - -- (NSData *) export:(NSError *__autoreleasing*)error -{ - NSMutableData *data = [NSMutableData data]; - [data appendBytes:&_specifier length:1]; - [data appendBytes:&_hashAlgorithm length:1]; - - if (_specifier != PGPS2KSpecifierSimple) { - [data appendData:self.salt]; - } - - if (_specifier == PGPS2KSpecifierIteratedAndSalted) { - NSAssert(self.uncodedCount != 0, @"Count value is 0"); - if (self.uncodedCount == 0) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Unexpected count is 0"}]; - } - return nil; - } - - [data appendBytes:&_uncodedCount length:1]; - } - - return [data copy]; -} - - -/** - * Calculate key for given password - * An S2K specifier can be stored in the secret keyring to specify how - * to convert the passphrase to a key that unlocks the secret data. - * Simple S2K hashes the passphrase to produce the session key. - * - * @param passphrase Password - * @param keySize Packet key size - * - * @return NSData with key - */ -- (NSData *) produceSessionKeyWithPassphrase:(NSString *)passphrase keySize:(NSUInteger)keySize -{ - NSMutableData *result = [NSMutableData data]; - NSMutableData *toHashData = [NSMutableData data]; - NSData *passphraseData = [passphrase dataUsingEncoding:NSUTF8StringEncoding]; - NSUInteger hashSize = [PGPCryptoUtils hashSizeOfHashAlhorithm:self.hashAlgorithm]; // SHA hash size - - switch (self.specifier) { - case PGPS2KSpecifierSimple: - { - // passphrase - [toHashData appendData:passphraseData]; - } - break; - case PGPS2KSpecifierSalted: - { - // salt + passphrase - // This includes a "salt" value in the S2K specifier -- some arbitrary - // data -- that gets hashed along with the passphrase string, to help - // prevent dictionary attacks. - - [toHashData appendData:self.salt]; - [toHashData appendData:passphraseData]; - } - break; - case PGPS2KSpecifierIteratedAndSalted: - { - // iterated (salt + passphrase) - // store all these as local vars to reduce the number of objc_msgSend calls that are made - NSUInteger saltLength = self.salt.length; - NSUInteger passphraseLength = passphraseData.length; - UInt32 codedCount = self.codedCount; - const void *saltAsBytes = self.salt.bytes; - const void *passphraseDataAsBytes = passphraseData.bytes; - - // This is an approximation of the amount of memory needed. - // It's mostly too small so a realloc is needed within the loop to compensate - NSUInteger dataLength = codedCount * keySize / (saltLength + passphraseLength); - // To keep track of how much data has been added to hashData - // Used to determin when to realloc and how much data should be copied into the NSData object - NSUInteger accumulatedDataLength = 0; - void *hashData = malloc(dataLength); - void *grownHashData = NULL; - - for (NSUInteger n = 0; n * hashSize < keySize; ++n) - { - for (NSUInteger i = 0; i < codedCount; i += saltLength + passphraseLength) - { - NSUInteger j = saltLength + passphraseLength; - if (i + j > codedCount && i != 0) { - j = codedCount - i; - } - - // add salt - NSUInteger saltlen = MIN(j, saltLength); - NSUInteger oldSize = accumulatedDataLength; - accumulatedDataLength = oldSize + saltlen; - if (accumulatedDataLength >= dataLength) { - dataLength = accumulatedDataLength * 2; - grownHashData = realloc(hashData, dataLength); - if (grownHashData != NULL) { - hashData = grownHashData; - } else { - abort(); - } - } - memcpy(hashData + oldSize, saltAsBytes, saltlen); - // add passphrase - if (j > saltLength) { - NSUInteger passlen = j - saltLength; - NSUInteger passlenOldSize = accumulatedDataLength; - accumulatedDataLength = passlenOldSize + passlen; - if (accumulatedDataLength >= dataLength) { - dataLength = accumulatedDataLength * 2; - grownHashData = realloc(hashData, dataLength); - if (grownHashData != NULL) { - hashData = grownHashData; - } else { - abort(); - } - } - memcpy(hashData + passlenOldSize, passphraseDataAsBytes, passlen); - } - } - } - [toHashData appendBytes:hashData length:accumulatedDataLength]; - free(hashData); - } - break; - default: - break; - } - - NSData *hash = [toHashData pgp_HashedWithAlgorithm:self.hashAlgorithm]; - [result appendData:hash]; - - return [result copy]; -} - - -@end diff --git a/PGPSecretKeyPacket.h b/PGPSecretKeyPacket.h deleted file mode 100644 index c8fe07b9..00000000 --- a/PGPSecretKeyPacket.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// PGPSecretKeyPacket.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 07/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPublicKeyPacket.h" -#import "PGPS2K.h" - -@interface PGPSecretKeyPacket : PGPPublicKeyPacket <NSCopying> - -@property (assign, readonly, nonatomic) BOOL isEncryptedWithPassword; -@property (assign) PGPS2KUsage s2kUsage; -@property (strong) PGPS2K *s2k; -@property (assign) PGPSymmetricAlgorithm symmetricAlgorithm; -@property (strong, readonly) NSData *ivData; - -/** - * Decrypt packet - * - * @param passphrase Password - * @param error error - * - * @return Decrypted key on success - */ -- (PGPSecretKeyPacket *) decryptedKeyPacket:(NSString *)passphrase error:(NSError * __autoreleasing *)error; - -- (PGPMPI *) secretMPI:(NSString *)identifier; -- (NSData *) decryptData:(NSData *)data withPublicKeyAlgorithm:(PGPPublicKeyAlgorithm)publicKeyAlgorithm; - -@end diff --git a/PGPSecretKeyPacket.m b/PGPSecretKeyPacket.m deleted file mode 100644 index ec0f55a3..00000000 --- a/PGPSecretKeyPacket.m +++ /dev/null @@ -1,444 +0,0 @@ -// -// PGPSecretKeyPacket.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 07/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// -// A Secret-Key packet contains all the information that is found in a -// Public-Key packet, including the public-key material, but also -// includes the secret-key material after all the public-key fields. - -#import "PGPSecretKeyPacket.h" -#import "PGPS2K.h" -#import "PGPMPI.h" -#import "PGPTypes.h" - -#import "PGPCryptoUtils.h" -#import "NSData+PGPUtils.h" -#import "PGPCryptoCFB.h" -#import "PGPPublicKeyRSA.h" - -#import <CommonCrypto/CommonCrypto.h> -#import <CommonCrypto/CommonDigest.h> -#import <CommonCrypto/CommonCryptor.h> - -#include <openssl/cast.h> -#include <openssl/idea.h> -#include <openssl/aes.h> -#include <openssl/sha.h> -#include <openssl/des.h> -#include <openssl/camellia.h> -#include <openssl/blowfish.h> - -@interface PGPPacket () -@property (copy, readwrite) NSData *headerData; -@property (copy, readwrite) NSData *bodyData; -@end - -@interface PGPSecretKeyPacket () -@property (strong, readwrite) NSData *encryptedMPIsPartData; // after decrypt -> secretMPIArray -@property (strong, readwrite) NSData *ivData; -@property (strong, readwrite) NSArray *secretMPIArray; // decrypted MPI - -@property (assign, readwrite) BOOL wasDecrypted; // is decrypted -@end - -@implementation PGPSecretKeyPacket - -- (PGPPacketTag)tag -{ - return PGPSecretKeyPacketTag; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ isEncrypted: %@", [super description], @(self.isEncryptedWithPassword)]; -} - -- (BOOL)isEncryptedWithPassword -{ - if (self.wasDecrypted) { - return NO; - } - - return (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed); -} - -- (PGPMPI *) secretMPI:(NSString *)identifier -{ - __block PGPMPI *returnMPI = nil; - [self.secretMPIArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - PGPMPI *mpi = obj; - if ([mpi.identifier isEqualToString:identifier]) { - returnMPI = mpi; - *stop = YES; - } - }]; - - return returnMPI; -} - -- (PGPFingerprint *)fingerprint -{ - return [super fingerprint]; -} - -- (NSData *) exportPacket:(NSError *__autoreleasing *)error -{ - NSMutableData *data = [NSMutableData data]; - NSData *publicKeyData = [super buildPublicKeyBodyData:YES]; - - NSMutableData *secretKeyPacketData = [NSMutableData data]; - [secretKeyPacketData appendData:publicKeyData]; - [secretKeyPacketData appendData:[self buildSecretKeyDataAndForceV4:YES]]; - - NSData *headerData = [self buildHeaderData:secretKeyPacketData]; - [data appendData: headerData]; - [data appendData: secretKeyPacketData]; - - // header not allways match because export new format while input can be old format - NSAssert([secretKeyPacketData isEqualToData:self.bodyData], @"Secret key not match"); - return [data copy]; -} - -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - NSUInteger position = [super parsePacketBody:packetBody error:error]; - // 5.5.3. Secret-Key Packet Formats - - NSAssert(self.version == 0x04,@"Only Secret Key version 4 is supported. Found version %@", @(self.version)); - - // One octet indicating string-to-key usage conventions - [packetBody getBytes:&_s2kUsage range:(NSRange){position, 1}]; - position = position + 1; - - if (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { - // moved to parseEncryptedPart:error - } else if (self.s2kUsage != PGPS2KUsageNone) { - // this is version 3, looks just like a V4 simple hash - self.symmetricAlgorithm = (PGPSymmetricAlgorithm)self.s2kUsage; // this is tricky, but this is right. V3 algorithm is in place of s2kUsage of V4 - self.s2kUsage = PGPS2KUsageEncrypted; - - self.s2k = [[PGPS2K alloc] init]; // not really parsed s2k - self.s2k.specifier = PGPS2KSpecifierSimple; - self.s2k.hashAlgorithm = PGPHashMD5; - } - - NSData *encryptedData = [packetBody subdataWithRange:(NSRange){position, packetBody.length - position}]; - if (self.isEncryptedWithPassword) { - position = position + [self parseEncryptedPart:encryptedData error:error]; - } else { - position = position + [self parseUnencryptedPart:encryptedData error:error]; - } - - return position; -} - -/** - * Encrypted algorithm-specific fields for secret keys - * - * @param packetBody packet data - * @param position position offset - * - * @return length - */ -- (NSUInteger) parseEncryptedPart:(NSData *)data error:(NSError * __autoreleasing *)error -{ - NSUInteger position = 0; - - if (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { - // If string-to-key usage octet was 255 or 254, a one-octet symmetric encryption algorithm - [data getBytes:&_symmetricAlgorithm range:(NSRange){position, 1}]; - position = position + 1; - - // S2K - self.s2k = [PGPS2K string2KeyFromData:data atPosition:position]; - position = position + self.s2k.length; - } - - if (self.s2kUsage != PGPS2KUsageNone) { - // Initial Vector (IV) of the same length as the cipher's block size - NSUInteger blockSize = [PGPCryptoUtils blockSizeOfSymmetricAlhorithm:self.symmetricAlgorithm]; - NSAssert(blockSize <= 16, @"invalid blockSize"); - self.ivData = [data subdataWithRange:(NSRange) {position, blockSize}]; - position = position + blockSize; - } - - // encrypted MPIs - // checksum or hash is encrypted together with the algorithm-specific fields (mpis) (if string-to-key usage octet is not zero). - self.encryptedMPIsPartData = [data subdataWithRange:(NSRange) {position, data.length - position}]; - position = position + self.encryptedMPIsPartData.length; - - return data.length; -} - -/** - * Cleartext part, parse cleartext or unencrypted data - * Store decrypted values in secretMPI array - * - * @param packetBody packet data - * @param position position offset - * - * @return length - */ -- (NSUInteger) parseUnencryptedPart:(NSData *)data error:(NSError * __autoreleasing *)error -{ - __unused NSUInteger position = 0; - - // check hash before read actual data - // hash is physically located at the end of dataBody - switch (self.s2kUsage) { - case PGPS2KUsageEncryptedAndHashed: - { - // a 20-octet SHA-1 hash of the plaintext of the algorithm-specific portion. - NSUInteger hashSize = [PGPCryptoUtils hashSizeOfHashAlhorithm:PGPHashSHA1]; - NSAssert(hashSize <= 20, @"invalid hashSize"); - - NSData *clearTextData = [data subdataWithRange:(NSRange) {0, data.length - hashSize}]; - NSData *hashData = [data subdataWithRange:(NSRange){data.length - hashSize, hashSize}]; - NSData *calculatedHashData = [clearTextData pgp_SHA1]; - - if (![hashData isEqualToData:calculatedHashData]) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorPassphraseInvalid userInfo:@{NSLocalizedDescriptionKey: @"Decrypted hash mismatch, invalid password."}]; - return data.length; - } - } - - } - break; - default: - { - // a two-octet checksum of the plaintext of the algorithm-specific portion - NSUInteger checksumLength = 2; - NSData *clearTextData = [data subdataWithRange:(NSRange) {0, data.length - checksumLength}]; - NSData *checksumData = [data subdataWithRange:(NSRange){data.length - checksumLength, checksumLength}]; - NSUInteger calculatedChecksum = [clearTextData pgp_Checksum]; - - UInt16 checksum = 0; - [checksumData getBytes:&checksum length:checksumLength]; - checksum = CFSwapInt16BigToHost(checksum); - - if (checksum != calculatedChecksum) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Decrypted hash mismatch, check password."}]; - return data.length; - } - } - } - break; - } - - // now read the actual data - switch (self.publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - case PGPPublicKeyAlgorithmRSASignOnly: - { - // multiprecision integer (MPI) of RSA secret exponent d. - PGPMPI *mpiD = [[PGPMPI alloc] initWithMPIData:data atPosition:position]; - mpiD.identifier = @"D"; - position = position + mpiD.packetLength; - - // MPI of RSA secret prime value p. - PGPMPI *mpiP = [[PGPMPI alloc] initWithMPIData:data atPosition:position]; - mpiP.identifier = @"P"; - position = position + mpiP.packetLength; - - // MPI of RSA secret prime value q (p < q). - PGPMPI *mpiQ = [[PGPMPI alloc] initWithMPIData:data atPosition:position]; - mpiQ.identifier = @"Q"; - position = position + mpiQ.packetLength; - - // MPI of u, the multiplicative inverse of p, mod q. - PGPMPI *mpiU = [[PGPMPI alloc] initWithMPIData:data atPosition:position]; - mpiU.identifier = @"U"; - position = position + mpiU.packetLength; - - self.secretMPIArray = @[mpiD, mpiP, mpiQ, mpiU]; - } - break; - case PGPPublicKeyAlgorithmDSA: - { - // MPI of DSA secret exponent x. - PGPMPI *mpiX = [[PGPMPI alloc] initWithMPIData:data atPosition:position]; - mpiX.identifier = @"X"; - position = position + mpiX.packetLength; - - self.secretMPIArray = @[mpiX]; - } - break; - case PGPPublicKeyAlgorithmElgamal: - case PGPPublicKeyAlgorithmElgamalEncryptorSign: - { - // MPI of Elgamal secret exponent x. - PGPMPI *mpiX = [[PGPMPI alloc] initWithMPIData:data atPosition:position]; - mpiX.identifier = @"X"; - position = position + mpiX.packetLength; - - self.secretMPIArray = @[mpiX]; - } - break; - default: - break; - } - - return data.length; -} - -/** - * Decrypt parsed encrypted packet - * Decrypt packet and store decrypted data on instance - * TODO: V3 support - partially supported, need testing. - * NOTE: Decrypted packet data should be released/forget after use - */ -- (PGPSecretKeyPacket *) decryptedKeyPacket:(NSString *)passphrase error:(NSError *__autoreleasing *)error -{ - NSParameterAssert(passphrase); - //NSParameterAssert(error); ????? Uncomment oliver - - if (!self.isEncryptedWithPassword) { - return self; - } - - if (!self.ivData) { - return nil; - } - - PGPSecretKeyPacket *encryptedKey = [self copy]; - - // Keysize - NSUInteger keySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:encryptedKey.symmetricAlgorithm]; - NSAssert(keySize <= 32, @"invalid keySize"); - - // Session key for password - // producing a key to be used with a symmetric block cipher from a string of octets - NSData *sessionKeyData = [encryptedKey.s2k produceSessionKeyWithPassphrase:passphrase keySize:keySize]; - - // Decrypted MPIs - NSData *decryptedData = [PGPCryptoCFB decryptData:encryptedKey.encryptedMPIsPartData - sessionKeyData:sessionKeyData - symmetricAlgorithm:self.symmetricAlgorithm - iv:encryptedKey.ivData]; - - - // now read mpis - if (decryptedData) { - [encryptedKey parseUnencryptedPart:decryptedData error:error]; - // if (*error) { - // return nil; - //} - } - encryptedKey.wasDecrypted = YES; - return encryptedKey; -} - -#pragma mark - Decrypt - -- (NSData *) decryptData:(NSData *)data withPublicKeyAlgorithm:(PGPPublicKeyAlgorithm)publicKeyAlgorithm -{ - switch (publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - case PGPPublicKeyAlgorithmRSASignOnly: - { - // return decrypted m - return [PGPPublicKeyRSA privateDecrypt:data withSecretKeyPacket:self]; - } - break; - default: - //TODO: add algorithms - [NSException raise:@"PGPNotSupported" format:@"Algorith not supported"]; - break; - } - return nil; -} - -#pragma mark - Private - -/** - * Build public key data for fingerprint - * - * @return public key data starting with version octet - */ -- (NSData *) buildSecretKeyDataAndForceV4:(BOOL)forceV4 -{ - NSAssert(forceV4 == YES,@"Only V4 is supported"); - - NSMutableData *data = [NSMutableData data]; - [data appendBytes:&_s2kUsage length:1]; - - if (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { - // If string-to-key usage octet was 255 or 254, a one-octet symmetric encryption algorithm - [data appendBytes:&_symmetricAlgorithm length:1]; - - // If string-to-key usage octet was 255 or 254, a string-to-key specifier. - NSError *exportError = nil; - [data appendData:[self.s2k export:&exportError]]; - NSAssert(exportError == nil, @"export failed"); - } - - if (self.s2kUsage != PGPS2KUsageNone) { - // If secret data is encrypted (string-to-key usage octet not zero), an Initial Vector (IV) of the same length as the cipher's block size. - // Initial Vector (IV) of the same length as the cipher's block size - [data appendBytes:self.ivData.bytes length:self.ivData.length]; - } - - if (self.s2kUsage == PGPS2KUsageNone) { - for (PGPMPI *mpi in self.secretMPIArray) { - [data appendData:[mpi exportMPI]]; - } - - // append hash - UInt16 checksum = CFSwapInt16HostToBig([data pgp_Checksum]); - [data appendBytes:&checksum length:2]; - } else { - // encrypted MPIs with encrypted hash - [data appendData:self.encryptedMPIsPartData]; - - // hash is part of encryptedMPIsPartData - } - - // If the string-to-key usage octet is zero or 255, then a two-octet checksum of the plaintext of the algorithm-specific portion (sum of all octets, mod 65536). - // This checksum or hash is encrypted together with the algorithm-specific fields - // ---> is part of self.encryptedMPIsPartData - //if (self.s2kUsage == PGPS2KUsageNone || self.s2kUsage == PGPS2KUsageEncrypted) { - // // Checksum - // UInt16 checksum = CFSwapInt16HostToBig([data pgp_Checksum]); - // [data appendBytes:&checksum length:2]; - //} else if (self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { - // // If the string-to-key usage octet was 254, then a 20-octet SHA-1 hash of the plaintext of the algorithm-specific portion. - // [data appendData:[data pgp_SHA1]]; - //} - - -// } else if (self.s2kUsage != PGPS2KUsageNone) { -// // this is version 3, looks just like a V4 simple hash -// self.symmetricAlgorithm = (PGPSymmetricAlgorithm)self.s2kUsage; // this is tricky, but this is right. V3 algorithm is in place of s2kUsage of V4 -// self.s2kUsage = PGPS2KUsageEncrypted; -// -// self.s2k = [[PGPS2K alloc] init]; // not really parsed s2k -// self.s2k.specifier = PGPS2KSpecifierSimple; -// self.s2k.algorithm = PGPHashMD5; - - - - return [data copy]; -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone -{ - PGPSecretKeyPacket *copy = [super copyWithZone:zone]; - copy->_s2kUsage = self.s2kUsage; - copy->_s2k = self.s2k; - copy->_symmetricAlgorithm = self.symmetricAlgorithm; - copy->_ivData = self.ivData; - copy->_secretMPIArray = self.secretMPIArray; - copy->_encryptedMPIsPartData = self.encryptedMPIsPartData; - return copy; -} - -@end diff --git a/PGPSignaturePacket.h b/PGPSignaturePacket.h deleted file mode 100644 index 5ccdca2a..00000000 --- a/PGPSignaturePacket.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// PGPSignature.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// -// Tag 2 - -#import <Foundation/Foundation.h> -#import "PGPPacketFactory.h" -#import "PGPKeyID.h" - -@class PGPKey, PGPUser, PGPUserIDPacket, PGPPublicKeyPacket; - -@interface PGPSignaturePacket : PGPPacket <NSCopying> - -@property (assign) UInt8 version; -@property (assign) PGPSignatureType type; -@property (assign) PGPPublicKeyAlgorithm publicKeyAlgorithm; -@property (assign) PGPHashAlgorithm hashAlgoritm; -@property (strong, readonly, nonatomic) NSArray *hashedSubpackets; -@property (strong, readonly, nonatomic) NSArray *unhashedSubpackets; -@property (strong) NSData *signedHashValueData; -@property (strong) NSArray *signatureMPIs; - -@property (assign, nonatomic, readonly) BOOL canBeUsedToSign; -@property (assign, nonatomic, readonly) BOOL canBeUsedToEncrypt; - -/** - * Create signature packet for signing. This is convienience constructor. - * - * @param type example: PGPSignatureBinaryDocument - * @param publicKeyAlgorithm public key algorith to be used for signature - * @param hashAlgorithm hash algorithm to be used for signature - * - * @return Packet instance ready to call signData:secretKey - */ -+ (PGPSignaturePacket *) signaturePacket:(PGPSignatureType)type hashAlgorithm:(PGPHashAlgorithm)hashAlgorithm; - -- (PGPKeyID *) issuerKeyID; -- (NSArray *) subpackets; -- (NSArray *) subpacketsOfType:(PGPSignatureSubpacketType)type; -- (NSDate *) expirationDate; -- (BOOL) isExpired; -- (NSDate *) creationDate; -- (BOOL) isPrimaryUserID; - - -/** - * Build signature data (signature packet with subpackets). - * - * @param secretKey Secret key used to create signature - * @param inputData Data to sign - * @param userID Optional. User ID - * - * @return Signature packet data - */ -- (BOOL) signData:(NSData *)inputData secretKey:(PGPKey *)secretKey error:(NSError * __autoreleasing *)error; -- (BOOL) signData:(NSData *)inputData secretKey:(PGPKey *)secretKey passphrase:(NSString *)passphrase userID:(NSString *)userID error:(NSError * __autoreleasing *)error; - - -- (BOOL) verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey error:(NSError * __autoreleasing *)error; -- (BOOL) verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey userID:(NSString *)userID error:(NSError * __autoreleasing *)error; -- (BOOL) verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey signingKeyPacket:(PGPPublicKeyPacket *)signingKeyPacket userID:(NSString *)userID error:(NSError * __autoreleasing *)error; - - -@end diff --git a/PGPSignaturePacket.m b/PGPSignaturePacket.m deleted file mode 100644 index 50709f34..00000000 --- a/PGPSignaturePacket.m +++ /dev/null @@ -1,806 +0,0 @@ -// -// PGPSignature.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPSignaturePacket.h" -#import "PGPMPI.h" -#import "PGPSignatureSubpacket.h" -#import "PGPUserIDPacket.h" -#import "PGPKey.h" -#import "PGPUser.h" -#import "PGPSecretKeyPacket.h" -#import "PGPPKCSEmsa.h" -#import "PGPLiteralPacket.h" -#import "PGPPublicKeyRSA.h" -#import "NSData+PGPUtils.h" - -#import <openssl/rsa.h> -#import <openssl/dsa.h> -#import <openssl/bn.h> -#import <openssl/err.h> -#import <openssl/ssl.h> - -@interface PGPSignatureSubpacket () -@property (strong, readwrite) id value; -@end - -@interface PGPSignaturePacket () -@property (strong, readwrite, nonatomic) NSArray *hashedSubpackets; -@property (strong, readwrite, nonatomic) NSArray *unhashedSubpackets; - -// A V4 signature hashes the packet body -// starting from its first field, the version number, through the end -// of the hashed subpacket data. Thus, the fields hashed are the -// signature version, the signature type, the public-key algorithm, the -// hash algorithm, the hashed subpacket length, and the hashed -// subpacket body. -@property (strong) NSData *rawReadedSignedPartData; - -@end - -@implementation PGPSignaturePacket - -- (instancetype)init -{ - if (self = [super init]) { - _version = 4; - } - return self; -} - -+ (PGPSignaturePacket *) signaturePacket:(PGPSignatureType)type hashAlgorithm:(PGPHashAlgorithm)hashAlgorithm -{ - PGPSignaturePacket *signaturePacket = [[PGPSignaturePacket alloc] init]; - - signaturePacket.hashAlgoritm = hashAlgorithm; - return signaturePacket; -} - -- (NSArray *)hashedSubpackets -{ - if (!_hashedSubpackets) { - _hashedSubpackets = [NSArray array]; - } - return _hashedSubpackets; -} - -- (NSArray *)unhashedSubpackets -{ - if (!_unhashedSubpackets) { - _unhashedSubpackets = [NSArray array]; - } - return _unhashedSubpackets; - -} - -- (PGPPacketTag)tag -{ - return PGPSignaturePacketTag; -} - -#pragma mark - Helper properties - -- (PGPKeyID *)issuerKeyID -{ - PGPSignatureSubpacket *subpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeIssuerKeyID] firstObject]; - return subpacket.value; -} - -- (NSArray *)subpackets -{ - return [self.hashedSubpackets arrayByAddingObjectsFromArray:self.unhashedSubpackets]; -} - -- (NSArray *)subpacketsOfType:(PGPSignatureSubpacketType)type -{ - NSMutableArray *arr = [NSMutableArray array]; - for (PGPSignatureSubpacket *subPacket in self.subpackets) { - if (subPacket.type == type) { - [arr addObject:subPacket]; - } - } - return [arr copy]; -} - -- (NSDate *)expirationDate -{ - PGPSignatureSubpacket *creationDateSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeSignatureCreationTime] firstObject]; - PGPSignatureSubpacket *validityPeriodSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeSignatureExpirationTime] firstObject]; - if (validityPeriodSubpacket == nil ) { - validityPeriodSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeKeyExpirationTime] firstObject]; - } - - NSDate *creationDate = creationDateSubpacket.value; - NSNumber *validityPeriod = validityPeriodSubpacket.value; - if (!validityPeriod || validityPeriod.unsignedIntegerValue == 0) { - return nil; - } - - NSDate *expirationDate = [creationDate dateByAddingTimeInterval:validityPeriod.unsignedIntegerValue]; - return expirationDate; -} - -- (BOOL) isExpired -{ - // is no expiration date then signature never expires - NSDate *expirationDate = [self expirationDate]; - if (!expirationDate) { - return NO; - } - - if ([expirationDate compare:[NSDate date]] == NSOrderedAscending) { - return YES; - } - return NO; -} - -- (NSDate *) creationDate -{ - PGPSignatureSubpacket *creationDateSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeSignatureCreationTime] lastObject]; - return creationDateSubpacket.value; -} - -- (BOOL) isPrimaryUserID -{ - PGPSignatureSubpacket *primaryUserIDSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypePrimaryUserID] firstObject]; - return [(NSNumber *)primaryUserIDSubpacket.value boolValue]; -} - -- (BOOL)canBeUsedToSign -{ - BOOL result = self.publicKeyAlgorithm == PGPPublicKeyAlgorithmDSA || self.publicKeyAlgorithm == PGPPublicKeyAlgorithmRSA || self.publicKeyAlgorithm == PGPPublicKeyAlgorithmRSASignOnly; - - if (result) { - PGPSignatureSubpacket *subpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeKeyFlags] firstObject]; - NSArray *flags = subpacket.value; - if ([flags containsObject:@(PGPSignatureFlagAllowSignData)]) { - return YES; - } - } - return NO; -} - -- (BOOL)canBeUsedToEncrypt -{ - BOOL result = NO; - PGPSignatureSubpacket *subpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeKeyFlags] firstObject]; - NSArray *flags = subpacket.value; - if ([flags containsObject:@(PGPSignatureFlagAllowEncryptStorage)] || [flags containsObject:@(PGPSignatureFlagAllowEncryptCommunications)]) { - result = YES; - } - - // I'm not convinced if DSA is allowed here self.publicKeyAlgorithm != PGPPublicKeyAlgorithmDSA - result = result && self.publicKeyAlgorithm != PGPPublicKeyAlgorithmRSASignOnly && self.publicKeyAlgorithm != PGPPublicKeyAlgorithmElgamalEncryptorSign; - - return result; -} - -#pragma mark - Build packet - -- (NSData *) exportPacket:(NSError *__autoreleasing *)error -{ - NSMutableData *data = [NSMutableData data]; - - NSData *bodyData = [self buildFullSignatureBodyData:error]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - - return [data copy]; -} - -- (NSData *) buildSignedPart:(NSArray *)hashedSubpackets -{ - NSMutableData *data = [NSMutableData data]; - - // One-octet version number (4). - UInt8 exportVersion = 4; - [data appendBytes:&exportVersion length:1]; - - // One-octet signature type. - [data appendBytes:&_type length:1]; - - // One-octet public-key algorithm. - [data appendBytes:&_publicKeyAlgorithm length:1]; - - // One-octet hash algorithm. - [data appendBytes:&_hashAlgoritm length:1]; - - // hashed Subpackets - [data appendData:[self buildSubpacketsCollectionData:hashedSubpackets]]; - - return [data copy]; -} - -- (NSData *) buildFullSignatureBodyData:(NSError *__autoreleasing *)error -{ - NSMutableData *data = [NSMutableData data]; - - NSData *signedPartData = [self buildSignedPart:self.hashedSubpackets]; - [data appendData:signedPartData]; - - // unhashed Subpackets - [data appendData:[self buildSubpacketsCollectionData:self.unhashedSubpackets]]; - - // signed hash value - [data appendData:self.signedHashValueData]; - - for (PGPMPI *mpi in self.signatureMPIs) { - [data appendData:[mpi exportMPI]]; - } - - return [data copy]; -} - -#pragma mark - Verify - -- (BOOL) verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey error:(NSError * __autoreleasing *)error; -{ - return [self verifyData:inputData withKey:publicKey signingKeyPacket:(PGPPublicKeyPacket *)[publicKey signingKeyPacketWithKeyID:self.issuerKeyID] userID:nil error:error]; -} - -- (BOOL) verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey userID:(NSString *)userID error:(NSError * __autoreleasing *)error; -{ - return [self verifyData:inputData withKey:publicKey signingKeyPacket:(PGPPublicKeyPacket *)[publicKey signingKeyPacketWithKeyID:self.issuerKeyID] userID:userID error:error]; -} - -// Opposite to sign, with readed data (not produced) -- (BOOL) verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey signingKeyPacket:(PGPPublicKeyPacket *)signingKeyPacket userID:(NSString *)userID error:(NSError * __autoreleasing *)error -{ - if (!signingKeyPacket) - { - // no signing packet was found, this we have no valid signature - return NO; - } - - //FIXME: publicKey is actually secret key sometimes? - - if (self.type == PGPSignatureBinaryDocument && inputData.length == 0) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Invalid signature packet type"}]; - } - return NO; - } - - // 5.2.4. Computing Signatures - - // build toSignData, toSign - NSData *toSignData = [self toSignDataForType:self.type inputData:inputData key:publicKey keyPacket:signingKeyPacket userID:userID error:error]; - - // signedPartData - NSData *signedPartData = [self buildSignedPart:self.hashedSubpackets]; - // calculate trailer - NSData *trailerData = [self calculateTrailerFor:signedPartData]; - - //toHash = toSignData + signedPartData + trailerData; - NSMutableData *toHashData = [NSMutableData data]; - [toHashData appendData:toSignData]; - [toHashData appendData:self.rawReadedSignedPartData ?: signedPartData]; - [toHashData appendData:trailerData]; - - // Calculate hash value - NSData *hashData = [toHashData pgp_HashedWithAlgorithm:self.hashAlgoritm]; - - // check signed hash value, should match - // FIXME: propably will fail on V3 signature, need investigate how to handle V3 scenario here - if (![self.signedHashValueData isEqualToData:[hashData subdataWithRange:(NSRange){0,2}]]) { - return NO; - } - - switch (signingKeyPacket.publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSASignOnly: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - { - // convert mpi data to binary signature_bn_bin - PGPMPI *signatureMPI = self.signatureMPIs[0]; - - // encoded m value - NSData *encryptedEmData = [signatureMPI bodyData]; - - // decrypted encoded m value - NSData *decryptedEmData = [PGPPublicKeyRSA publicDecrypt:encryptedEmData withPublicKeyPacket:signingKeyPacket]; - - // calculate EM and compare with decrypted EM. PKCS-emsa Encoded M. - NSData *emData = [PGPPKCSEmsa encode:self.hashAlgoritm message:toHashData encodedMessageLength:signingKeyPacket.keySize error:error]; - if (![emData isEqualToData:decryptedEmData]) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"em hash dont match"}]; - } - return NO; - } - return YES; - } - break; - default: - break; - } - return NO; -} - -#pragma mark - Sign - -// 5.2.4. Computing Signatures -// http://tools.ietf.org/html/rfc4880#section-5.2.4 -// @see https://github.com/singpolyma/openpgp-spec/blob/master/key-signatures -- (BOOL) signData:(NSData *)inputData secretKey:(PGPKey *)secretKey error:(NSError * __autoreleasing *)error -{ - return [self signData:inputData secretKey:secretKey passphrase:nil userID:nil error:error]; -} - -- (BOOL) signData:(NSData *)inputData secretKey:(PGPKey *)secretKey passphrase:(NSString *)passphrase userID:(NSString *)userID error:(NSError * __autoreleasing *)error -{ - NSAssert(secretKey.type == PGPKeySecret,@"Need secret key"); - NSAssert([secretKey.primaryKeyPacket isKindOfClass:[PGPSecretKeyPacket class]], @"Signing key packet not found"); - - - PGPSecretKeyPacket *signingKeyPacket = (PGPSecretKeyPacket *)secretKey.signingKeyPacket; - NSAssert(signingKeyPacket, @"No signing signature found"); - if (!signingKeyPacket) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"No signing signature found"}]; - } - return NO; - } - - //TODO: check it this is right ? setup public key algorithm from secret key packet - self.publicKeyAlgorithm = signingKeyPacket.publicKeyAlgorithm; - - if (signingKeyPacket.isEncryptedWithPassword && passphrase.length > 0) { - NSError *decryptError; - //Copy secret key instance, then decrypt on copy, not on the original (do not leave unencrypted instance around) - signingKeyPacket = [signingKeyPacket decryptedKeyPacket:passphrase error:&decryptError]; - NSAssert(signingKeyPacket && !decryptError, @"decrypt error %@", decryptError); - } - else if(signingKeyPacket.isEncryptedWithPassword) { - NSError *decryptError; - passphrase = @""; - //Copy secret key instance, then decrypt on copy, not on the original (do not leave unencrypted instance around) - signingKeyPacket = [signingKeyPacket decryptedKeyPacket:passphrase error:&decryptError]; - NSAssert(signingKeyPacket && !decryptError, @"decrypt error %@", decryptError); - } - // signed part data - // timestamp subpacket is required - PGPSignatureSubpacket *creationTimeSubpacket = [PGPSignatureSubpacket subpacketWithType:PGPSignatureSubpacketTypeSignatureCreationTime andValue:[NSDate date]]; - self.hashedSubpackets = @[creationTimeSubpacket]; - NSData *signedPartData = [self buildSignedPart:self.hashedSubpackets]; - // calculate trailer - NSData *trailerData = [self calculateTrailerFor:signedPartData]; - - // build toSignData, toSign - NSData *toSignData = [self toSignDataForType:self.type inputData:inputData key:secretKey keyPacket:signingKeyPacket userID:userID error:error]; - //toHash = toSignData + signedPartData + trailerData; - NSMutableData *toHashData = [NSMutableData dataWithData:toSignData]; - [toHashData appendData:signedPartData]; - [toHashData appendData:trailerData]; - - // Calculate hash value - NSData *hashData = [toHashData pgp_HashedWithAlgorithm:self.hashAlgoritm]; - - // == Computing Signatures == - // Encrypt hash data Packet signature MPIs - // Encrypted m value (PKCS emsa encrypted) - NSData *em = [PGPPKCSEmsa encode:self.hashAlgoritm message:toHashData encodedMessageLength:signingKeyPacket.keySize error:nil]; - NSData *encryptedEmData = nil; - - switch (self.publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - case PGPPublicKeyAlgorithmRSASignOnly: - { - encryptedEmData = [PGPPublicKeyRSA privateEncrypt:em withSecretKeyPacket:signingKeyPacket]; - } - break; - - default: - [NSException raise:@"PGPNotSupported" format:@"Algorith not supported"]; - break; - } - - - NSAssert(encryptedEmData, @"Encryption failed"); - if (!encryptedEmData) { - if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Sign Encryption failed"}]; - } - return NO; - } - // store signature data as MPI - self.signatureMPIs = @[[[PGPMPI alloc] initWithData:encryptedEmData]]; - - // add unhashed PGPSignatureSubpacketTypeIssuer subpacket - REQUIRED - PGPKeyID *keyid = [[PGPKeyID alloc] initWithFingerprint:signingKeyPacket.fingerprint]; - PGPSignatureSubpacket *issuerSubpacket = [PGPSignatureSubpacket subpacketWithType:PGPSignatureSubpacketTypeIssuerKeyID andValue:keyid]; - self.unhashedSubpackets = @[issuerSubpacket]; - - // Checksum - // Two-octet field holding the left 16 bits of the signed hash value. - NSData *signedHashValue = [hashData subdataWithRange:(NSRange){0,2}]; - self.signedHashValueData = signedHashValue; - return YES; -} - -- (NSData *) toSignDataForType:(PGPSignatureType)type inputData:(NSData *)inputData key:(PGPKey *)key keyPacket:(PGPPublicKeyPacket *)keyPacket userID:(NSString *)userID error:(NSError * __autoreleasing *)error -{ - NSMutableData *toSignData = [NSMutableData data]; - switch (type) { - case PGPSignatureBinaryDocument: - case PGPSignatureCanonicalTextDocument: - { - [toSignData appendData:inputData]; - } - break; - case PGPSignatureGenericCertificationUserIDandPublicKey: // 0x10 - case PGPSignaturePersonalCertificationUserIDandPublicKey:// 0x11 - case PGPSignatureCasualCertificationUserIDandPublicKey: // 0x12 - case PGPSignaturePositiveCertificationUserIDandPublicKey:// 0x13 - case PGPSignatureCertificationRevocation: // 0x28 - { - // A certification signature (type 0x10 through 0x13) - - // When a signature is made over a key, the hash data starts with the - // octet 0x99, followed by a two-octet length of the key, and then body - // of the key packet. (Note that this is an old-style packet header for - // a key packet with two-octet length.) - - NSData *keyData = [keyPacket exportPublicPacketOldStyle]; - [toSignData appendData:keyData]; - - NSAssert(key.users > 0, @"Key need at least one user"); - - BOOL userIsValid = NO; - for (PGPUser *user in key.users) { - if ([user.userID isEqualToString:userID]) { - userIsValid = YES; - } - } - - if (!userIsValid) { - return nil; - } - - if (userID.length > 0) { - NSData *userIDData = [userID dataUsingEncoding:NSUTF8StringEncoding]; - if (self.version == 4) { - // constant tag (1) - UInt8 userIDConstant = 0xB4; - [toSignData appendBytes:&userIDConstant length:1]; - - // length (4) - UInt32 userIDLength = (UInt32)userIDData.length; - userIDLength = CFSwapInt32HostToBig(userIDLength); - [toSignData appendBytes:&userIDLength length:4]; - } - // data - [toSignData appendData:userIDData]; - } - //TODO user attributes alternative - //UInt8 userAttributeConstant = 0xD1; - //[data appendBytes:&userAttributeConstant length:sizeof(userAttributeConstant)]; - - } - break; - - default: - [toSignData appendData:inputData]; - break; - } - return [toSignData copy]; -} - -- (NSData *) calculateTrailerFor:(NSData *)signedPartData -{ - NSAssert(self.version == 4, @"Not supported signature version"); - if (self.version < 4) - return nil; - - NSMutableData *trailerData = [NSMutableData data]; - UInt8 prefix[2] = {self.version, 0xFF}; - [trailerData appendBytes:&prefix length:2]; - - UInt32 signatureLength = (UInt32)signedPartData.length; // + 6; // ??? (note that this number does not include these final six octets) - signatureLength = CFSwapInt32HostToBig(signatureLength); - [trailerData appendBytes:&signatureLength length:4]; - - return [trailerData copy]; -} - -#pragma mark - Parse - -/** - * 5.2. Signature Packet (Tag 2) - * - * @param packetBody Packet body - */ - -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - __unused NSUInteger position = [super parsePacketBody:packetBody error:error]; - NSUInteger startPosition = position; - - UInt8 parsedVersion = 0; - // One-octet version number. - [packetBody getBytes:&parsedVersion range:(NSRange){position,1}]; - position = position + 1; - - switch (parsedVersion) { - case 0x04: - position = [self parseV4PacketBody:packetBody error:error]; - break; - case 0x03: - position = [self parseV3PacketBody:packetBody error:error]; - break; - default: - NSAssert(true, @"Unsupported signature packet version"); - if (error) - { - *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Signature version %@ is supported at the moment", @(parsedVersion)]}]; - } - return startPosition + packetBody.length; - break; - } - return position; -} - -// FIXME: V3 signatures fail somewehere (I don't know where yet) because everything is designed -// for V4 and uses V4 specific data to (for example) validate signature -- (NSUInteger)parseV3PacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - NSUInteger position = [super parsePacketBody:packetBody error:error]; - - // V3 - // One-octet version number (3). - UInt8 parsedVersion = 0; - [packetBody getBytes:&parsedVersion range:(NSRange){position,1}]; - position = position + 1; - - // One-octet length of following hashed material. MUST be 5. - UInt8 parsedLength = 0; - [packetBody getBytes:&parsedLength range:(NSRange){position,1}]; - position = position + 1; - NSAssert(parsedLength == 5, @"Invalid signature data"); - - // One-octet signature type. - [packetBody getBytes:&_type range:(NSRange){position,1}]; - position = position + 1; - - // Four-octet creation time - UInt32 parsedCreationTimestamp = 0; - [packetBody getBytes:&parsedCreationTimestamp range:(NSRange){position,4}]; - parsedCreationTimestamp = CFSwapInt32BigToHost(parsedCreationTimestamp); - position = position + 4; - - // Eight-octet Key ID of signer - PGPKeyID *parsedkeyID = [[PGPKeyID alloc] initWithLongKey:[packetBody subdataWithRange:(NSRange){position, 8}]]; - position = position + 8; - - // One-octet public-key algorithm. - [packetBody getBytes:&_publicKeyAlgorithm range:(NSRange){position,1}]; - position = position + 1; - - // One-octet hash algorithm. - [packetBody getBytes:&_hashAlgoritm range:(NSRange){position,1}]; - position = position + 1; - - // Two-octet field holding the left 16 bits of the signed hash value. - self.signedHashValueData = [packetBody subdataWithRange:(NSRange){position, 2}]; - position = position + 2; - - // 5.2.2. One or more multiprecision integers comprising the signature. This portion is algorithm specific - // Signature - switch (_publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - case PGPPublicKeyAlgorithmRSASignOnly: - { - // multiprecision integer (MPI) of RSA signature value m**d mod n. - // MPI of RSA public modulus n; - PGPMPI *mpiN = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiN.identifier = @"N"; - position = position + mpiN.packetLength; - - self.signatureMPIs = @[mpiN]; - } - break; - case PGPPublicKeyAlgorithmDSA: - case PGPPublicKeyAlgorithmECDSA: - { - // MPI of DSA value r. - PGPMPI *mpiR = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiR.identifier = @"R"; - position = position + mpiR.packetLength; - - // MPI of DSA value s. - PGPMPI *mpiS = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiS.identifier = @"S"; - position = position + mpiS.packetLength; - - self.signatureMPIs = @[mpiR, mpiS]; - } - break; - default: - break; - } - - // convert V3 values to V4 subpackets - PGPSignatureSubpacket *keyIDSubpacket = [[PGPSignatureSubpacket alloc] init]; - keyIDSubpacket.type = PGPSignatureSubpacketTypeIssuerKeyID; - keyIDSubpacket.value = parsedkeyID; - self.unhashedSubpackets = [self.unhashedSubpackets arrayByAddingObject:keyIDSubpacket]; - - PGPSignatureSubpacket *creationTimeSubpacket = [[PGPSignatureSubpacket alloc] init]; - creationTimeSubpacket.type = PGPSignatureSubpacketTypeSignatureCreationTime; - creationTimeSubpacket.value = [NSDate dateWithTimeIntervalSince1970:parsedCreationTimestamp]; - self.hashedSubpackets = [self.hashedSubpackets arrayByAddingObject:creationTimeSubpacket]; - - return position; -} - -- (NSUInteger)parseV4PacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - NSUInteger position = [super parsePacketBody:packetBody error:error]; - NSUInteger startPosition = position; - - UInt8 parsedVersion = 0; - // V4 - // One-octet version number (4). - [packetBody getBytes:&parsedVersion range:(NSRange){position,1}]; - position = position + 1; - - // One-octet signature type. - [packetBody getBytes:&_type range:(NSRange){position,1}]; - position = position + 1; - - // One-octet public-key algorithm. - [packetBody getBytes:&_publicKeyAlgorithm range:(NSRange){position,1}]; - position = position + 1; - - // One-octet hash algorithm. - [packetBody getBytes:&_hashAlgoritm range:(NSRange){position,1}]; - position = position + 1; - - // Two-octet scalar octet count for following hashed subpacket data. - UInt16 hashedOctetCount = 0; - [packetBody getBytes:&hashedOctetCount range:(NSRange){position, 2}]; - hashedOctetCount = CFSwapInt16BigToHost(hashedOctetCount); - position = position + 2; - - // Hashed subpacket data set (zero or more subpackets) - NSData *hashedSubpacketsData = nil; - if (hashedOctetCount > 0) { - hashedSubpacketsData = [packetBody subdataWithRange:(NSRange){position,hashedOctetCount}]; - position = position + hashedOctetCount; - - NSMutableArray *hashedSubpackets = [NSMutableArray arrayWithCapacity:hashedOctetCount]; - - NSUInteger positionSubpacket = 0; - while (positionSubpacket < hashedSubpacketsData.length) { - PGPSignatureSubpacket *subpacket = [self getSubpacketStartingAtPosition:positionSubpacket fromData:hashedSubpacketsData]; - [hashedSubpackets addObject:subpacket]; - positionSubpacket = subpacket.bodyRange.location + subpacket.bodyRange.length; - } - - self.hashedSubpackets = [hashedSubpackets copy]; - } - - // Raw, signed data - self.rawReadedSignedPartData = [packetBody subdataWithRange:(NSRange){startPosition, position}]; - - // Two-octet scalar octet count for the following unhashed subpacket - UInt16 unhashedOctetCount = 0; - [packetBody getBytes:&unhashedOctetCount range:(NSRange){position, 2}]; - unhashedOctetCount = CFSwapInt16BigToHost(unhashedOctetCount); - position = position + 2; - - // Unhashed subpacket data set (zero or more subpackets) - NSData *unhashedSubpacketsData = nil; - if (unhashedOctetCount > 0) { - unhashedSubpacketsData = [packetBody subdataWithRange:(NSRange){position,unhashedOctetCount}]; - position = position + unhashedOctetCount; - - NSMutableArray *unhashedSubpackets = [NSMutableArray arrayWithCapacity:unhashedOctetCount]; - - // Loop subpackets - NSUInteger positionSubpacket = 0; - while (positionSubpacket < unhashedSubpacketsData.length) { - PGPSignatureSubpacket *subpacket = [self getSubpacketStartingAtPosition:positionSubpacket fromData:unhashedSubpacketsData]; - [unhashedSubpackets addObject:subpacket]; - positionSubpacket = subpacket.bodyRange.location + subpacket.bodyRange.length; - } - - self.unhashedSubpackets = [unhashedSubpackets copy]; - } - - // Two-octet field holding the left 16 bits of the signed hash value. - self.signedHashValueData = [packetBody subdataWithRange:(NSRange){position, 2}]; - position = position + 2; - - // 5.2.2. One or more multiprecision integers comprising the signature. This portion is algorithm specific - // Signature - switch (_publicKeyAlgorithm) { - case PGPPublicKeyAlgorithmRSA: - case PGPPublicKeyAlgorithmRSAEncryptOnly: - case PGPPublicKeyAlgorithmRSASignOnly: - { - // multiprecision integer (MPI) of RSA signature value m**d mod n. - // MPI of RSA public modulus n; - PGPMPI *mpiN = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiN.identifier = @"N"; - position = position + mpiN.packetLength; - - self.signatureMPIs = @[mpiN]; - } - break; - case PGPPublicKeyAlgorithmDSA: - case PGPPublicKeyAlgorithmECDSA: - { - // MPI of DSA value r. - PGPMPI *mpiR = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiR.identifier = @"R"; - position = position + mpiR.packetLength; - - // MPI of DSA value s. - PGPMPI *mpiS = [[PGPMPI alloc] initWithMPIData:packetBody atPosition:position]; - mpiS.identifier = @"S"; - position = position + mpiS.packetLength; - - self.signatureMPIs = @[mpiR, mpiS]; - } - break; - default: - break; - } - - return position; -} - -#pragma mark - Private - -// I don't like this part, really ugly -// This is because subpacket length is unknow and header need to be found first -// then subpacket can be parsed -- (PGPSignatureSubpacket *) getSubpacketStartingAtPosition:(NSUInteger)subpacketsPosition fromData:(NSData *)subpacketsData -{ - NSRange headerRange = (NSRange) {subpacketsPosition, MIN(6,subpacketsData.length - subpacketsPosition) }; // up to 5+1 octets - NSData *guessHeaderData = [subpacketsData subdataWithRange:headerRange]; // this is "may be" header to be parsed - PGPSignatureSubpacketHeader *subpacketHeader = [PGPSignatureSubpacket subpacketHeaderFromData:guessHeaderData]; - - NSRange subPacketBodyRange = (NSRange){subpacketsPosition + subpacketHeader.headerLength,subpacketHeader.bodyLength}; - NSData *subPacketBody = [subpacketsData subdataWithRange:subPacketBodyRange]; - PGPSignatureSubpacket *subpacket = [[PGPSignatureSubpacket alloc] initWithHeader:subpacketHeader body:subPacketBody bodyRange:subPacketBodyRange]; - - return subpacket; -} - -- (NSData *) buildSubpacketsCollectionData:(NSArray *)subpacketsCollection -{ - NSMutableData *data = [NSMutableData data]; - if (subpacketsCollection.count > 0) { - NSMutableData *subpackets = [NSMutableData data]; - // Hashed subpacket data set (zero or more subpackets) - for (PGPSignatureSubpacket *subpacket in subpacketsCollection) { - NSError *error = nil; - NSData *subpacketData = [subpacket exportSubpacket:&error]; - if (subpacketData && !error) { - [subpackets appendData:subpacketData]; - } - } - // Two-octet scalar octet count for following hashed subpacket data. - UInt16 countBE = CFSwapInt16HostToBig(subpackets.length); - [data appendBytes:&countBE length:2]; - // subackets data - [data appendData:subpackets]; - } else { - // 0x00 0x00 - UInt16 zeroZero = 0; - [data appendBytes:&zeroZero length:2]; - } - return [data copy]; -} - - -@end diff --git a/PGPSignatureSubpacket.h b/PGPSignatureSubpacket.h deleted file mode 100644 index 9e795db8..00000000 --- a/PGPSignatureSubpacket.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// PGPSignatureSubPacket.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPTypes.h" - -@interface PGPSignatureSubpacketHeader : NSObject -@property (assign) PGPSignatureSubpacketType type; -@property (assign) NSUInteger headerLength; -@property (assign) NSUInteger bodyLength; -@end - - -@interface PGPSignatureSubpacket : NSObject - -@property (assign, readonly) NSRange bodyRange; // subrange range within parent packet - -@property (assign) PGPSignatureSubpacketType type; -@property (strong, readonly) id value; - -- (instancetype) initWithHeader:(PGPSignatureSubpacketHeader *)header body:(NSData *)subPacketBodyData bodyRange:(NSRange)bodyRange; -+ (PGPSignatureSubpacketHeader *) subpacketHeaderFromData:(NSData *)headerData; -+ (PGPSignatureSubpacket *) subpacketWithType:(PGPSignatureSubpacketType)type andValue:(id)value; - -- (void) parseSubpacketBody:(NSData *)packetBody; -- (NSData *) exportSubpacket:(NSError *__autoreleasing *)error; - -@end diff --git a/PGPSubKey.h b/PGPSubKey.h deleted file mode 100644 index 17d73baa..00000000 --- a/PGPSubKey.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// PGPSubKey.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 16/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPKey.h" -#import "PGPPacket.h" -#import "PGPSignaturePacket.h" -#import "PGPKeyID.h" - -@interface PGPSubKey : PGPKey - -@property (strong) PGPSignaturePacket *bindingSignature; -@property (nonatomic, readonly) PGPKeyID *keyID; - -- (instancetype) initWithPacket:(PGPPacket *)packet; -- (NSArray *) allPackets; - -@end diff --git a/PGPSubKey.m b/PGPSubKey.m deleted file mode 100644 index 9ac14343..00000000 --- a/PGPSubKey.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// PGPSubKey.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 16/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPSubKey.h" -#import "PGPPublicKeyPacket.h" - -@implementation PGPSubKey - -- (instancetype) initWithPacket:(PGPPacket *)packet -{ - if (self = [self init]) { - self.primaryKeyPacket = packet; - } - return self; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ %@",[super description], [self.primaryKeyPacket description]]; -} - -- (PGPKeyID *)keyID -{ - //note: public key packet because this is main class for public and secret class - PGPPublicKeyPacket *primaryKeyPacket = (PGPPublicKeyPacket *)self.primaryKeyPacket; - PGPKeyID *keyID = [[PGPKeyID alloc] initWithFingerprint:primaryKeyPacket.fingerprint]; - return keyID; -} - -- (NSArray *) allPackets -{ - NSMutableArray *arr = [NSMutableArray array]; - - [arr addObject:self.primaryKeyPacket]; - - if (self.revocationSignature) { - [arr addObject:self.revocationSignature]; - } - - if (self.bindingSignature) { - [arr addObject:self.bindingSignature]; - } - - return [arr copy]; -} -@end diff --git a/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h b/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h deleted file mode 100644 index a785ec3b..00000000 --- a/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PGPSymmetricallyEncryptedDataPacket.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 04/06/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPPacket.h" -#import "PGPSymmetricallyEncryptedDataPacket.h" - -@class PGPSecretKeyPacket, PGPPublicKeyPacket; - -@interface PGPSymmetricallyEncryptedIntegrityProtectedDataPacket : PGPSymmetricallyEncryptedDataPacket -@property (assign) NSUInteger version; - -- (BOOL) encrypt:(NSData *)literalPacketData symmetricAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData error:(NSError * __autoreleasing *)error; -- (NSArray *) decryptWithSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData isIntegrityProtected:(BOOL *)isIntegrityProtected error:(NSError * __autoreleasing *)error; - -@end diff --git a/PGPTypes.h b/PGPTypes.h deleted file mode 100644 index 0400ece6..00000000 --- a/PGPTypes.h +++ /dev/null @@ -1,180 +0,0 @@ -// -// PGPTypes.h -// PGPKeyring -// -// Created by Marcin Krzyzanowski on 04/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#pragma once - -#ifndef NS_DESIGNATED_INITIALIZER -#define NS_DESIGNATED_INITIALIZER -#endif - -static NSString * const PGPErrorDomain = @"ObjectivePGP"; - -typedef NS_ENUM(NSInteger, PGPErrorCode) { - PGPErrorGeneral = -1, - PGPErrorPassphraseRequired = 5, - PGPErrorPassphraseInvalid = 6 -}; - -typedef NS_ENUM(NSInteger, PGPFormatType) { - PGPFormatUnknown = 0, - PGPFormatOld = 1, - PGPFormatNew = 2 -}; - -typedef NS_ENUM(NSUInteger, PGPHeaderPacketTag) { - PGPHeaderPacketTagNewFormat = 0x40, - PGPHeaderPacketTagAllwaysSet = 0x80 -}; - -typedef NS_ENUM(UInt8, PGPPacketTag) { - PGPInvalidPacketTag = 0, - PGPPublicKeyEncryptedSessionKeyPacketTag = 1, - PGPSignaturePacketTag = 2, - PGPSymetricKeyEncryptedSessionKeyPacketTag = 3, //TODO - PGPOnePassSignaturePacketTag = 4, - PGPSecretKeyPacketTag = 5, - PGPPublicKeyPacketTag = 6, - PGPSecretSubkeyPacketTag = 7, - PGPCompressedDataPacketTag = 8, - PGPSymmetricallyEncryptedDataPacketTag = 9, //TODO - PGPMarkerPacketTag = 10, //Ignored (Obsolete Literal Packet) - PGPLiteralDataPacketTag = 11, - PGPTrustPacketTag = 12, - PGPUserIDPacketTag = 13, - PGPPublicSubkeyPacketTag = 14, - PGPUserAttributePacketTag = 17, - PGPSymmetricallyEncryptedIntegrityProtectedDataPacketTag = 18, - PGPModificationDetectionCodePacketTag = 19, -}; - -// 9.1. Public-Key Algorithms -typedef NS_ENUM(UInt8, PGPPublicKeyAlgorithm) { - PGPPublicKeyAlgorithmRSA = 1, - PGPPublicKeyAlgorithmRSAEncryptOnly = 2, - PGPPublicKeyAlgorithmRSASignOnly = 3, - PGPPublicKeyAlgorithmElgamal = 16,// Elgamal (Encrypt-Only) - PGPPublicKeyAlgorithmDSA = 17, - PGPPublicKeyAlgorithmElliptic = 18, - PGPPublicKeyAlgorithmECDSA = 19, - PGPPublicKeyAlgorithmElgamalEncryptorSign = 20,// Deprecated ? - PGPPublicKeyAlgorithmDiffieHellman = 21, - PGPPublicKeyAlgorithmPrivate1 = 100, - PGPPublicKeyAlgorithmPrivate2 = 101, - PGPPublicKeyAlgorithmPrivate3 = 102, - PGPPublicKeyAlgorithmPrivate4 = 103, - PGPPublicKeyAlgorithmPrivate5 = 104, - PGPPublicKeyAlgorithmPrivate6 = 105, - PGPPublicKeyAlgorithmPrivate7 = 106, - PGPPublicKeyAlgorithmPrivate8 = 107, - PGPPublicKeyAlgorithmPrivate9 = 108, - PGPPublicKeyAlgorithmPrivate10 = 109, - PGPPublicKeyAlgorithmPrivate11 = 110 -}; - -// 9.2. Symmetric-Key Algorithms -typedef NS_ENUM(UInt8, PGPSymmetricAlgorithm) { - PGPSymmetricPlaintext = 0, - PGPSymmetricIDEA = 1, // 8 bytes (64-bit) block size, key length: 2 bytes (16 bit) - PGPSymmetricTripleDES = 2, // 8 bytes (64-bit) block size - PGPSymmetricCAST5 = 3, // aka CAST-128 is a symmetric block cipher with a block-size of 8 bytes (64bit) and a variable key-size of up to 16 bytes (128 bits). - PGPSymmetricBlowfish = 4, // 8 bytes (64 bit) block size, key length: 16 bits (4-56 bits) - PGPSymmetricAES128 = 7, // 16 bytes (128 bit), key length 128 bit - PGPSymmetricAES192 = 8, // 16 bytes (128 bit), key length 192 bit - PGPSymmetricAES256 = 9, // 16 bytes (128 bit), key length 256 bit - PGPSymmetricTwofish256 = 10, // 16 bytes (128 bit) - PGPSymmetricMax -}; - -// 9.4. Hash Algorithms -typedef NS_ENUM(UInt8, PGPHashAlgorithm) { - PGPHashMD5 = 1, //MD5 - deprecated - PGPHashSHA1 = 2, //SHA1 - required - PGPHashRIPEMD160 = 3, //RIPEMD160 - PGPHashSHA256 = 8, //SHA256 - PGPHashSHA384 = 9, //SHA384 - PGPHashSHA512 = 10,//SHA512 - PGPHashSHA224 = 11 //SHA224 -}; - -typedef NS_ENUM(UInt8, PGPSignatureType) { - PGPSignatureBinaryDocument = 0x00, - PGPSignatureCanonicalTextDocument = 0x01, - PGPSignatureStandalone = 0x02, - PGPSignatureGenericCertificationUserIDandPublicKey = 0x10, // Self-Signature - PGPSignaturePersonalCertificationUserIDandPublicKey = 0x11, // Self-Signature - PGPSignatureCasualCertificationUserIDandPublicKey = 0x12, // Self-Signature - PGPSignaturePositiveCertificationUserIDandPublicKey = 0x13, // Self-Signature - PGPSignatureSubkeyBinding = 0x18, // Self-Signature - PGPSignaturePrimaryKeyBinding = 0x19, - PGPSignatureDirectlyOnKey = 0x1F, // 0x1F: Signature directly on a key (key) - Self-Signature - PGPSignatureKeyRevocation = 0x20, // 0x20: Key revocation signature (key_revocation) - PGPSignatureSubkeyRevocation = 0x28, // 0x28: Subkey revocation signature (subkey_revocation) - PGPSignatureCertificationRevocation = 0x30, // 0x30: Certification revocation signature (cert_revocation) - PGPSignatureTimestamp = 0x40, - PGPSignature3PartyConfirmation = 0x50 -}; - -typedef NS_ENUM(UInt8, PGPSignatureSubpacketType) { - PGPSignatureSubpacketTypeSignatureCreationTime = 2, - PGPSignatureSubpacketTypeSignatureExpirationTime = 3, - PGPSignatureSubpacketTypeExportableCertification = 4, - PGPSignatureSubpacketTypeTrustSignature = 5, //TODO - PGPSignatureSubpacketTypeRegularExpression = 6, //TODO - PGPSignatureSubpacketTypeRevocable = 7, //TODO - PGPSignatureSubpacketTypeKeyExpirationTime = 9, - PGPSignatureSubpacketTypePreferredSymetricAlgorithm = 11, - PGPSignatureSubpacketTypeRevocationKey = 12,//TODO - PGPSignatureSubpacketTypeIssuerKeyID = 16, - PGPSignatureSubpacketTypeNotationData = 20,//TODO - PGPSignatureSubpacketTypePreferredHashAlgorithm = 21, - PGPSignatureSubpacketTypePreferredCompressionAlgorithm = 22, - PGPSignatureSubpacketTypeKeyServerPreference = 23, - PGPSignatureSubpacketTypePreferredKeyServer = 24, - PGPSignatureSubpacketTypePrimaryUserID = 25, - PGPSignatureSubpacketTypePolicyURI = 26, - PGPSignatureSubpacketTypeKeyFlags = 27, - PGPSignatureSubpacketTypeSignerUserID = 28, - PGPSignatureSubpacketTypeReasonForRevocation = 29, - PGPSignatureSubpacketTypeFeatures = 30, - PGPSignatureSubpacketTypeSignatureTarget = 31,//TODO - PGPSignatureSubpacketTypeEmbeddedSignature = 32 //TODO -}; - -// 5.2.3.21. Key Flags -typedef NS_ENUM(UInt8, PGPSignatureFlags) { - PGPSignatureFlagAllowCertifyOtherKeys = 0x01,// indicates that this key may be used to certify other keys - PGPSignatureFlagAllowSignData = 0x02,// indicates that this key may be used to sign data. - PGPSignatureFlagAllowEncryptCommunications = 0x04,// indicates that this key may be used to encrypt communication. - PGPSignatureFlagAllowEncryptStorage = 0x08,// indicates that this key may be used to encrypt storage. - PGPSignatureFlagSecretComponentMayBeSplit = 0x10,// indicates that the secret components of this key may have been split using a secret-sharing mechanism. - PGPSignatureFlagAllowAuthentication = 0x20,// indicates that this key may be used for authentication. - PGPSignatureFlagPrivateKeyMayBeInThePossesionOfManyPersons = 0x80 // indicates that the secret components of this key may be in the possession of more than one person. -}; - -// 5.2.3.17. Key Server Preferences -typedef NS_ENUM(UInt8, PGPKeyServerPreferenceFlags) { - PGPKeyServerPreferenceNoModify = 0x80 // No-modify -}; - -// 5.2.3.24. Features -typedef NS_ENUM(UInt8, PGPFeature) { - PGPFeatureModificationDetection = 0x01 // Modification Detection (packets 18 and 19) -}; - -// 3.7.1. String-to-Key (S2K) Specifier Types -typedef NS_ENUM(UInt8, PGPS2KSpecifier) { - PGPS2KSpecifierSimple = 0, - PGPS2KSpecifierSalted = 1, - PGPS2KSpecifierIteratedAndSalted = 3 -}; - -typedef NS_ENUM(UInt8, PGPS2KUsage) { - PGPS2KUsageNone = 0, - PGPS2KUsageEncryptedAndHashed = 254, - PGPS2KUsageEncrypted = 255 -}; diff --git a/PGPUser.h b/PGPUser.h deleted file mode 100644 index cb777552..00000000 --- a/PGPUser.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// PGPUser.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 15/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "PGPPacket.h" - -@class PGPUserIDPacket, PGPUserAttributePacket, PGPSignaturePacket, PGPKey; - -@interface PGPUser : NSObject -@property (strong, nonatomic) NSString *userID; -@property (strong, nonatomic) PGPUserAttributePacket *userAttribute; -@property (strong, nonatomic) NSArray *selfCertifications; -@property (strong, nonatomic) NSArray *otherSignatures; -@property (strong, nonatomic) NSArray *revocationSignatures; - -@property (strong, nonatomic) PGPUserIDPacket *userIDPacket; - -- (instancetype) initWithUserIDPacket:(PGPUserIDPacket *)userPacket; -- (NSArray *) allPackets; -- (PGPSignaturePacket *) validSelfCertificate:(PGPKey *)key; - - -@end diff --git a/PGPUserAttributePacket.m b/PGPUserAttributePacket.m deleted file mode 100644 index 3074d302..00000000 --- a/PGPUserAttributePacket.m +++ /dev/null @@ -1,82 +0,0 @@ -// -// PGPUserAttributePacket.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 24/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPUserAttributePacket.h" -#import "PGPUserAttributeSubpacket.h" - -@implementation PGPUserAttributePacket - -- (PGPPacketTag)tag -{ - return PGPUserAttributePacketTag; -} - -//TODO: handle image subtype. Somehow it's broken, so not supported. -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - NSUInteger position = [super parsePacketBody:packetBody error:error]; - position = position + packetBody.length; - return position; -// while (position < position + packetBody.length) { -// UInt8 lengthLength = 0; -// UInt8 *lengthOctets = (UInt8 *)[packetBody subdataWithRange:(NSRange){position, 5}].bytes; -// UInt8 subpacketLength = lengthOctets[0]; -// -// if (lengthOctets[0] < 192) { -// // 4.2.2.1. One-Octet Length -// // bodyLen = 1st_octet; -// subpacketLength = lengthOctets[0]; -// lengthLength = 1; -// } else if (lengthOctets[0] >= 192 && lengthOctets[0] <= 223) { -// // 4.2.2.2. Two-Octet Lengths -// // bodyLen = ((1st_octet - 192) << 8) + (2nd_octet) + 192 -// subpacketLength = ((lengthOctets[0] - 192) << 8) + (lengthOctets[1]) + 192; -// lengthLength = 2; -// } else { -// // 4.2.2.3. Five-Octet Length -// // bodyLen = (2nd_octet << 24) | (3rd_octet << 16) | -// // (4th_octet << 8) | 5th_octet -// subpacketLength = (lengthOctets[1] << 24) | (lengthOctets[2] << 16) | (lengthOctets[3] << 8) | lengthOctets[4]; -// lengthLength = 5; -// } -// NSLog(@"PGPUserAttributePacket subpacketLength %@ (%@)",@(subpacketLength), @(lengthLength)); -// position = position + lengthLength; -// -// UInt8 subpacketType = 0; -// [packetBody getBytes:&subpacketType range:(NSRange){position, 1}]; -// position = position + 1; -// -//// PGPUserAttributeSubpacket *subpacket = [[PGPUserAttributeSubpacket alloc] init]; -//// subpacket.type = subpacketType; -//// subpacket.valueData = [packetBody subdataWithRange:(NSRange){position, subpacketLength}]; -//// position = position + subpacketLength; -//// -//// self.subpackets = [self.subpackets arrayByAddingObject:subpacket]; -// } - - return position; -} - -- (NSData *)exportPacket:(NSError *__autoreleasing *)error -{ - //TODO: export - return nil; -} - -- (NSUInteger)hash -{ - NSUInteger prime = 31; - NSUInteger result = 1; - - result = prime * result + self.tag; - result = prime * result + [_subpackets hash]; - - return result; -} - -@end diff --git a/PGPUserIDPacket.h b/PGPUserIDPacket.h deleted file mode 100644 index b3fbdd0e..00000000 --- a/PGPUserIDPacket.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// PGPUserID.h -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 05/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// -// Tag 13 - -#import <Foundation/Foundation.h> -#import "PGPPacketFactory.h" - -@interface PGPUserIDPacket : PGPPacket - -@property (retain, readonly) NSString *userID; - -@end diff --git a/PGPUserIDPacket.m b/PGPUserIDPacket.m deleted file mode 100644 index 66d4be78..00000000 --- a/PGPUserIDPacket.m +++ /dev/null @@ -1,49 +0,0 @@ -// -// PGPUserID.m -// ObjectivePGP -// -// Created by Marcin Krzyzanowski on 05/05/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. -// - -#import "PGPUserIDPacket.h" - -@interface PGPPacket () -@property (copy, readwrite) NSData *headerData; -@property (copy, readwrite) NSData *bodyData; -@end - -@implementation PGPUserIDPacket - -- (PGPPacketTag)tag -{ - return PGPUserIDPacketTag; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ %@",[super description], self.userID]; -} - -- (NSUInteger) parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ - NSUInteger position = [super parsePacketBody:packetBody error:error]; - - _userID = [[NSString alloc] initWithData:packetBody encoding:NSUTF8StringEncoding]; - position = position + packetBody.length; - - return position; -} - -- (NSData *) exportPacket:(NSError *__autoreleasing *)error -{ - NSMutableData *data = [NSMutableData data]; - NSData *bodyData = [self.userID dataUsingEncoding:NSUTF8StringEncoding]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - return [data copy]; -} - - -@end diff --git a/enzevalos_iphone.xcodeproj/project.pbxproj b/enzevalos_iphone.xcodeproj/project.pbxproj index 6a2d0060..cb4fb060 100644 --- a/enzevalos_iphone.xcodeproj/project.pbxproj +++ b/enzevalos_iphone.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 4715B0F51EF3D58100520DE5 /* DecryptedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4715B0F41EF3D58100520DE5 /* DecryptedData.swift */; }; 4725C4F61EDDADA10068235E /* bob-private.gpg in Resources */ = {isa = PBXBuildFile; fileRef = 4725C4F41EDDADA10068235E /* bob-private.gpg */; }; 4725C4F71EDDADA10068235E /* bob-public.gpg in Resources */ = {isa = PBXBuildFile; fileRef = 4725C4F51EDDADA10068235E /* bob-public.gpg */; }; 472F392A1E1277D2009260FB /* EnzevalosContact+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F39261E1277D2009260FB /* EnzevalosContact+CoreDataClass.swift */; }; @@ -26,6 +25,56 @@ 472F398C1E2519C8009260FB /* CNContactExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F398B1E2519C8009260FB /* CNContactExtension.swift */; }; 472F398E1E251B8D009260FB /* MailAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F398D1E251B8D009260FB /* MailAddress.swift */; }; 472F39901E252470009260FB /* CNMailAddressesExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F398F1E252470009260FB /* CNMailAddressesExtension.swift */; }; + 475B00011F7B953B006CDD41 /* PGPCryptoHash.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFF941F7B953B006CDD41 /* PGPCryptoHash.m */; }; + 475B00021F7B953B006CDD41 /* PGPCryptoUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFF961F7B953B006CDD41 /* PGPCryptoUtils.m */; }; + 475B00031F7B953B006CDD41 /* PGPDSA.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFF981F7B953B006CDD41 /* PGPDSA.m */; }; + 475B00041F7B953B006CDD41 /* PGPKeyMaterial.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFF9A1F7B953B006CDD41 /* PGPKeyMaterial.m */; }; + 475B00051F7B953B006CDD41 /* PGPRSA.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFF9C1F7B953B006CDD41 /* PGPRSA.m */; }; + 475B00061F7B953B006CDD41 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 475BFF9D1F7B953B006CDD41 /* Info.plist */; }; + 475B00071F7B953B006CDD41 /* ObjectivePGPObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFA11F7B953B006CDD41 /* ObjectivePGPObject.m */; }; + 475B00081F7B953B006CDD41 /* PGPCompressedPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFA41F7B953B006CDD41 /* PGPCompressedPacket.m */; }; + 475B00091F7B953B006CDD41 /* PGPLiteralPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFA61F7B953B006CDD41 /* PGPLiteralPacket.m */; }; + 475B000A1F7B953B006CDD41 /* PGPModificationDetectionCodePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFA81F7B953B006CDD41 /* PGPModificationDetectionCodePacket.m */; }; + 475B000B1F7B953B006CDD41 /* PGPOnePassSignaturePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFAA1F7B953B006CDD41 /* PGPOnePassSignaturePacket.m */; }; + 475B000C1F7B953B006CDD41 /* PGPPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFAD1F7B953B006CDD41 /* PGPPacket.m */; }; + 475B000D1F7B953B006CDD41 /* PGPPublicKeyEncryptedSessionKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFB01F7B953B006CDD41 /* PGPPublicKeyEncryptedSessionKeyPacket.m */; }; + 475B000E1F7B953B006CDD41 /* PGPPublicKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFB31F7B953B006CDD41 /* PGPPublicKeyPacket.m */; }; + 475B000F1F7B953B006CDD41 /* PGPPublicSubKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFB51F7B953B006CDD41 /* PGPPublicSubKeyPacket.m */; }; + 475B00101F7B953B006CDD41 /* PGPSecretKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFB81F7B953B006CDD41 /* PGPSecretKeyPacket.m */; }; + 475B00111F7B953B006CDD41 /* PGPSecretSubKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFBA1F7B953B006CDD41 /* PGPSecretSubKeyPacket.m */; }; + 475B00121F7B953B006CDD41 /* PGPSignaturePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFBD1F7B953B006CDD41 /* PGPSignaturePacket.m */; }; + 475B00131F7B953B006CDD41 /* PGPSignatureSubpacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFC01F7B953B006CDD41 /* PGPSignatureSubpacket.m */; }; + 475B00141F7B953B006CDD41 /* PGPSignatureSubpacketCreationTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFC21F7B953B006CDD41 /* PGPSignatureSubpacketCreationTime.m */; }; + 475B00151F7B953B006CDD41 /* PGPSignatureSubpacketHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFC41F7B953B006CDD41 /* PGPSignatureSubpacketHeader.m */; }; + 475B00161F7B953B006CDD41 /* PGPSymmetricallyEncryptedDataPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFC61F7B953B006CDD41 /* PGPSymmetricallyEncryptedDataPacket.m */; }; + 475B00171F7B953B006CDD41 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFC81F7B953B006CDD41 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m */; }; + 475B00181F7B953B006CDD41 /* PGPTrustPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFCA1F7B953B006CDD41 /* PGPTrustPacket.m */; }; + 475B00191F7B953B006CDD41 /* PGPUserAttributePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFCC1F7B953B006CDD41 /* PGPUserAttributePacket.m */; }; + 475B001A1F7B953B006CDD41 /* PGPUserAttributeSubpacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFCE1F7B953B006CDD41 /* PGPUserAttributeSubpacket.m */; }; + 475B001B1F7B953B006CDD41 /* PGPUserIDPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFD01F7B953B006CDD41 /* PGPUserIDPacket.m */; }; + 475B001C1F7B953B006CDD41 /* PGPArmor.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFD21F7B953B006CDD41 /* PGPArmor.m */; }; + 475B001D1F7B953B006CDD41 /* PGPBigNum.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFD51F7B953B006CDD41 /* PGPBigNum.m */; }; + 475B001E1F7B953B006CDD41 /* PGPCryptoCFB.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFD71F7B953B006CDD41 /* PGPCryptoCFB.m */; }; + 475B001F1F7B953B006CDD41 /* PGPFingerprint.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFDA1F7B953B006CDD41 /* PGPFingerprint.m */; }; + 475B00201F7B953B006CDD41 /* PGPFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFDC1F7B953B006CDD41 /* PGPFoundation.m */; }; + 475B00211F7B953B006CDD41 /* PGPKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFDF1F7B953B006CDD41 /* PGPKey.m */; }; + 475B00221F7B953B006CDD41 /* PGPKeyGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFE11F7B953B006CDD41 /* PGPKeyGenerator.m */; }; + 475B00231F7B953B006CDD41 /* PGPKeyID.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFE31F7B953B006CDD41 /* PGPKeyID.m */; }; + 475B00241F7B953B006CDD41 /* PGPMPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFE81F7B953B006CDD41 /* PGPMPI.m */; }; + 475B00251F7B953B006CDD41 /* PGPPacketFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFEA1F7B953B006CDD41 /* PGPPacketFactory.m */; }; + 475B00261F7B953B006CDD41 /* PGPPartialKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFEC1F7B953B006CDD41 /* PGPPartialKey.m */; }; + 475B00271F7B953B006CDD41 /* PGPPartialSubKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFEE1F7B953B006CDD41 /* PGPPartialSubKey.m */; }; + 475B00281F7B953B006CDD41 /* PGPPKCSEme.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFF01F7B953B006CDD41 /* PGPPKCSEme.m */; }; + 475B00291F7B953B006CDD41 /* PGPPKCSEmsa.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFF21F7B953B006CDD41 /* PGPPKCSEmsa.m */; }; + 475B002A1F7B953B006CDD41 /* PGPS2K.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFF41F7B953B006CDD41 /* PGPS2K.m */; }; + 475B002B1F7B953B006CDD41 /* PGPUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFF71F7B953B006CDD41 /* PGPUser.m */; }; + 475B002C1F7B953B006CDD41 /* NSData+compression.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFFA1F7B953B006CDD41 /* NSData+compression.m */; }; + 475B002D1F7B953B006CDD41 /* NSData+PGPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFFC1F7B953B006CDD41 /* NSData+PGPUtils.m */; }; + 475B002E1F7B953B006CDD41 /* NSMutableArray+PGPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 475BFFFE1F7B953B006CDD41 /* NSMutableArray+PGPUtils.m */; }; + 475B002F1F7B953B006CDD41 /* NSMutableData+PGPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 475B00001F7B953B006CDD41 /* NSMutableData+PGPUtils.m */; }; + 475B00331F7B9565006CDD41 /* SwiftPGP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00301F7B9565006CDD41 /* SwiftPGP.swift */; }; + 475B00341F7B9565006CDD41 /* Cryptography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00311F7B9565006CDD41 /* Cryptography.swift */; }; + 475B00351F7B9565006CDD41 /* CryptoObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00321F7B9565006CDD41 /* CryptoObject.swift */; }; 475DF4791F0D54C9009D807F /* Folder+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475DF4771F0D54C9009D807F /* Folder+CoreDataClass.swift */; }; 475DF47A1F0D54C9009D807F /* Folder+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475DF4781F0D54C9009D807F /* Folder+CoreDataProperties.swift */; }; 476142081E07E52B00FD5E4F /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476142071E07E52B00FD5E4F /* Theme.swift */; }; @@ -67,59 +116,13 @@ A1083A541E8BFEA6003666B7 /* Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1083A531E8BFEA6003666B7 /* Onboarding.swift */; }; A10DE4201EFAA2CE005E8189 /* FolderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10DE41F1EFAA2CE005E8189 /* FolderViewController.swift */; }; A1123E6A1DA682850069551C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1123E6C1DA682850069551C /* Localizable.strings */; }; - A1182C571E30F45C0024D389 /* PGPKeyManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1182C561E30F45C0024D389 /* PGPKeyManagement.swift */; }; - A1230BD71E2F8818006642C7 /* PGPEncryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1230BD61E2F8818006642C7 /* PGPEncryption.swift */; }; A13526791D955BDF00D3BFE1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A13526781D955BDF00D3BFE1 /* AppDelegate.swift */; }; A13526811D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = A135267F1D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld */; }; A13526861D955BDF00D3BFE1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A13526841D955BDF00D3BFE1 /* LaunchScreen.storyboard */; }; A13526911D955BE000D3BFE1 /* enzevalos_iphoneTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A13526901D955BE000D3BFE1 /* enzevalos_iphoneTests.swift */; }; A135269C1D955BE000D3BFE1 /* enzevalos_iphoneUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A135269B1D955BE000D3BFE1 /* enzevalos_iphoneUITests.swift */; }; - A135CF021DD4BDD1007E3C29 /* NSData+compression.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEB91DD4BDD1007E3C29 /* NSData+compression.m */; }; - A135CF031DD4BDD1007E3C29 /* NSData+PGPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEBB1DD4BDD1007E3C29 /* NSData+PGPUtils.m */; }; - A135CF041DD4BDD1007E3C29 /* NSValue+PGPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEBD1DD4BDD1007E3C29 /* NSValue+PGPUtils.m */; }; - A135CF051DD4BDD1007E3C29 /* ObjectivePGP.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEC01DD4BDD1007E3C29 /* ObjectivePGP.m */; }; - A135CF061DD4BDD1007E3C29 /* PGPArmor.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEC21DD4BDD1007E3C29 /* PGPArmor.m */; }; - A135CF071DD4BDD1007E3C29 /* PGPCompressedPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEC41DD4BDD1007E3C29 /* PGPCompressedPacket.m */; }; - A135CF081DD4BDD1007E3C29 /* PGPCryptoCFB.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEC61DD4BDD1007E3C29 /* PGPCryptoCFB.m */; }; - A135CF091DD4BDD1007E3C29 /* PGPCryptoUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEC81DD4BDD1007E3C29 /* PGPCryptoUtils.m */; }; - A135CF0A1DD4BDD1007E3C29 /* PGPFingerprint.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CECA1DD4BDD1007E3C29 /* PGPFingerprint.m */; }; - A135CF0B1DD4BDD1007E3C29 /* PGPKey.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CECC1DD4BDD1007E3C29 /* PGPKey.m */; }; - A135CF0C1DD4BDD1007E3C29 /* PGPKeyID.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CECE1DD4BDD1007E3C29 /* PGPKeyID.m */; }; - A135CF0D1DD4BDD1007E3C29 /* PGPLiteralPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CED01DD4BDD1007E3C29 /* PGPLiteralPacket.m */; }; - A135CF0E1DD4BDD1007E3C29 /* PGPModificationDetectionCodePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CED21DD4BDD1007E3C29 /* PGPModificationDetectionCodePacket.m */; }; - A135CF0F1DD4BDD1007E3C29 /* PGPMPI.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CED41DD4BDD1007E3C29 /* PGPMPI.m */; }; - A135CF101DD4BDD1007E3C29 /* PGPOnePassSignaturePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CED61DD4BDD1007E3C29 /* PGPOnePassSignaturePacket.m */; }; - A135CF111DD4BDD1007E3C29 /* PGPPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CED81DD4BDD1007E3C29 /* PGPPacket.m */; }; - A135CF121DD4BDD1007E3C29 /* PGPPacketFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEDA1DD4BDD1007E3C29 /* PGPPacketFactory.m */; }; - A135CF131DD4BDD1007E3C29 /* PGPPKCSEme.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEDC1DD4BDD1007E3C29 /* PGPPKCSEme.m */; }; - A135CF141DD4BDD1007E3C29 /* PGPPKCSEmsa.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEDE1DD4BDD1007E3C29 /* PGPPKCSEmsa.m */; }; - A135CF151DD4BDD1007E3C29 /* PGPPublicKeyEncryptedSessionKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEE01DD4BDD1007E3C29 /* PGPPublicKeyEncryptedSessionKeyPacket.m */; }; - A135CF161DD4BDD1007E3C29 /* PGPPublicKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEE21DD4BDD1007E3C29 /* PGPPublicKeyPacket.m */; }; - A135CF171DD4BDD1007E3C29 /* PGPPublicKeyRSA.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEE41DD4BDD1007E3C29 /* PGPPublicKeyRSA.m */; }; - A135CF181DD4BDD1007E3C29 /* PGPPublicSubKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEE61DD4BDD1007E3C29 /* PGPPublicSubKeyPacket.m */; }; - A135CF191DD4BDD1007E3C29 /* PGPS2K.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEE81DD4BDD1007E3C29 /* PGPS2K.m */; }; - A135CF1A1DD4BDD1007E3C29 /* PGPSecretKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEEA1DD4BDD1007E3C29 /* PGPSecretKeyPacket.m */; }; - A135CF1B1DD4BDD1007E3C29 /* PGPSecretSubKeyPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEEC1DD4BDD1007E3C29 /* PGPSecretSubKeyPacket.m */; }; - A135CF1C1DD4BDD1007E3C29 /* PGPSignaturePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEEE1DD4BDD1007E3C29 /* PGPSignaturePacket.m */; }; - A135CF1D1DD4BDD1007E3C29 /* PGPSignatureSubpacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEF01DD4BDD1007E3C29 /* PGPSignatureSubpacket.m */; }; - A135CF1E1DD4BDD1007E3C29 /* PGPSubKey.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEF21DD4BDD1007E3C29 /* PGPSubKey.m */; }; - A135CF1F1DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedDataPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEF41DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedDataPacket.m */; }; - A135CF201DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEF61DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m */; }; - A135CF211DD4BDD1007E3C29 /* PGPTrustPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEF81DD4BDD1007E3C29 /* PGPTrustPacket.m */; }; - A135CF221DD4BDD1007E3C29 /* PGPUser.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEFB1DD4BDD1007E3C29 /* PGPUser.m */; }; - A135CF231DD4BDD1007E3C29 /* PGPUserAttributePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEFD1DD4BDD1007E3C29 /* PGPUserAttributePacket.m */; }; - A135CF241DD4BDD1007E3C29 /* PGPUserAttributeSubpacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CEFF1DD4BDD1007E3C29 /* PGPUserAttributeSubpacket.m */; }; - A135CF251DD4BDD1007E3C29 /* PGPUserIDPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = A135CF011DD4BDD1007E3C29 /* PGPUserIDPacket.m */; }; - A1416C191E268EFB001809F3 /* EncryptionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1416C181E268EFB001809F3 /* EncryptionHandler.swift */; }; - A1416C1B1E268F1A001809F3 /* Encryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1416C1A1E268F1A001809F3 /* Encryption.swift */; }; - A15B7BE41E29306D0024E499 /* EnzevalosEncryptionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15B7BE31E29306D0024E499 /* EnzevalosEncryptionHandler.swift */; }; - A15B7BE61E2931AD0024E499 /* KeyWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15B7BE51E2931AD0024E499 /* KeyWrapper.swift */; }; - A15B7BE81E2934CB0024E499 /* EncryptionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15B7BE71E2934CB0024E499 /* EncryptionType.swift */; }; A16BA2121E0439B6005E29E3 /* providers.json in Resources */ = {isa = PBXBuildFile; fileRef = A16BA2111E0439B6005E29E3 /* providers.json */; }; - A172F90D1E4CD37D00F2A136 /* PGPTemporaryDecryptionObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = A172F90C1E4CD37D00F2A136 /* PGPTemporaryDecryptionObject.swift */; }; - A17A18F71DDCBE530058D934 /* PGPKeyWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17A18F61DDCBE530058D934 /* PGPKeyWrapper.swift */; }; A17A18F91DDCCF370058D934 /* JakobBode.asc in Resources */ = {isa = PBXBuildFile; fileRef = A17A18F81DDCCF370058D934 /* JakobBode.asc */; }; - A17BEB391E55E3DD00403EBE /* PGPTemporaryDecryptionObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A17BEB381E55E3DD00403EBE /* PGPTemporaryDecryptionObject.m */; }; A17C04841DC6504E00F66EDB /* LogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17C04831DC6504E00F66EDB /* LogHandler.swift */; }; A19C12471DE602FF007F72E7 /* jabo.asc in Resources */ = {isa = PBXBuildFile; fileRef = A19C12461DE602FF007F72E7 /* jabo.asc */; }; A1B8C01A1DD5D9B10044A358 /* alice2005-2.gpg in Resources */ = {isa = PBXBuildFile; fileRef = A1B8C0191DD5D9B10044A358 /* alice2005-2.gpg */; }; @@ -198,7 +201,6 @@ /* Begin PBXFileReference section */ 411EB2B85F99B48FFD36F966 /* Pods-enzevalos_iphoneTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-enzevalos_iphoneTests.debug.xcconfig"; path = "../workspace/Pods/Target Support Files/Pods-enzevalos_iphoneTests/Pods-enzevalos_iphoneTests.debug.xcconfig"; sourceTree = "<group>"; }; - 4715B0F41EF3D58100520DE5 /* DecryptedData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecryptedData.swift; sourceTree = "<group>"; }; 4725C4F41EDDADA10068235E /* bob-private.gpg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "bob-private.gpg"; path = "keys/bob-private.gpg"; sourceTree = "<group>"; }; 4725C4F51EDDADA10068235E /* bob-public.gpg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "bob-public.gpg"; path = "keys/bob-public.gpg"; sourceTree = "<group>"; }; 472F39261E1277D2009260FB /* EnzevalosContact+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "EnzevalosContact+CoreDataClass.swift"; path = "../EnzevalosContact+CoreDataClass.swift"; sourceTree = "<group>"; }; @@ -217,6 +219,117 @@ 472F398B1E2519C8009260FB /* CNContactExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CNContactExtension.swift; sourceTree = "<group>"; }; 472F398D1E251B8D009260FB /* MailAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MailAddress.swift; sourceTree = "<group>"; }; 472F398F1E252470009260FB /* CNMailAddressesExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CNMailAddressesExtension.swift; sourceTree = "<group>"; }; + 475B00001F7B953B006CDD41 /* NSMutableData+PGPUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableData+PGPUtils.m"; sourceTree = "<group>"; }; + 475B00301F7B9565006CDD41 /* SwiftPGP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftPGP.swift; sourceTree = "<group>"; }; + 475B00311F7B9565006CDD41 /* Cryptography.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cryptography.swift; sourceTree = "<group>"; }; + 475B00321F7B9565006CDD41 /* CryptoObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CryptoObject.swift; sourceTree = "<group>"; }; + 475BFF931F7B953B006CDD41 /* PGPCryptoHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPCryptoHash.h; sourceTree = "<group>"; }; + 475BFF941F7B953B006CDD41 /* PGPCryptoHash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPCryptoHash.m; sourceTree = "<group>"; }; + 475BFF951F7B953B006CDD41 /* PGPCryptoUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPCryptoUtils.h; sourceTree = "<group>"; }; + 475BFF961F7B953B006CDD41 /* PGPCryptoUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPCryptoUtils.m; sourceTree = "<group>"; }; + 475BFF971F7B953B006CDD41 /* PGPDSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPDSA.h; sourceTree = "<group>"; }; + 475BFF981F7B953B006CDD41 /* PGPDSA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPDSA.m; sourceTree = "<group>"; }; + 475BFF991F7B953B006CDD41 /* PGPKeyMaterial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPKeyMaterial.h; sourceTree = "<group>"; }; + 475BFF9A1F7B953B006CDD41 /* PGPKeyMaterial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPKeyMaterial.m; sourceTree = "<group>"; }; + 475BFF9B1F7B953B006CDD41 /* PGPRSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPRSA.h; sourceTree = "<group>"; }; + 475BFF9C1F7B953B006CDD41 /* PGPRSA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPRSA.m; sourceTree = "<group>"; }; + 475BFF9D1F7B953B006CDD41 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 475BFF9E1F7B953B006CDD41 /* ObjectivePGP-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ObjectivePGP-Prefix.pch"; sourceTree = "<group>"; }; + 475BFF9F1F7B953B006CDD41 /* ObjectivePGP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectivePGP.h; sourceTree = "<group>"; }; + 475BFFA01F7B953B006CDD41 /* ObjectivePGPObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectivePGPObject.h; sourceTree = "<group>"; }; + 475BFFA11F7B953B006CDD41 /* ObjectivePGPObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjectivePGPObject.m; sourceTree = "<group>"; }; + 475BFFA31F7B953B006CDD41 /* PGPCompressedPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPCompressedPacket.h; sourceTree = "<group>"; }; + 475BFFA41F7B953B006CDD41 /* PGPCompressedPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPCompressedPacket.m; sourceTree = "<group>"; }; + 475BFFA51F7B953B006CDD41 /* PGPLiteralPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPLiteralPacket.h; sourceTree = "<group>"; }; + 475BFFA61F7B953B006CDD41 /* PGPLiteralPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPLiteralPacket.m; sourceTree = "<group>"; }; + 475BFFA71F7B953B006CDD41 /* PGPModificationDetectionCodePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPModificationDetectionCodePacket.h; sourceTree = "<group>"; }; + 475BFFA81F7B953B006CDD41 /* PGPModificationDetectionCodePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPModificationDetectionCodePacket.m; sourceTree = "<group>"; }; + 475BFFA91F7B953B006CDD41 /* PGPOnePassSignaturePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPOnePassSignaturePacket.h; sourceTree = "<group>"; }; + 475BFFAA1F7B953B006CDD41 /* PGPOnePassSignaturePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPOnePassSignaturePacket.m; sourceTree = "<group>"; }; + 475BFFAB1F7B953B006CDD41 /* PGPPacket+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPPacket+Private.h"; sourceTree = "<group>"; }; + 475BFFAC1F7B953B006CDD41 /* PGPPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPacket.h; sourceTree = "<group>"; }; + 475BFFAD1F7B953B006CDD41 /* PGPPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPacket.m; sourceTree = "<group>"; }; + 475BFFAE1F7B953B006CDD41 /* PGPPacketProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPacketProtocol.h; sourceTree = "<group>"; }; + 475BFFAF1F7B953B006CDD41 /* PGPPublicKeyEncryptedSessionKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPublicKeyEncryptedSessionKeyPacket.h; sourceTree = "<group>"; }; + 475BFFB01F7B953B006CDD41 /* PGPPublicKeyEncryptedSessionKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPublicKeyEncryptedSessionKeyPacket.m; sourceTree = "<group>"; }; + 475BFFB11F7B953B006CDD41 /* PGPPublicKeyPacket+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPPublicKeyPacket+Private.h"; sourceTree = "<group>"; }; + 475BFFB21F7B953B006CDD41 /* PGPPublicKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPublicKeyPacket.h; sourceTree = "<group>"; }; + 475BFFB31F7B953B006CDD41 /* PGPPublicKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPublicKeyPacket.m; sourceTree = "<group>"; }; + 475BFFB41F7B953B006CDD41 /* PGPPublicSubKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPublicSubKeyPacket.h; sourceTree = "<group>"; }; + 475BFFB51F7B953B006CDD41 /* PGPPublicSubKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPublicSubKeyPacket.m; sourceTree = "<group>"; }; + 475BFFB61F7B953B006CDD41 /* PGPSecretKeyPacket+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPSecretKeyPacket+Private.h"; sourceTree = "<group>"; }; + 475BFFB71F7B953B006CDD41 /* PGPSecretKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSecretKeyPacket.h; sourceTree = "<group>"; }; + 475BFFB81F7B953B006CDD41 /* PGPSecretKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSecretKeyPacket.m; sourceTree = "<group>"; }; + 475BFFB91F7B953B006CDD41 /* PGPSecretSubKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSecretSubKeyPacket.h; sourceTree = "<group>"; }; + 475BFFBA1F7B953B006CDD41 /* PGPSecretSubKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSecretSubKeyPacket.m; sourceTree = "<group>"; }; + 475BFFBB1F7B953B006CDD41 /* PGPSignaturePacket+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPSignaturePacket+Private.h"; sourceTree = "<group>"; }; + 475BFFBC1F7B953B006CDD41 /* PGPSignaturePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSignaturePacket.h; sourceTree = "<group>"; }; + 475BFFBD1F7B953B006CDD41 /* PGPSignaturePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSignaturePacket.m; sourceTree = "<group>"; }; + 475BFFBE1F7B953B006CDD41 /* PGPSignatureSubpacket+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPSignatureSubpacket+Private.h"; sourceTree = "<group>"; }; + 475BFFBF1F7B953B006CDD41 /* PGPSignatureSubpacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSignatureSubpacket.h; sourceTree = "<group>"; }; + 475BFFC01F7B953B006CDD41 /* PGPSignatureSubpacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSignatureSubpacket.m; sourceTree = "<group>"; }; + 475BFFC11F7B953B006CDD41 /* PGPSignatureSubpacketCreationTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSignatureSubpacketCreationTime.h; sourceTree = "<group>"; }; + 475BFFC21F7B953B006CDD41 /* PGPSignatureSubpacketCreationTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSignatureSubpacketCreationTime.m; sourceTree = "<group>"; }; + 475BFFC31F7B953B006CDD41 /* PGPSignatureSubpacketHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSignatureSubpacketHeader.h; sourceTree = "<group>"; }; + 475BFFC41F7B953B006CDD41 /* PGPSignatureSubpacketHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSignatureSubpacketHeader.m; sourceTree = "<group>"; }; + 475BFFC51F7B953B006CDD41 /* PGPSymmetricallyEncryptedDataPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSymmetricallyEncryptedDataPacket.h; sourceTree = "<group>"; }; + 475BFFC61F7B953B006CDD41 /* PGPSymmetricallyEncryptedDataPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSymmetricallyEncryptedDataPacket.m; sourceTree = "<group>"; }; + 475BFFC71F7B953B006CDD41 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h; sourceTree = "<group>"; }; + 475BFFC81F7B953B006CDD41 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m; sourceTree = "<group>"; }; + 475BFFC91F7B953B006CDD41 /* PGPTrustPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPTrustPacket.h; sourceTree = "<group>"; }; + 475BFFCA1F7B953B006CDD41 /* PGPTrustPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPTrustPacket.m; sourceTree = "<group>"; }; + 475BFFCB1F7B953B006CDD41 /* PGPUserAttributePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUserAttributePacket.h; sourceTree = "<group>"; }; + 475BFFCC1F7B953B006CDD41 /* PGPUserAttributePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUserAttributePacket.m; sourceTree = "<group>"; }; + 475BFFCD1F7B953B006CDD41 /* PGPUserAttributeSubpacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUserAttributeSubpacket.h; sourceTree = "<group>"; }; + 475BFFCE1F7B953B006CDD41 /* PGPUserAttributeSubpacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUserAttributeSubpacket.m; sourceTree = "<group>"; }; + 475BFFCF1F7B953B006CDD41 /* PGPUserIDPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUserIDPacket.h; sourceTree = "<group>"; }; + 475BFFD01F7B953B006CDD41 /* PGPUserIDPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUserIDPacket.m; sourceTree = "<group>"; }; + 475BFFD11F7B953B006CDD41 /* PGPArmor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPArmor.h; sourceTree = "<group>"; }; + 475BFFD21F7B953B006CDD41 /* PGPArmor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPArmor.m; sourceTree = "<group>"; }; + 475BFFD31F7B953B006CDD41 /* PGPBigNum+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPBigNum+Private.h"; sourceTree = "<group>"; }; + 475BFFD41F7B953B006CDD41 /* PGPBigNum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPBigNum.h; sourceTree = "<group>"; }; + 475BFFD51F7B953B006CDD41 /* PGPBigNum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPBigNum.m; sourceTree = "<group>"; }; + 475BFFD61F7B953B006CDD41 /* PGPCryptoCFB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPCryptoCFB.h; sourceTree = "<group>"; }; + 475BFFD71F7B953B006CDD41 /* PGPCryptoCFB.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPCryptoCFB.m; sourceTree = "<group>"; }; + 475BFFD81F7B953B006CDD41 /* PGPExportableProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPExportableProtocol.h; sourceTree = "<group>"; }; + 475BFFD91F7B953B006CDD41 /* PGPFingerprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPFingerprint.h; sourceTree = "<group>"; }; + 475BFFDA1F7B953B006CDD41 /* PGPFingerprint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPFingerprint.m; sourceTree = "<group>"; }; + 475BFFDB1F7B953B006CDD41 /* PGPFoundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPFoundation.h; sourceTree = "<group>"; }; + 475BFFDC1F7B953B006CDD41 /* PGPFoundation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPFoundation.m; sourceTree = "<group>"; }; + 475BFFDD1F7B953B006CDD41 /* PGPKey+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPKey+Private.h"; sourceTree = "<group>"; }; + 475BFFDE1F7B953B006CDD41 /* PGPKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPKey.h; sourceTree = "<group>"; }; + 475BFFDF1F7B953B006CDD41 /* PGPKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPKey.m; sourceTree = "<group>"; }; + 475BFFE01F7B953B006CDD41 /* PGPKeyGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPKeyGenerator.h; sourceTree = "<group>"; }; + 475BFFE11F7B953B006CDD41 /* PGPKeyGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPKeyGenerator.m; sourceTree = "<group>"; }; + 475BFFE21F7B953B006CDD41 /* PGPKeyID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPKeyID.h; sourceTree = "<group>"; }; + 475BFFE31F7B953B006CDD41 /* PGPKeyID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPKeyID.m; sourceTree = "<group>"; }; + 475BFFE41F7B953B006CDD41 /* PGPLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPLogging.h; sourceTree = "<group>"; }; + 475BFFE51F7B953B006CDD41 /* PGPMacros+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGPMacros+Private.h"; sourceTree = "<group>"; }; + 475BFFE61F7B953B006CDD41 /* PGPMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPMacros.h; sourceTree = "<group>"; }; + 475BFFE71F7B953B006CDD41 /* PGPMPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPMPI.h; sourceTree = "<group>"; }; + 475BFFE81F7B953B006CDD41 /* PGPMPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPMPI.m; sourceTree = "<group>"; }; + 475BFFE91F7B953B006CDD41 /* PGPPacketFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPacketFactory.h; sourceTree = "<group>"; }; + 475BFFEA1F7B953B006CDD41 /* PGPPacketFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPacketFactory.m; sourceTree = "<group>"; }; + 475BFFEB1F7B953B006CDD41 /* PGPPartialKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPartialKey.h; sourceTree = "<group>"; }; + 475BFFEC1F7B953B006CDD41 /* PGPPartialKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPartialKey.m; sourceTree = "<group>"; }; + 475BFFED1F7B953B006CDD41 /* PGPPartialSubKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPartialSubKey.h; sourceTree = "<group>"; }; + 475BFFEE1F7B953B006CDD41 /* PGPPartialSubKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPartialSubKey.m; sourceTree = "<group>"; }; + 475BFFEF1F7B953B006CDD41 /* PGPPKCSEme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPKCSEme.h; sourceTree = "<group>"; }; + 475BFFF01F7B953B006CDD41 /* PGPPKCSEme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPKCSEme.m; sourceTree = "<group>"; }; + 475BFFF11F7B953B006CDD41 /* PGPPKCSEmsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPKCSEmsa.h; sourceTree = "<group>"; }; + 475BFFF21F7B953B006CDD41 /* PGPPKCSEmsa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPKCSEmsa.m; sourceTree = "<group>"; }; + 475BFFF31F7B953B006CDD41 /* PGPS2K.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPS2K.h; sourceTree = "<group>"; }; + 475BFFF41F7B953B006CDD41 /* PGPS2K.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPS2K.m; sourceTree = "<group>"; }; + 475BFFF51F7B953B006CDD41 /* PGPTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPTypes.h; sourceTree = "<group>"; }; + 475BFFF61F7B953B006CDD41 /* PGPUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUser.h; sourceTree = "<group>"; }; + 475BFFF71F7B953B006CDD41 /* PGPUser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUser.m; sourceTree = "<group>"; }; + 475BFFF91F7B953B006CDD41 /* NSData+compression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+compression.h"; sourceTree = "<group>"; }; + 475BFFFA1F7B953B006CDD41 /* NSData+compression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+compression.m"; sourceTree = "<group>"; }; + 475BFFFB1F7B953B006CDD41 /* NSData+PGPUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+PGPUtils.h"; sourceTree = "<group>"; }; + 475BFFFC1F7B953B006CDD41 /* NSData+PGPUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+PGPUtils.m"; sourceTree = "<group>"; }; + 475BFFFD1F7B953B006CDD41 /* NSMutableArray+PGPUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+PGPUtils.h"; sourceTree = "<group>"; }; + 475BFFFE1F7B953B006CDD41 /* NSMutableArray+PGPUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+PGPUtils.m"; sourceTree = "<group>"; }; + 475BFFFF1F7B953B006CDD41 /* NSMutableData+PGPUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableData+PGPUtils.h"; sourceTree = "<group>"; }; 475DF4771F0D54C9009D807F /* Folder+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Folder+CoreDataClass.swift"; sourceTree = "<group>"; }; 475DF4781F0D54C9009D807F /* Folder+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Folder+CoreDataProperties.swift"; sourceTree = "<group>"; }; 476142071E07E52B00FD5E4F /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; @@ -289,9 +402,7 @@ A10DE41F1EFAA2CE005E8189 /* FolderViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FolderViewController.swift; sourceTree = "<group>"; }; A1123E6B1DA682850069551C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; }; A1123E6D1DA682870069551C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; }; - A1182C561E30F45C0024D389 /* PGPKeyManagement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PGPKeyManagement.swift; sourceTree = "<group>"; }; A11E733B1E019AE3006574DD /* InitViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InitViewController.swift; sourceTree = "<group>"; }; - A1230BD61E2F8818006642C7 /* PGPEncryption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PGPEncryption.swift; sourceTree = "<group>"; }; A13526751D955BDF00D3BFE1 /* enzevalos_iphone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = enzevalos_iphone.app; sourceTree = BUILT_PRODUCTS_DIR; }; A13526781D955BDF00D3BFE1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; A13526801D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = enzevalos_iphone.xcdatamodel; sourceTree = "<group>"; }; @@ -302,91 +413,8 @@ A13526971D955BE000D3BFE1 /* enzevalos_iphoneUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = enzevalos_iphoneUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A135269B1D955BE000D3BFE1 /* enzevalos_iphoneUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = enzevalos_iphoneUITests.swift; sourceTree = "<group>"; }; A135269D1D955BE000D3BFE1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; - A135CEB81DD4BDD1007E3C29 /* NSData+compression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+compression.h"; sourceTree = "<group>"; }; - A135CEB91DD4BDD1007E3C29 /* NSData+compression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+compression.m"; sourceTree = "<group>"; }; - A135CEBA1DD4BDD1007E3C29 /* NSData+PGPUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+PGPUtils.h"; sourceTree = "<group>"; }; - A135CEBB1DD4BDD1007E3C29 /* NSData+PGPUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+PGPUtils.m"; sourceTree = "<group>"; }; - A135CEBC1DD4BDD1007E3C29 /* NSValue+PGPUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+PGPUtils.h"; sourceTree = "<group>"; }; - A135CEBD1DD4BDD1007E3C29 /* NSValue+PGPUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+PGPUtils.m"; sourceTree = "<group>"; }; - A135CEBE1DD4BDD1007E3C29 /* ObjectivePGP-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ObjectivePGP-Prefix.pch"; sourceTree = "<group>"; }; - A135CEBF1DD4BDD1007E3C29 /* ObjectivePGP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectivePGP.h; sourceTree = "<group>"; }; - A135CEC01DD4BDD1007E3C29 /* ObjectivePGP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjectivePGP.m; sourceTree = "<group>"; }; - A135CEC11DD4BDD1007E3C29 /* PGPArmor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPArmor.h; sourceTree = "<group>"; }; - A135CEC21DD4BDD1007E3C29 /* PGPArmor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPArmor.m; sourceTree = "<group>"; }; - A135CEC31DD4BDD1007E3C29 /* PGPCompressedPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPCompressedPacket.h; sourceTree = "<group>"; }; - A135CEC41DD4BDD1007E3C29 /* PGPCompressedPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPCompressedPacket.m; sourceTree = "<group>"; }; - A135CEC51DD4BDD1007E3C29 /* PGPCryptoCFB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPCryptoCFB.h; sourceTree = "<group>"; }; - A135CEC61DD4BDD1007E3C29 /* PGPCryptoCFB.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPCryptoCFB.m; sourceTree = "<group>"; }; - A135CEC71DD4BDD1007E3C29 /* PGPCryptoUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPCryptoUtils.h; sourceTree = "<group>"; }; - A135CEC81DD4BDD1007E3C29 /* PGPCryptoUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPCryptoUtils.m; sourceTree = "<group>"; }; - A135CEC91DD4BDD1007E3C29 /* PGPFingerprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPFingerprint.h; sourceTree = "<group>"; }; - A135CECA1DD4BDD1007E3C29 /* PGPFingerprint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPFingerprint.m; sourceTree = "<group>"; }; - A135CECB1DD4BDD1007E3C29 /* PGPKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPKey.h; sourceTree = "<group>"; }; - A135CECC1DD4BDD1007E3C29 /* PGPKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPKey.m; sourceTree = "<group>"; }; - A135CECD1DD4BDD1007E3C29 /* PGPKeyID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPKeyID.h; sourceTree = "<group>"; }; - A135CECE1DD4BDD1007E3C29 /* PGPKeyID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPKeyID.m; sourceTree = "<group>"; }; - A135CECF1DD4BDD1007E3C29 /* PGPLiteralPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPLiteralPacket.h; sourceTree = "<group>"; }; - A135CED01DD4BDD1007E3C29 /* PGPLiteralPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPLiteralPacket.m; sourceTree = "<group>"; }; - A135CED11DD4BDD1007E3C29 /* PGPModificationDetectionCodePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPModificationDetectionCodePacket.h; sourceTree = "<group>"; }; - A135CED21DD4BDD1007E3C29 /* PGPModificationDetectionCodePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPModificationDetectionCodePacket.m; sourceTree = "<group>"; }; - A135CED31DD4BDD1007E3C29 /* PGPMPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPMPI.h; sourceTree = "<group>"; }; - A135CED41DD4BDD1007E3C29 /* PGPMPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPMPI.m; sourceTree = "<group>"; }; - A135CED51DD4BDD1007E3C29 /* PGPOnePassSignaturePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPOnePassSignaturePacket.h; sourceTree = "<group>"; }; - A135CED61DD4BDD1007E3C29 /* PGPOnePassSignaturePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPOnePassSignaturePacket.m; sourceTree = "<group>"; }; - A135CED71DD4BDD1007E3C29 /* PGPPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPacket.h; sourceTree = "<group>"; }; - A135CED81DD4BDD1007E3C29 /* PGPPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPacket.m; sourceTree = "<group>"; }; - A135CED91DD4BDD1007E3C29 /* PGPPacketFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPacketFactory.h; sourceTree = "<group>"; }; - A135CEDA1DD4BDD1007E3C29 /* PGPPacketFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPacketFactory.m; sourceTree = "<group>"; }; - A135CEDB1DD4BDD1007E3C29 /* PGPPKCSEme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPKCSEme.h; sourceTree = "<group>"; }; - A135CEDC1DD4BDD1007E3C29 /* PGPPKCSEme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPKCSEme.m; sourceTree = "<group>"; }; - A135CEDD1DD4BDD1007E3C29 /* PGPPKCSEmsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPKCSEmsa.h; sourceTree = "<group>"; }; - A135CEDE1DD4BDD1007E3C29 /* PGPPKCSEmsa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPKCSEmsa.m; sourceTree = "<group>"; }; - A135CEDF1DD4BDD1007E3C29 /* PGPPublicKeyEncryptedSessionKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPublicKeyEncryptedSessionKeyPacket.h; sourceTree = "<group>"; }; - A135CEE01DD4BDD1007E3C29 /* PGPPublicKeyEncryptedSessionKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPublicKeyEncryptedSessionKeyPacket.m; sourceTree = "<group>"; }; - A135CEE11DD4BDD1007E3C29 /* PGPPublicKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPublicKeyPacket.h; sourceTree = "<group>"; }; - A135CEE21DD4BDD1007E3C29 /* PGPPublicKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPublicKeyPacket.m; sourceTree = "<group>"; }; - A135CEE31DD4BDD1007E3C29 /* PGPPublicKeyRSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPublicKeyRSA.h; sourceTree = "<group>"; }; - A135CEE41DD4BDD1007E3C29 /* PGPPublicKeyRSA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPublicKeyRSA.m; sourceTree = "<group>"; }; - A135CEE51DD4BDD1007E3C29 /* PGPPublicSubKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPPublicSubKeyPacket.h; sourceTree = "<group>"; }; - A135CEE61DD4BDD1007E3C29 /* PGPPublicSubKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPPublicSubKeyPacket.m; sourceTree = "<group>"; }; - A135CEE71DD4BDD1007E3C29 /* PGPS2K.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPS2K.h; sourceTree = "<group>"; }; - A135CEE81DD4BDD1007E3C29 /* PGPS2K.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPS2K.m; sourceTree = "<group>"; }; - A135CEE91DD4BDD1007E3C29 /* PGPSecretKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSecretKeyPacket.h; sourceTree = "<group>"; }; - A135CEEA1DD4BDD1007E3C29 /* PGPSecretKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSecretKeyPacket.m; sourceTree = "<group>"; }; - A135CEEB1DD4BDD1007E3C29 /* PGPSecretSubKeyPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSecretSubKeyPacket.h; sourceTree = "<group>"; }; - A135CEEC1DD4BDD1007E3C29 /* PGPSecretSubKeyPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSecretSubKeyPacket.m; sourceTree = "<group>"; }; - A135CEED1DD4BDD1007E3C29 /* PGPSignaturePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSignaturePacket.h; sourceTree = "<group>"; }; - A135CEEE1DD4BDD1007E3C29 /* PGPSignaturePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSignaturePacket.m; sourceTree = "<group>"; }; - A135CEEF1DD4BDD1007E3C29 /* PGPSignatureSubpacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSignatureSubpacket.h; sourceTree = "<group>"; }; - A135CEF01DD4BDD1007E3C29 /* PGPSignatureSubpacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSignatureSubpacket.m; sourceTree = "<group>"; }; - A135CEF11DD4BDD1007E3C29 /* PGPSubKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSubKey.h; sourceTree = "<group>"; }; - A135CEF21DD4BDD1007E3C29 /* PGPSubKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSubKey.m; sourceTree = "<group>"; }; - A135CEF31DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedDataPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSymmetricallyEncryptedDataPacket.h; sourceTree = "<group>"; }; - A135CEF41DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedDataPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSymmetricallyEncryptedDataPacket.m; sourceTree = "<group>"; }; - A135CEF51DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h; sourceTree = "<group>"; }; - A135CEF61DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m; sourceTree = "<group>"; }; - A135CEF71DD4BDD1007E3C29 /* PGPTrustPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPTrustPacket.h; sourceTree = "<group>"; }; - A135CEF81DD4BDD1007E3C29 /* PGPTrustPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPTrustPacket.m; sourceTree = "<group>"; }; - A135CEF91DD4BDD1007E3C29 /* PGPTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPTypes.h; sourceTree = "<group>"; }; - A135CEFA1DD4BDD1007E3C29 /* PGPUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUser.h; sourceTree = "<group>"; }; - A135CEFB1DD4BDD1007E3C29 /* PGPUser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUser.m; sourceTree = "<group>"; }; - A135CEFC1DD4BDD1007E3C29 /* PGPUserAttributePacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUserAttributePacket.h; sourceTree = "<group>"; }; - A135CEFD1DD4BDD1007E3C29 /* PGPUserAttributePacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUserAttributePacket.m; sourceTree = "<group>"; }; - A135CEFE1DD4BDD1007E3C29 /* PGPUserAttributeSubpacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUserAttributeSubpacket.h; sourceTree = "<group>"; }; - A135CEFF1DD4BDD1007E3C29 /* PGPUserAttributeSubpacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUserAttributeSubpacket.m; sourceTree = "<group>"; }; - A135CF001DD4BDD1007E3C29 /* PGPUserIDPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPUserIDPacket.h; sourceTree = "<group>"; }; - A135CF011DD4BDD1007E3C29 /* PGPUserIDPacket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPUserIDPacket.m; sourceTree = "<group>"; }; - A1416C181E268EFB001809F3 /* EncryptionHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncryptionHandler.swift; sourceTree = "<group>"; }; - A1416C1A1E268F1A001809F3 /* Encryption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Encryption.swift; sourceTree = "<group>"; }; - A15B7BE31E29306D0024E499 /* EnzevalosEncryptionHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnzevalosEncryptionHandler.swift; sourceTree = "<group>"; }; - A15B7BE51E2931AD0024E499 /* KeyWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyWrapper.swift; sourceTree = "<group>"; }; - A15B7BE71E2934CB0024E499 /* EncryptionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncryptionType.swift; sourceTree = "<group>"; }; A16BA2111E0439B6005E29E3 /* providers.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; lineEnding = 0; path = providers.json; sourceTree = "<group>"; }; - A172F90C1E4CD37D00F2A136 /* PGPTemporaryDecryptionObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PGPTemporaryDecryptionObject.swift; sourceTree = "<group>"; }; - A17A18F61DDCBE530058D934 /* PGPKeyWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PGPKeyWrapper.swift; sourceTree = "<group>"; }; A17A18F81DDCCF370058D934 /* JakobBode.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = JakobBode.asc; path = keys/JakobBode.asc; sourceTree = "<group>"; }; - A17BEB371E55E21700403EBE /* PGPTemporaryDecryptionObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PGPTemporaryDecryptionObject.h; sourceTree = "<group>"; }; - A17BEB381E55E3DD00403EBE /* PGPTemporaryDecryptionObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPTemporaryDecryptionObject.m; sourceTree = "<group>"; }; A17C04831DC6504E00F66EDB /* LogHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogHandler.swift; sourceTree = "<group>"; }; A198270D1D9A8ABC0027F65C /* enzevalos_iphone-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "enzevalos_iphone-Bridging-Header.h"; sourceTree = "<group>"; }; A19C12461DE602FF007F72E7 /* jabo.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = jabo.asc; path = keys/jabo.asc; sourceTree = "<group>"; }; @@ -509,6 +537,145 @@ name = protocols; sourceTree = "<group>"; }; + 475BFF911F7B953B006CDD41 /* ObjectivePGP */ = { + isa = PBXGroup; + children = ( + 475BFF921F7B953B006CDD41 /* CryptoBox */, + 475BFF9D1F7B953B006CDD41 /* Info.plist */, + 475BFF9E1F7B953B006CDD41 /* ObjectivePGP-Prefix.pch */, + 475BFF9F1F7B953B006CDD41 /* ObjectivePGP.h */, + 475BFFA01F7B953B006CDD41 /* ObjectivePGPObject.h */, + 475BFFA11F7B953B006CDD41 /* ObjectivePGPObject.m */, + 475BFFA21F7B953B006CDD41 /* Packets */, + 475BFFD11F7B953B006CDD41 /* PGPArmor.h */, + 475BFFD21F7B953B006CDD41 /* PGPArmor.m */, + 475BFFD31F7B953B006CDD41 /* PGPBigNum+Private.h */, + 475BFFD41F7B953B006CDD41 /* PGPBigNum.h */, + 475BFFD51F7B953B006CDD41 /* PGPBigNum.m */, + 475BFFD61F7B953B006CDD41 /* PGPCryptoCFB.h */, + 475BFFD71F7B953B006CDD41 /* PGPCryptoCFB.m */, + 475BFFD81F7B953B006CDD41 /* PGPExportableProtocol.h */, + 475BFFD91F7B953B006CDD41 /* PGPFingerprint.h */, + 475BFFDA1F7B953B006CDD41 /* PGPFingerprint.m */, + 475BFFDB1F7B953B006CDD41 /* PGPFoundation.h */, + 475BFFDC1F7B953B006CDD41 /* PGPFoundation.m */, + 475BFFDD1F7B953B006CDD41 /* PGPKey+Private.h */, + 475BFFDE1F7B953B006CDD41 /* PGPKey.h */, + 475BFFDF1F7B953B006CDD41 /* PGPKey.m */, + 475BFFE01F7B953B006CDD41 /* PGPKeyGenerator.h */, + 475BFFE11F7B953B006CDD41 /* PGPKeyGenerator.m */, + 475BFFE21F7B953B006CDD41 /* PGPKeyID.h */, + 475BFFE31F7B953B006CDD41 /* PGPKeyID.m */, + 475BFFE41F7B953B006CDD41 /* PGPLogging.h */, + 475BFFE51F7B953B006CDD41 /* PGPMacros+Private.h */, + 475BFFE61F7B953B006CDD41 /* PGPMacros.h */, + 475BFFE71F7B953B006CDD41 /* PGPMPI.h */, + 475BFFE81F7B953B006CDD41 /* PGPMPI.m */, + 475BFFE91F7B953B006CDD41 /* PGPPacketFactory.h */, + 475BFFEA1F7B953B006CDD41 /* PGPPacketFactory.m */, + 475BFFEB1F7B953B006CDD41 /* PGPPartialKey.h */, + 475BFFEC1F7B953B006CDD41 /* PGPPartialKey.m */, + 475BFFED1F7B953B006CDD41 /* PGPPartialSubKey.h */, + 475BFFEE1F7B953B006CDD41 /* PGPPartialSubKey.m */, + 475BFFEF1F7B953B006CDD41 /* PGPPKCSEme.h */, + 475BFFF01F7B953B006CDD41 /* PGPPKCSEme.m */, + 475BFFF11F7B953B006CDD41 /* PGPPKCSEmsa.h */, + 475BFFF21F7B953B006CDD41 /* PGPPKCSEmsa.m */, + 475BFFF31F7B953B006CDD41 /* PGPS2K.h */, + 475BFFF41F7B953B006CDD41 /* PGPS2K.m */, + 475BFFF51F7B953B006CDD41 /* PGPTypes.h */, + 475BFFF61F7B953B006CDD41 /* PGPUser.h */, + 475BFFF71F7B953B006CDD41 /* PGPUser.m */, + 475BFFF81F7B953B006CDD41 /* Utils */, + ); + path = ObjectivePGP; + sourceTree = "<group>"; + }; + 475BFF921F7B953B006CDD41 /* CryptoBox */ = { + isa = PBXGroup; + children = ( + 475BFF931F7B953B006CDD41 /* PGPCryptoHash.h */, + 475BFF941F7B953B006CDD41 /* PGPCryptoHash.m */, + 475BFF951F7B953B006CDD41 /* PGPCryptoUtils.h */, + 475BFF961F7B953B006CDD41 /* PGPCryptoUtils.m */, + 475BFF971F7B953B006CDD41 /* PGPDSA.h */, + 475BFF981F7B953B006CDD41 /* PGPDSA.m */, + 475BFF991F7B953B006CDD41 /* PGPKeyMaterial.h */, + 475BFF9A1F7B953B006CDD41 /* PGPKeyMaterial.m */, + 475BFF9B1F7B953B006CDD41 /* PGPRSA.h */, + 475BFF9C1F7B953B006CDD41 /* PGPRSA.m */, + ); + path = CryptoBox; + sourceTree = "<group>"; + }; + 475BFFA21F7B953B006CDD41 /* Packets */ = { + isa = PBXGroup; + children = ( + 475BFFA31F7B953B006CDD41 /* PGPCompressedPacket.h */, + 475BFFA41F7B953B006CDD41 /* PGPCompressedPacket.m */, + 475BFFA51F7B953B006CDD41 /* PGPLiteralPacket.h */, + 475BFFA61F7B953B006CDD41 /* PGPLiteralPacket.m */, + 475BFFA71F7B953B006CDD41 /* PGPModificationDetectionCodePacket.h */, + 475BFFA81F7B953B006CDD41 /* PGPModificationDetectionCodePacket.m */, + 475BFFA91F7B953B006CDD41 /* PGPOnePassSignaturePacket.h */, + 475BFFAA1F7B953B006CDD41 /* PGPOnePassSignaturePacket.m */, + 475BFFAB1F7B953B006CDD41 /* PGPPacket+Private.h */, + 475BFFAC1F7B953B006CDD41 /* PGPPacket.h */, + 475BFFAD1F7B953B006CDD41 /* PGPPacket.m */, + 475BFFAE1F7B953B006CDD41 /* PGPPacketProtocol.h */, + 475BFFAF1F7B953B006CDD41 /* PGPPublicKeyEncryptedSessionKeyPacket.h */, + 475BFFB01F7B953B006CDD41 /* PGPPublicKeyEncryptedSessionKeyPacket.m */, + 475BFFB11F7B953B006CDD41 /* PGPPublicKeyPacket+Private.h */, + 475BFFB21F7B953B006CDD41 /* PGPPublicKeyPacket.h */, + 475BFFB31F7B953B006CDD41 /* PGPPublicKeyPacket.m */, + 475BFFB41F7B953B006CDD41 /* PGPPublicSubKeyPacket.h */, + 475BFFB51F7B953B006CDD41 /* PGPPublicSubKeyPacket.m */, + 475BFFB61F7B953B006CDD41 /* PGPSecretKeyPacket+Private.h */, + 475BFFB71F7B953B006CDD41 /* PGPSecretKeyPacket.h */, + 475BFFB81F7B953B006CDD41 /* PGPSecretKeyPacket.m */, + 475BFFB91F7B953B006CDD41 /* PGPSecretSubKeyPacket.h */, + 475BFFBA1F7B953B006CDD41 /* PGPSecretSubKeyPacket.m */, + 475BFFBB1F7B953B006CDD41 /* PGPSignaturePacket+Private.h */, + 475BFFBC1F7B953B006CDD41 /* PGPSignaturePacket.h */, + 475BFFBD1F7B953B006CDD41 /* PGPSignaturePacket.m */, + 475BFFBE1F7B953B006CDD41 /* PGPSignatureSubpacket+Private.h */, + 475BFFBF1F7B953B006CDD41 /* PGPSignatureSubpacket.h */, + 475BFFC01F7B953B006CDD41 /* PGPSignatureSubpacket.m */, + 475BFFC11F7B953B006CDD41 /* PGPSignatureSubpacketCreationTime.h */, + 475BFFC21F7B953B006CDD41 /* PGPSignatureSubpacketCreationTime.m */, + 475BFFC31F7B953B006CDD41 /* PGPSignatureSubpacketHeader.h */, + 475BFFC41F7B953B006CDD41 /* PGPSignatureSubpacketHeader.m */, + 475BFFC51F7B953B006CDD41 /* PGPSymmetricallyEncryptedDataPacket.h */, + 475BFFC61F7B953B006CDD41 /* PGPSymmetricallyEncryptedDataPacket.m */, + 475BFFC71F7B953B006CDD41 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h */, + 475BFFC81F7B953B006CDD41 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m */, + 475BFFC91F7B953B006CDD41 /* PGPTrustPacket.h */, + 475BFFCA1F7B953B006CDD41 /* PGPTrustPacket.m */, + 475BFFCB1F7B953B006CDD41 /* PGPUserAttributePacket.h */, + 475BFFCC1F7B953B006CDD41 /* PGPUserAttributePacket.m */, + 475BFFCD1F7B953B006CDD41 /* PGPUserAttributeSubpacket.h */, + 475BFFCE1F7B953B006CDD41 /* PGPUserAttributeSubpacket.m */, + 475BFFCF1F7B953B006CDD41 /* PGPUserIDPacket.h */, + 475BFFD01F7B953B006CDD41 /* PGPUserIDPacket.m */, + ); + path = Packets; + sourceTree = "<group>"; + }; + 475BFFF81F7B953B006CDD41 /* Utils */ = { + isa = PBXGroup; + children = ( + 475BFFF91F7B953B006CDD41 /* NSData+compression.h */, + 475BFFFA1F7B953B006CDD41 /* NSData+compression.m */, + 475BFFFB1F7B953B006CDD41 /* NSData+PGPUtils.h */, + 475BFFFC1F7B953B006CDD41 /* NSData+PGPUtils.m */, + 475BFFFD1F7B953B006CDD41 /* NSMutableArray+PGPUtils.h */, + 475BFFFE1F7B953B006CDD41 /* NSMutableArray+PGPUtils.m */, + 475BFFFF1F7B953B006CDD41 /* NSMutableData+PGPUtils.h */, + 475B00001F7B953B006CDD41 /* NSMutableData+PGPUtils.m */, + ); + path = Utils; + sourceTree = "<group>"; + }; 478175061F06E57E00300D20 /* netpgp */ = { isa = PBXGroup; children = ( @@ -646,18 +813,9 @@ A1230BD81E2F881E006642C7 /* Encryption */ = { isa = PBXGroup; children = ( - A15B7BE71E2934CB0024E499 /* EncryptionType.swift */, - A1416C181E268EFB001809F3 /* EncryptionHandler.swift */, - A15B7BE31E29306D0024E499 /* EnzevalosEncryptionHandler.swift */, - A1182C561E30F45C0024D389 /* PGPKeyManagement.swift */, - A1416C1A1E268F1A001809F3 /* Encryption.swift */, - A1230BD61E2F8818006642C7 /* PGPEncryption.swift */, - A17A18F61DDCBE530058D934 /* PGPKeyWrapper.swift */, - A15B7BE51E2931AD0024E499 /* KeyWrapper.swift */, - A172F90C1E4CD37D00F2A136 /* PGPTemporaryDecryptionObject.swift */, - A17BEB371E55E21700403EBE /* PGPTemporaryDecryptionObject.h */, - A17BEB381E55E3DD00403EBE /* PGPTemporaryDecryptionObject.m */, - 4715B0F41EF3D58100520DE5 /* DecryptedData.swift */, + 475B00301F7B9565006CDD41 /* SwiftPGP.swift */, + 475B00311F7B9565006CDD41 /* Cryptography.swift */, + 475B00321F7B9565006CDD41 /* CryptoObject.swift */, ); name = Encryption; sourceTree = "<group>"; @@ -687,10 +845,10 @@ A13526771D955BDF00D3BFE1 /* enzevalos_iphone */ = { isa = PBXGroup; children = ( + 475BFF911F7B953B006CDD41 /* ObjectivePGP */, 478175061F06E57E00300D20 /* netpgp */, 47B91AC11EC0C1FB000AE3EE /* data */, F19B29011E02DCAC00B29DD1 /* enzevalos_iphone.entitlements */, - A135CEB61DD4BDA2007E3C29 /* ObjectivePGP */, A1C7FF8B1E895316000D1E92 /* keys */, A11E733A1E019AB5006574DD /* init */, A10DE41E1EFAA140005E8189 /* folders */, @@ -740,88 +898,6 @@ path = enzevalos_iphoneUITests; sourceTree = "<group>"; }; - A135CEB61DD4BDA2007E3C29 /* ObjectivePGP */ = { - isa = PBXGroup; - children = ( - A135CEB81DD4BDD1007E3C29 /* NSData+compression.h */, - A135CEB91DD4BDD1007E3C29 /* NSData+compression.m */, - A135CEBA1DD4BDD1007E3C29 /* NSData+PGPUtils.h */, - A135CEBB1DD4BDD1007E3C29 /* NSData+PGPUtils.m */, - A135CEBC1DD4BDD1007E3C29 /* NSValue+PGPUtils.h */, - A135CEBD1DD4BDD1007E3C29 /* NSValue+PGPUtils.m */, - A135CEBE1DD4BDD1007E3C29 /* ObjectivePGP-Prefix.pch */, - A135CEBF1DD4BDD1007E3C29 /* ObjectivePGP.h */, - A135CEC01DD4BDD1007E3C29 /* ObjectivePGP.m */, - A135CEC11DD4BDD1007E3C29 /* PGPArmor.h */, - A135CEC21DD4BDD1007E3C29 /* PGPArmor.m */, - A135CEC31DD4BDD1007E3C29 /* PGPCompressedPacket.h */, - A135CEC41DD4BDD1007E3C29 /* PGPCompressedPacket.m */, - A135CEC51DD4BDD1007E3C29 /* PGPCryptoCFB.h */, - A135CEC61DD4BDD1007E3C29 /* PGPCryptoCFB.m */, - A135CEC71DD4BDD1007E3C29 /* PGPCryptoUtils.h */, - A135CEC81DD4BDD1007E3C29 /* PGPCryptoUtils.m */, - A135CEC91DD4BDD1007E3C29 /* PGPFingerprint.h */, - A135CECA1DD4BDD1007E3C29 /* PGPFingerprint.m */, - A135CECB1DD4BDD1007E3C29 /* PGPKey.h */, - A135CECC1DD4BDD1007E3C29 /* PGPKey.m */, - A135CECD1DD4BDD1007E3C29 /* PGPKeyID.h */, - A135CECE1DD4BDD1007E3C29 /* PGPKeyID.m */, - A135CECF1DD4BDD1007E3C29 /* PGPLiteralPacket.h */, - A135CED01DD4BDD1007E3C29 /* PGPLiteralPacket.m */, - A135CED11DD4BDD1007E3C29 /* PGPModificationDetectionCodePacket.h */, - A135CED21DD4BDD1007E3C29 /* PGPModificationDetectionCodePacket.m */, - A135CED31DD4BDD1007E3C29 /* PGPMPI.h */, - A135CED41DD4BDD1007E3C29 /* PGPMPI.m */, - A135CED51DD4BDD1007E3C29 /* PGPOnePassSignaturePacket.h */, - A135CED61DD4BDD1007E3C29 /* PGPOnePassSignaturePacket.m */, - A135CED71DD4BDD1007E3C29 /* PGPPacket.h */, - A135CED81DD4BDD1007E3C29 /* PGPPacket.m */, - A135CED91DD4BDD1007E3C29 /* PGPPacketFactory.h */, - A135CEDA1DD4BDD1007E3C29 /* PGPPacketFactory.m */, - A135CEDB1DD4BDD1007E3C29 /* PGPPKCSEme.h */, - A135CEDC1DD4BDD1007E3C29 /* PGPPKCSEme.m */, - A135CEDD1DD4BDD1007E3C29 /* PGPPKCSEmsa.h */, - A135CEDE1DD4BDD1007E3C29 /* PGPPKCSEmsa.m */, - A135CEDF1DD4BDD1007E3C29 /* PGPPublicKeyEncryptedSessionKeyPacket.h */, - A135CEE01DD4BDD1007E3C29 /* PGPPublicKeyEncryptedSessionKeyPacket.m */, - A135CEE11DD4BDD1007E3C29 /* PGPPublicKeyPacket.h */, - A135CEE21DD4BDD1007E3C29 /* PGPPublicKeyPacket.m */, - A135CEE31DD4BDD1007E3C29 /* PGPPublicKeyRSA.h */, - A135CEE41DD4BDD1007E3C29 /* PGPPublicKeyRSA.m */, - A135CEE51DD4BDD1007E3C29 /* PGPPublicSubKeyPacket.h */, - A135CEE61DD4BDD1007E3C29 /* PGPPublicSubKeyPacket.m */, - A135CEE71DD4BDD1007E3C29 /* PGPS2K.h */, - A135CEE81DD4BDD1007E3C29 /* PGPS2K.m */, - A135CEE91DD4BDD1007E3C29 /* PGPSecretKeyPacket.h */, - A135CEEA1DD4BDD1007E3C29 /* PGPSecretKeyPacket.m */, - A135CEEB1DD4BDD1007E3C29 /* PGPSecretSubKeyPacket.h */, - A135CEEC1DD4BDD1007E3C29 /* PGPSecretSubKeyPacket.m */, - A135CEED1DD4BDD1007E3C29 /* PGPSignaturePacket.h */, - A135CEEE1DD4BDD1007E3C29 /* PGPSignaturePacket.m */, - A135CEEF1DD4BDD1007E3C29 /* PGPSignatureSubpacket.h */, - A135CEF01DD4BDD1007E3C29 /* PGPSignatureSubpacket.m */, - A135CEF11DD4BDD1007E3C29 /* PGPSubKey.h */, - A135CEF21DD4BDD1007E3C29 /* PGPSubKey.m */, - A135CEF31DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedDataPacket.h */, - A135CEF41DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedDataPacket.m */, - A135CEF51DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h */, - A135CEF61DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m */, - A135CEF71DD4BDD1007E3C29 /* PGPTrustPacket.h */, - A135CEF81DD4BDD1007E3C29 /* PGPTrustPacket.m */, - A135CEF91DD4BDD1007E3C29 /* PGPTypes.h */, - A135CEFA1DD4BDD1007E3C29 /* PGPUser.h */, - A135CEFB1DD4BDD1007E3C29 /* PGPUser.m */, - A135CEFC1DD4BDD1007E3C29 /* PGPUserAttributePacket.h */, - A135CEFD1DD4BDD1007E3C29 /* PGPUserAttributePacket.m */, - A135CEFE1DD4BDD1007E3C29 /* PGPUserAttributeSubpacket.h */, - A135CEFF1DD4BDD1007E3C29 /* PGPUserAttributeSubpacket.m */, - A135CF001DD4BDD1007E3C29 /* PGPUserIDPacket.h */, - A135CF011DD4BDD1007E3C29 /* PGPUserIDPacket.m */, - ); - name = ObjectivePGP; - path = ..; - sourceTree = "<group>"; - }; A18C76851E8185ED00B21414 /* onboarding */ = { isa = PBXGroup; children = ( @@ -1061,6 +1137,7 @@ 4761420A1E082F9C00FD5E4F /* Settings.bundle in Resources */, A19C12471DE602FF007F72E7 /* jabo.asc in Resources */, 479BBDDB1EFEA17900A2107C /* alice_enzevalos_public.asc in Resources */, + 475B00061F7B953B006CDD41 /* Info.plist in Resources */, A16BA2121E0439B6005E29E3 /* providers.json in Resources */, F189C17F1ED59FEF00BAE9B3 /* idsolutions-private.gpg in Resources */, F14D189D1ED880680080515D /* nchr-public.gpg in Resources */, @@ -1247,138 +1324,140 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 475B000B1F7B953B006CDD41 /* PGPOnePassSignaturePacket.m in Sources */, 47691A8A1ECB56D1004BCFC5 /* Mail.swift in Sources */, 472F398A1E251787009260FB /* Contact.swift in Sources */, 4781754B1F06E57E00300D20 /* signature.c in Sources */, 472F39861E1FA34E009260FB /* Record.swift in Sources */, + 475B00221F7B953B006CDD41 /* PGPKeyGenerator.m in Sources */, + 475B001C1F7B953B006CDD41 /* PGPArmor.m in Sources */, + 475B00191F7B953B006CDD41 /* PGPUserAttributePacket.m in Sources */, A1C3270E1DB907D900CE2ED5 /* TextFormatter.swift in Sources */, - A17BEB391E55E3DD00403EBE /* PGPTemporaryDecryptionObject.m in Sources */, A1F2A5691E85586300320275 /* Providers.swift in Sources */, F12041FD1DA409A5002E4940 /* ListViewCell.swift in Sources */, + 475B00151F7B953B006CDD41 /* PGPSignatureSubpacketHeader.m in Sources */, + 475B000E1F7B953B006CDD41 /* PGPPublicKeyPacket.m in Sources */, A1E2324E1F0FA41A00DC9D40 /* FolderListCell.swift in Sources */, A1EB059C1D956957008659C1 /* NSDateCompare.swift in Sources */, - A15B7BE61E2931AD0024E499 /* KeyWrapper.swift in Sources */, 478175471F06E57E00300D20 /* packet-parse.c in Sources */, + 475B00041F7B953B006CDD41 /* PGPKeyMaterial.m in Sources */, A1EB05941D956931008659C1 /* InboxCellDelegator.swift in Sources */, - A135CF121DD4BDD1007E3C29 /* PGPPacketFactory.m in Sources */, - A135CF111DD4BDD1007E3C29 /* PGPPacket.m in Sources */, - 4715B0F51EF3D58100520DE5 /* DecryptedData.swift in Sources */, 472F39811E1E5347009260FB /* Mail_Address+CoreDataClass.swift in Sources */, + 475B002F1F7B953B006CDD41 /* NSMutableData+PGPUtils.m in Sources */, + 475B00021F7B953B006CDD41 /* PGPCryptoUtils.m in Sources */, 4781753C1F06E57E00300D20 /* bufgap.c in Sources */, 478175431F06E57E00300D20 /* misc.c in Sources */, A1EB05821D95685B008659C1 /* CollectionDataDelegate.swift in Sources */, A17C04841DC6504E00F66EDB /* LogHandler.swift in Sources */, A1EB05801D956851008659C1 /* SendViewController.swift in Sources */, + 475B001B1F7B953B006CDD41 /* PGPUserIDPacket.m in Sources */, 47691A8C1ECC3EC7004BCFC5 /* EphemeralMail.swift in Sources */, - A135CF231DD4BDD1007E3C29 /* PGPUserAttributePacket.m in Sources */, - A1230BD71E2F8818006642C7 /* PGPEncryption.swift in Sources */, A1EB05981D956947008659C1 /* InboxViewController.swift in Sources */, F1984D721E1D327200804E1E /* IconsStyleKit.swift in Sources */, - A135CF221DD4BDD1007E3C29 /* PGPUser.m in Sources */, - A135CF031DD4BDD1007E3C29 /* NSData+PGPUtils.m in Sources */, 472F398C1E2519C8009260FB /* CNContactExtension.swift in Sources */, F113C3851F30D06800E7F1D6 /* QRScannerView.swift in Sources */, - A135CF171DD4BDD1007E3C29 /* PGPPublicKeyRSA.m in Sources */, F18B44601E704C550080C041 /* ReplaceSegue.swift in Sources */, - A135CF181DD4BDD1007E3C29 /* PGPPublicSubKeyPacket.m in Sources */, + 475B000C1F7B953B006CDD41 /* PGPPacket.m in Sources */, 472F39881E1FA377009260FB /* KeyRecord.swift in Sources */, - A135CF141DD4BDD1007E3C29 /* PGPPKCSEmsa.m in Sources */, 4781754E1F06E57E00300D20 /* validate.c in Sources */, - A135CF051DD4BDD1007E3C29 /* ObjectivePGP.m in Sources */, 4781754C1F06E57E00300D20 /* ssh2pgp.c in Sources */, + 475B00241F7B953B006CDD41 /* PGPMPI.m in Sources */, F1ACF21C1E0C1C6800C1B843 /* ContactViewController.swift in Sources */, + 475B00351F7B9565006CDD41 /* CryptoObject.swift in Sources */, 4781754F1F06E57E00300D20 /* writer.c in Sources */, 478175441F06E57E00300D20 /* mj.c in Sources */, + 475B00161F7B953B006CDD41 /* PGPSymmetricallyEncryptedDataPacket.m in Sources */, 478175491F06E57E00300D20 /* packet-show.c in Sources */, + 475B002B1F7B953B006CDD41 /* PGPUser.m in Sources */, A1EB057E1D956848008659C1 /* VENDataDelegate.swift in Sources */, 4781753D1F06E57E00300D20 /* compress.c in Sources */, A1E81B671DCA296200535F98 /* UIViewResolver.swift in Sources */, - A135CF0F1DD4BDD1007E3C29 /* PGPMPI.m in Sources */, + 475B001A1F7B953B006CDD41 /* PGPUserAttributeSubpacket.m in Sources */, + 475B000A1F7B953B006CDD41 /* PGPModificationDetectionCodePacket.m in Sources */, + 475B00331F7B9565006CDD41 /* SwiftPGP.swift in Sources */, + 475B00171F7B953B006CDD41 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m in Sources */, + 475B002C1F7B953B006CDD41 /* NSData+compression.m in Sources */, F14239C11F30A99C00998A83 /* QRCodeGenerator.swift in Sources */, 472F392A1E1277D2009260FB /* EnzevalosContact+CoreDataClass.swift in Sources */, F1AF938F1E2D04BA00755128 /* CustomCells.swift in Sources */, - A135CF191DD4BDD1007E3C29 /* PGPS2K.m in Sources */, - A135CF061DD4BDD1007E3C29 /* PGPArmor.m in Sources */, + 475B00211F7B953B006CDD41 /* PGPKey.m in Sources */, A10DE4201EFAA2CE005E8189 /* FolderViewController.swift in Sources */, - A135CF251DD4BDD1007E3C29 /* PGPUserIDPacket.m in Sources */, 4781753B1F06E57E00300D20 /* README.md in Sources */, + 475B00071F7B953B006CDD41 /* ObjectivePGPObject.m in Sources */, + 475B00131F7B953B006CDD41 /* PGPSignatureSubpacket.m in Sources */, + 475B00011F7B953B006CDD41 /* PGPCryptoHash.m in Sources */, 4781754D1F06E57E00300D20 /* symmetric.c in Sources */, 478175461F06E57E00300D20 /* openssl_crypto.c in Sources */, - A135CF0C1DD4BDD1007E3C29 /* PGPKeyID.m in Sources */, 478175501F06E57E00300D20 /* UNNetPGP.m in Sources */, - A135CF021DD4BDD1007E3C29 /* NSData+compression.m in Sources */, + 475B002E1F7B953B006CDD41 /* NSMutableArray+PGPUtils.m in Sources */, 476142081E07E52B00FD5E4F /* Theme.swift in Sources */, A1EB057A1D956829008659C1 /* ContactCell.swift in Sources */, 475DF47A1F0D54C9009D807F /* Folder+CoreDataProperties.swift in Sources */, - A135CF1E1DD4BDD1007E3C29 /* PGPSubKey.m in Sources */, + 475B00101F7B953B006CDD41 /* PGPSecretKeyPacket.m in Sources */, 472F392C1E1277D2009260FB /* PersistentMail +CoreDataClass.swift in Sources */, - A135CF0D1DD4BDD1007E3C29 /* PGPLiteralPacket.m in Sources */, - A135CF1D1DD4BDD1007E3C29 /* PGPSignatureSubpacket.m in Sources */, F119D2901E364B59001D732A /* AnimatedSendIcon.swift in Sources */, - A135CF041DD4BDD1007E3C29 /* NSValue+PGPUtils.m in Sources */, 478175481F06E57E00300D20 /* packet-print.c in Sources */, + 475B00231F7B953B006CDD41 /* PGPKeyID.m in Sources */, + 475B00181F7B953B006CDD41 /* PGPTrustPacket.m in Sources */, F12060801DA540FE00F6EF37 /* RefreshControlExtension.swift in Sources */, - A135CF0A1DD4BDD1007E3C29 /* PGPFingerprint.m in Sources */, + 475B001F1F7B953B006CDD41 /* PGPFingerprint.m in Sources */, + 475B001E1F7B953B006CDD41 /* PGPCryptoCFB.m in Sources */, A13526811D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld in Sources */, + 475B00111F7B953B006CDD41 /* PGPSecretSubKeyPacket.m in Sources */, 478175411F06E57E00300D20 /* keyring.c in Sources */, - A1416C191E268EFB001809F3 /* EncryptionHandler.swift in Sources */, - A135CF1C1DD4BDD1007E3C29 /* PGPSignaturePacket.m in Sources */, - A135CF1F1DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedDataPacket.m in Sources */, - A135CF211DD4BDD1007E3C29 /* PGPTrustPacket.m in Sources */, + 475B00141F7B953B006CDD41 /* PGPSignatureSubpacketCreationTime.m in Sources */, 472F39821E1E5347009260FB /* Mail_Address+CoreDataProperties.swift in Sources */, 476373C21E09BA88004D5EFE /* UserData.swift in Sources */, + 475B00081F7B953B006CDD41 /* PGPCompressedPacket.m in Sources */, A1EB05A01D95696C008659C1 /* MessageBodyTableViewCell.swift in Sources */, + 475B00271F7B953B006CDD41 /* PGPPartialSubKey.m in Sources */, F18B44621E73286C0080C041 /* ReadVENDelegate.swift in Sources */, - A17A18F71DDCBE530058D934 /* PGPKeyWrapper.swift in Sources */, + 475B000F1F7B953B006CDD41 /* PGPPublicSubKeyPacket.m in Sources */, + 475B00051F7B953B006CDD41 /* PGPRSA.m in Sources */, A1D5076F1E80257A00B68B38 /* KeyViewController.swift in Sources */, 472F39901E252470009260FB /* CNMailAddressesExtension.swift in Sources */, 472F39731E1D09C4009260FB /* State+CoreDataClass.swift in Sources */, + 475B00261F7B953B006CDD41 /* PGPPartialKey.m in Sources */, + 475B00251F7B953B006CDD41 /* PGPPacketFactory.m in Sources */, + 475B002A1F7B953B006CDD41 /* PGPS2K.m in Sources */, 478175451F06E57E00300D20 /* netpgp.c in Sources */, A1E2324C1F0FA13F00DC9D40 /* FolderListViewController.swift in Sources */, - A135CF081DD4BDD1007E3C29 /* PGPCryptoCFB.m in Sources */, - A1416C1B1E268F1A001809F3 /* Encryption.swift in Sources */, + 475B00121F7B953B006CDD41 /* PGPSignaturePacket.m in Sources */, + 475B00091F7B953B006CDD41 /* PGPLiteralPacket.m in Sources */, F113C38B1F3344C200E7F1D6 /* ViewControllerPannable.swift in Sources */, A1EB05841D956867008659C1 /* TableViewDataDelegate.swift in Sources */, 4781753E1F06E57E00300D20 /* create.c in Sources */, - A15B7BE41E29306D0024E499 /* EnzevalosEncryptionHandler.swift in Sources */, 472F397C1E1D0B0B009260FB /* PersistentMail +CoreDataProperties.swift in Sources */, A1EB05961D956939008659C1 /* InboxTableViewCell.swift in Sources */, 478175401F06E57E00300D20 /* fastctype.c in Sources */, - A135CF131DD4BDD1007E3C29 /* PGPPKCSEme.m in Sources */, - A135CF241DD4BDD1007E3C29 /* PGPUserAttributeSubpacket.m in Sources */, - A135CF151DD4BDD1007E3C29 /* PGPPublicKeyEncryptedSessionKeyPacket.m in Sources */, + 475B00201F7B953B006CDD41 /* PGPFoundation.m in Sources */, + 475B002D1F7B953B006CDD41 /* NSData+PGPUtils.m in Sources */, + 475B000D1F7B953B006CDD41 /* PGPPublicKeyEncryptedSessionKeyPacket.m in Sources */, A1083A541E8BFEA6003666B7 /* Onboarding.swift in Sources */, 472F39741E1D09C4009260FB /* State+CoreDataProperties.swift in Sources */, A13526791D955BDF00D3BFE1 /* AppDelegate.swift in Sources */, A1ECE54B1EFBE7ED0009349F /* FolderCell.swift in Sources */, - A135CF0E1DD4BDD1007E3C29 /* PGPModificationDetectionCodePacket.m in Sources */, 475DF4791F0D54C9009D807F /* Folder+CoreDataClass.swift in Sources */, + 475B00281F7B953B006CDD41 /* PGPPKCSEme.m in Sources */, + 475B00341F7B9565006CDD41 /* Cryptography.swift in Sources */, A1EB057C1D956838008659C1 /* MailHandler.swift in Sources */, - A135CF161DD4BDD1007E3C29 /* PGPPublicKeyPacket.m in Sources */, - A135CF0B1DD4BDD1007E3C29 /* PGPKey.m in Sources */, - A1182C571E30F45C0024D389 /* PGPKeyManagement.swift in Sources */, A1EB05881D956879008659C1 /* AddressHandler.swift in Sources */, 4781753F1F06E57E00300D20 /* crypto.c in Sources */, 472F39701E14F75C009260FB /* DataHandler.swift in Sources */, A1EB05901D956923008659C1 /* ReadViewController.swift in Sources */, A1C3DEEC1E0AB15300EB7D02 /* InitViewController.swift in Sources */, 472F398E1E251B8D009260FB /* MailAddress.swift in Sources */, - A135CF101DD4BDD1007E3C29 /* PGPOnePassSignaturePacket.m in Sources */, F12060821DA552FC00F6EF37 /* MailHandlerDelegator.swift in Sources */, + 475B001D1F7B953B006CDD41 /* PGPBigNum.m in Sources */, 4781754A1F06E57E00300D20 /* reader.c in Sources */, + 475B00031F7B953B006CDD41 /* PGPDSA.m in Sources */, F1984D741E1E92B300804E1E /* LabelStyleKit.swift in Sources */, - A15B7BE81E2934CB0024E499 /* EncryptionType.swift in Sources */, A1EB05861D956872008659C1 /* FrequentCell.swift in Sources */, 4781753A1F06E57E00300D20 /* fmemopen.c in Sources */, - A135CF091DD4BDD1007E3C29 /* PGPCryptoUtils.m in Sources */, - A135CF1A1DD4BDD1007E3C29 /* PGPSecretKeyPacket.m in Sources */, F12041FB1DA3FBF7002E4940 /* ListViewController.swift in Sources */, F18B445E1E7044B70080C041 /* FlipTransition.swift in Sources */, - A135CF201DD4BDD1007E3C29 /* PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m in Sources */, + 475B00291F7B953B006CDD41 /* PGPPKCSEmsa.m in Sources */, 472F397E1E1D0B0B009260FB /* EnzevalosContact+CoreDataProperties.swift in Sources */, - A135CF1B1DD4BDD1007E3C29 /* PGPSecretSubKeyPacket.m in Sources */, - A172F90D1E4CD37D00F2A136 /* PGPTemporaryDecryptionObject.swift in Sources */, - A135CF071DD4BDD1007E3C29 /* PGPCompressedPacket.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/enzevalos_iphone/CryptoObject.swift b/enzevalos_iphone/CryptoObject.swift new file mode 100644 index 00000000..5b6f6c4c --- /dev/null +++ b/enzevalos_iphone/CryptoObject.swift @@ -0,0 +1,49 @@ +// +// CryptoObject.swift +// ObjectivePGP +// +// Created by Oliver Wiese on 25.09.17. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +import Foundation +enum SignatureState { + case NoSignature + case InvalidSignature + case ValidSignature +} + +enum EncryptionState { + case NoEncryption + case UnableToDecrypt + case ValidEncryptedWithOldKey + case ValidedEncryptedWithCurrentKey +} + +enum CryptoScheme { + case PGP + case UNKNOWN +} + +public class CryptoObject{ + let chiphertext: Data? + let plaintext: String? + let signatureState: SignatureState + let encryptionState: EncryptionState + let signKey: String? + let encType: CryptoScheme + + + init(chiphertext: Data?, plaintext: String?, sigState: SignatureState, encState: EncryptionState, signKey: String?, encType: CryptoScheme){ + self.chiphertext = chiphertext + self.plaintext = plaintext + self.signatureState = sigState + self.encryptionState = encState + self.signKey = signKey + self.encType = encType + } + + + + +} diff --git a/enzevalos_iphone/Cryptography.swift b/enzevalos_iphone/Cryptography.swift new file mode 100644 index 00000000..d8d10bce --- /dev/null +++ b/enzevalos_iphone/Cryptography.swift @@ -0,0 +1,22 @@ +// +// Encryption.swift +// ObjectivePGP +// +// Created by Oliver Wiese on 25.09.17. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +import Foundation + +public protocol Encryption{ + + // Key handling + func generateKey(adr: String) -> String + func importKeys(key: String, isSecretKey: Bool, autocrypt: Bool) -> [String] + func exportKey(id: String, isSecretkey: Bool, autocrypt: Bool) -> String? + + // operations on keys + func encrypt(plaintext: String, ids: [String], myId: String) -> CryptoObject + func decrypt(data: Data, decryptionId: String, verifyIds: [String]) -> CryptoObject + +} diff --git a/enzevalos_iphone/DecryptedData.swift b/enzevalos_iphone/DecryptedData.swift deleted file mode 100644 index a3660b54..00000000 --- a/enzevalos_iphone/DecryptedData.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// DecryptedData.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 16.06.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -import Foundation - -enum SignatureState { - case NoSignature - case InvalidSignature - case ValidSignature -} - -enum EncryptionState { - case NoEncryption - case UnableToDecrypt - case ValidEncryptedWithOldKey - case ValidedEncryptedWithCurrentKey -} - -public class DecryptedData{ - let decryptedBody: Data? - let signatureState: SignatureState - let encryptionState: EncryptionState - let keyID: String? - let encType: EncryptionType? - - - init(decryptedBody: Data?, sigState: SignatureState, encState: EncryptionState, key: String?, encType: EncryptionType?){ - self.decryptedBody = decryptedBody - self.signatureState = sigState - self.encryptionState = encState - self.keyID = key - self.encType = encType - } - - - - -} diff --git a/enzevalos_iphone/Encryption.swift b/enzevalos_iphone/Encryption.swift deleted file mode 100644 index 2e3068fa..00000000 --- a/enzevalos_iphone/Encryption.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// Encryption.swift -// enzevalos_iphone -// -// Created by jakobsbode on 11.01.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -public protocol Encryption { - /** - * ATTENTION: always have a look at the concrete Encryption you are working with! It my differ in some cases from this definition. e.g. some parameters may be used or unused. - * In some functions nil is returned, if there is no answer to be made at the moment. An example for this case is the PGPEncryption. You have to decrypt the message before you can see, if there is a signature - */ - - var encryptionHandler: EncryptionHandler {get} - var encryptionType: EncryptionType {get} - - init(encHandler: EncryptionHandler) - - - func generateKey(adr: String) -> KeyWrapper? - - //check whether this encryption is used in this mail. This means is it used for encryption OR signing. - func isUsed(_ mail: PersistentMail) -> Bool - - //check whether this encryption is used in this text. This means is it used for encryption OR signing. the key is not known to be used. nil is returned, if there is no answer to be made at the moment. - func isUsed(_ text: String, key: KeyWrapper?) -> Bool - - //check whether this encryption is used in this mail for encryption. nil is returned, if there is no answer to be made at the moment. - func isUsedForEncryption(_ mail: PersistentMail) -> Bool? - - //check whether this encryption is used in this text for encryption. the key is not known to be used. nil is returned, if there is no answer to be made at the moment. - func isUsedForEncryption(_ text: String, key: KeyWrapper?) -> Bool? - - //check whether this encryption is used in this mail for signing. nil is returned, if there is no answer to be made at the moment. - func isUsedForSignature(_ mail: PersistentMail) -> Bool? - - //check whether this encryption is used in this text for signing. nil is returned, if there is no answer to be made at the moment. - func isUsedForSignature(_ text: String, key: KeyWrapper?) -> Bool? - - //decrypt the mails body. the decryted body will be saved in the mail object. - func decrypt(_ mail: PersistentMail) -> String? - - // decrypt the mime data. OLIVER TODO - // func decryptMime(_ data: Data)-> Data? - - func decryptedMime(_ data: Data, from: String) -> DecryptedData? - - //decrypt the mails body. the decryted body will be saved in the mail object. - //Signaturechecking included. will be set in mail object too. - func decryptAndSignatureCheck(_ mail: PersistentMail) - - //decrypt the text with the given key and return it. - func decrypt(_ text: String, keyID: String) -> String? - - //check whether the mail is correctly signed with this encryption. nil is returned, if there is no answer to be made at the moment. - func isCorrectlySigned(_ mail: PersistentMail) -> Bool? - - //check whether the text is correctly signed with this encryption. - func isCorrectlySigned(_ text: String, key: KeyWrapper) -> Bool? - - //encrypt mail for contact - func encrypt(_ mail: PersistentMail) - - func encrypt(_ text: String, mailaddresses: [String]) -> Data? - - //encrypt text with key - func encrypt(_ text: String, keyIDs: [String]) -> Data? - - //sign mail - func sign(_ mail: PersistentMail) - - //sign text - func sign(_ text: String, key: KeyWrapper) -> String - - //sign and encrypt mail for contact - func signAndEncrypt(_ mail: PersistentMail, forContact: KeyRecord) - func signAndEncrypt(_ text: String, keyIDs: [String]) -> Data? - func signAndEncrypt(_ text: String, mailaddresses: [String]) -> Data? - - @discardableResult func addKey(_ keyData: Data, forMailAddresses: [String]?) -> String? - - @discardableResult func addKey(_ keyData: Data, forMailAddresses: [String]?, discoveryMailUID: UInt64?) -> String? - - //key is connected to the senders address, if discoveryMail is set - @discardableResult func addKey(_ keyData: Data, discoveryMail: PersistentMail?) -> String? - - //will be maybe deleted... because keyWrapper will be added when constructed - //func addKey(key: KeyWrapper, forMailAddress: [String]?, callBack: ((success: Bool) -> Void)?) - - func hasKey(_ enzContact: EnzevalosContact) -> Bool - func hasKey(_ mailaddress: String) -> Bool - func getKeyIDs(_ enzContact: EnzevalosContact) -> [String]? - func getKeyIDs(_ mailaddress: String) -> [String]? - - func getActualKeyID(_ mailaddress: String) -> String? - - func keyIDExists(_ keyID: String) -> Bool - - func getKey(_ keyID: String) -> KeyWrapper? - - //internaly done; update is done when a keyWrapper is manipulated - //func updateKey(key: KeyWrapper, callBack: ((success: Bool) -> Void)?) - func removeKey(_ keyID: String) //-> Bool - - func removeKey(_ key: KeyWrapper) //-> Bool - - //includes privatekeys too - func removeAllKeys() - - func printAllKeyIDs() - - func addMailAddressForKey(_ mailAddress: String, keyID: String) - - func removeMailAddressForKey(_ mailaddress: String, keyID: String) - - func keyOfThisEncryption(_ keyData: Data) -> Bool? - - func autocryptHeader(_ adr: String) -> String? -} diff --git a/enzevalos_iphone/EncryptionHandler.swift b/enzevalos_iphone/EncryptionHandler.swift deleted file mode 100644 index 4b8f77c0..00000000 --- a/enzevalos_iphone/EncryptionHandler.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// EncryptionHandler.swift -// enzevalos_iphone -// -// Created by jakobsbode on 11.01.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -import Foundation - -public protocol EncryptionHandler { - //var keychain - - //----- static stuff ----- - // static func getEncryption(_ encryptionType: EncryptionType) -> Encryption? - // static func hasKey(_ enzContact: EnzevalosContact) -> Bool - // static func hasKey(_ mailAddress: String) -> Bool - // static func getEncryptionTypeForMail(_ mail: Mail) -> EncryptionType - // static func sortMailaddressesByEncryption(_ mailaddresses: [String]) -> [EncryptionType: [String]] - // static func sortMailaddressesByEncryptionMCOAddress(_ mailaddresses: [String]) -> [EncryptionType: [MCOAddress]] - - - //handle entrys in keychain for different Encryptions - func addPersistentData(_ data: Data, searchKey: String, encryptionType: EncryptionType) - //for all encryptions - //func getPersistentData(searchKey: String) -> NSData? - func hasPersistentData(_ searchKey: String, encryptionType: EncryptionType) -> Bool - //for given encryption - func getPersistentData(_ searchKey: String, encryptionType: EncryptionType) -> Data? - func replacePersistentData(_ searchKey: String, replacementData: Data, encryptionType: EncryptionType) //-> Bool - func deletePersistentData(_ searchKey: String, encryptionType: EncryptionType) //-> Bool - -} diff --git a/enzevalos_iphone/EncryptionType.swift b/enzevalos_iphone/EncryptionType.swift deleted file mode 100644 index 696b9c56..00000000 --- a/enzevalos_iphone/EncryptionType.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// EncryptionType.swift -// enzevalos_iphone -// -// Created by jakobsbode on 13.01.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -public enum EncryptionType : String { - case unknown = "unknown", PGP = "PGP" - - var autocryptSymbol: String{ - switch self { - case .PGP: - return "1" - default: - return "" - } - - } - - static func typeFromAutocrypt(_ symbol: String)-> EncryptionType{ - switch symbol { - case "1": - return .PGP - default: - return .unknown - } - } - - static func fromString(_ string: String?)->EncryptionType{ - if let symbol = string{ - switch symbol { - case "PGP": - return .PGP - case "1": - return .PGP - default: - return .unknown - } - } - return .unknown - } -} diff --git a/enzevalos_iphone/EnzevalosEncryptionHandler.swift b/enzevalos_iphone/EnzevalosEncryptionHandler.swift deleted file mode 100644 index e1d7fb21..00000000 --- a/enzevalos_iphone/EnzevalosEncryptionHandler.swift +++ /dev/null @@ -1,176 +0,0 @@ -// -// EnzevalosEncryptionHandler.swift -// enzevalos_iphone -// -// Created by jakobsbode on 13.01.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - - -import KeychainAccess - -//statisch von außen drauf zugreifen; auf Objekt von Encryption aus zugreifen. -class EnzevalosEncryptionHandler: EncryptionHandler { - private static let handler = EnzevalosEncryptionHandler() - private static var encryptions: [EncryptionType: Encryption] = [ - EncryptionType.PGP: PGPEncryption(encHandler: handler) - //TODO insert new Encryptions here - ] - - static func getEncryption(_ encryptionType: EncryptionType) -> Encryption? { - if encryptionType == EncryptionType.PGP { - if encryptions[EncryptionType.PGP] == nil { - encryptions[EncryptionType.PGP] = PGPEncryption(encHandler: handler) - } - return encryptions[EncryptionType.PGP]! - } - //TODO insert new Encryptions here - return nil - } - - static func hasKey(_ enzContact: EnzevalosContact) -> Bool { - for (_, enc) in encryptions { - if enc.hasKey(enzContact) { - return true - } - } - return false - } - - static func hasKey(_ mailAddress: String) -> Bool { - for (_, enc) in encryptions { - if enc.hasKey(mailAddress) { - return true - } - } - return false - } - - static func getEncryptionType(_ mailAddress: String) -> EncryptionType { - for (_, enc) in encryptions { - if enc.hasKey(mailAddress) { - return enc.encryptionType - } - } - return EncryptionType.unknown - } - - - - static func getEncryptionTypeForMail(_ mail: PersistentMail) -> EncryptionType { - for (type, enc) in encryptions { - if enc.isUsed(mail) { - return type - } - } - return EncryptionType.unknown - } - - //a mailaddress can be found in multiple encryptionTypes - static func sortMailaddressesByEncryption(_ mailaddresses: [String]) -> [EncryptionType: [String]] { - //TODO add different Encryptions here. This may be done via an attribute Mail_Address, setting the preffered encryption - var returnValue: [EncryptionType: [String]] = [:] - var inserted: Bool - for addr in mailaddresses { - inserted = false - for (_, enc) in encryptions { - if let array = enc.getKeyIDs(addr) { - if array != [] { - if returnValue[enc.encryptionType] == nil { - returnValue[enc.encryptionType] = [addr] - } else { - returnValue[enc.encryptionType]!.append(addr) - } - inserted = true - } - } - } - if !inserted { - if returnValue[EncryptionType.unknown] == nil { - returnValue[EncryptionType.unknown] = [addr] - } else { - returnValue[EncryptionType.unknown]!.append(addr) - } - } - } - return returnValue - } - - //a mailaddress can be found multiple encryptionTypes - static func sortMailaddressesByEncryptionMCOAddress(_ mailaddresses: [String], sendEncryptedIfPossible: Bool = true) -> [EncryptionType: [MCOAddress]] { - //TODO add different Encryptions here. This may be done via an attribute Mail_Address, setting the preffered encryption - var returnValue: [EncryptionType: [MCOAddress]] = [:] - var inserted: Bool - for addr in mailaddresses { - inserted = false - if sendEncryptedIfPossible { - for (_, enc) in encryptions { - if let array = enc.getKeyIDs(addr) { - if array != [] { - if returnValue[enc.encryptionType] == nil { - returnValue[enc.encryptionType] = [MCOAddress(displayName: "", mailbox: addr)] - } else { - returnValue[enc.encryptionType]!.append(MCOAddress(displayName: "", mailbox: addr)) - } - inserted = true - } - } - } - } - if !inserted { - if returnValue[EncryptionType.unknown] == nil { - returnValue[EncryptionType.unknown] = [MCOAddress(displayName: "", mailbox: addr)] - } else { - returnValue[EncryptionType.unknown]!.append(MCOAddress(displayName: "", mailbox: addr)) - } - } - } - return returnValue - } - - //----------------------------------------------------------------------------------------- - - private var keychain: Keychain - - private init() { - keychain = Keychain(service: "Enzevalos")//FIXME: .accessibility(.WhenUnlocked) - } - - func hasPersistentData(_ searchKey: String, encryptionType: EncryptionType) -> Bool { - return getPersistentData(searchKey, encryptionType: encryptionType) != nil - } - - //handle entrys in keychain for different Encryptions - func addPersistentData(_ data: Data, searchKey: String, encryptionType: EncryptionType) { - let testData = try? keychain.getData(encryptionType.rawValue + "-" + searchKey) - if let tmp = testData, tmp == nil { - keychain[data: encryptionType.rawValue + "-" + searchKey] = data - } - - } - - //for all encryptions - /*func getPersistentData(searchKey: String) -> NSData? { - - }*/ - - //for given encryption - func getPersistentData(_ searchKey: String, encryptionType: EncryptionType) -> Data? { - return (try! keychain.getData(encryptionType.rawValue + "-" + searchKey)) - } - - func replacePersistentData(_ searchKey: String, replacementData: Data, encryptionType: EncryptionType) { - if !self.hasPersistentData(searchKey, encryptionType: encryptionType) { //let tmp = (try? keychain.getData(encryptionType.rawValue+"-"+searchKey)), _ = tmp { - return - } - keychain[data: encryptionType.rawValue + "-" + searchKey] = replacementData - } - - func deletePersistentData(_ searchKey: String, encryptionType: EncryptionType) { - let testData = try? keychain.getData(encryptionType.rawValue + "-" + searchKey) - if let tmp = testData, tmp == nil { - return - } - keychain[data: encryptionType.rawValue + "-" + searchKey] = nil - } -} diff --git a/enzevalos_iphone/KeyViewController.swift b/enzevalos_iphone/KeyViewController.swift index 111c22ed..80bc5962 100644 --- a/enzevalos_iphone/KeyViewController.swift +++ b/enzevalos_iphone/KeyViewController.swift @@ -13,8 +13,6 @@ class KeyViewController: UIViewController { @IBOutlet var tableView: UITableView! var record: KeyRecord? - var keyWrapper: KeyWrapper? - override func viewDidLoad() { super.viewDidLoad() if let rec = record, rec.key != nil { diff --git a/enzevalos_iphone/KeyWrapper.swift b/enzevalos_iphone/KeyWrapper.swift deleted file mode 100644 index e9c7a49f..00000000 --- a/enzevalos_iphone/KeyWrapper.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// KeyWrapper.swift -// enzevalos_iphone -// -// Created by jakobsbode on 13.01.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -import Foundation - -public protocol KeyWrapper { - - var revoked: Bool {get set} - var revokeTime: Date? {get} - var trustlevel: Int {get set} - var verified: Bool {get set} - var verifyTime: Date? {get} - var discoveryTime: Date {get} - var discoveryMailUID: UInt64? {get} - var type: EncryptionType {get} - var keyID: String {get} - var fingerprint: String {get} - var creationDate: Date {get} - var expireDate: Date? {get} - - //Mailaddresses we discovered using this key - var mailAddresses: [String]? {get set} - - //Mailaddresses, that are listed in the Key - var mailAddressesInKey: [String]? {get} - - init(coder: NSCoder) - - func encodeWithCoder(_ coder: NSCoder) -} diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.h b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.h new file mode 100644 index 00000000..666b43a8 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.h @@ -0,0 +1,26 @@ +// +// PGPCryptoHash.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 21/05/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^PGPUpdateBlock)(void (^update)(const void *data, int lenght)); + +NSData *_Nullable PGPCalculateHash(PGPHashAlgorithm algorithm, PGP_NOESCAPE PGPUpdateBlock update); + +NSData *_Nullable PGPmd5(PGP_NOESCAPE PGPUpdateBlock update); +NSData *_Nullable PGPsha1(PGP_NOESCAPE PGPUpdateBlock update); +NSData *_Nullable PGPsha224(PGP_NOESCAPE PGPUpdateBlock update); +NSData *_Nullable PGPsha256(PGP_NOESCAPE PGPUpdateBlock update); +NSData *_Nullable PGPsha384(PGP_NOESCAPE PGPUpdateBlock update); +NSData *_Nullable PGPsha512(PGP_NOESCAPE PGPUpdateBlock update); +NSData *_Nullable PGPripemd160(PGP_NOESCAPE PGPUpdateBlock update); + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.m b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.m new file mode 100644 index 00000000..c0f6433b --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoHash.m @@ -0,0 +1,75 @@ +// +// PGPCryptoHash.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 22/05/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPCryptoHash.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +#import <CommonCrypto/CommonCrypto.h> +#import <Foundation/Foundation.h> +#import <openssl/ripemd.h> + +NS_ASSUME_NONNULL_BEGIN + +NSData *_Nullable PGPCalculateHash(PGPHashAlgorithm algorithm, PGP_NOESCAPE PGPUpdateBlock update) { + switch (algorithm) { + case PGPHashMD5: + return PGPmd5(update); + case PGPHashSHA1: + return PGPsha1(update); + case PGPHashSHA224: + return PGPsha224(update); + case PGPHashSHA256: + return PGPsha256(update); + case PGPHashSHA384: + return PGPsha384(update); + case PGPHashSHA512: + return PGPsha512(update); + case PGPHashRIPEMD160: + return PGPripemd160(update); + default: + PGPLogWarning(@"Hash algorithm code %@ is not supported.", @(algorithm)); + } + return nil; +} + +#define commonHashImpl(name, INITfn, UPDATEfn, FINALfn, CTX, DIGEST_LENGTH) \ + NSData *_Nullable PGP##name(PGP_NOESCAPE PGPUpdateBlock update) { \ + let ctx = calloc(1, sizeof(CTX)); \ + if (!ctx) { \ + return nil; \ + } \ + \ + INITfn(ctx); \ + \ + if (update) { \ + update(^(const void *data, int lenght) { \ + UPDATEfn(ctx, data, (CC_LONG)lenght); \ + }); \ + } \ + \ + UInt8 *outbuf = calloc(DIGEST_LENGTH, sizeof(UInt8)); \ + if (!outbuf) { \ + free(ctx); \ + return nil; \ + } \ + FINALfn(outbuf, ctx); \ + \ + let outData = [NSData dataWithBytes:outbuf length:DIGEST_LENGTH]; \ + \ + free(outbuf); \ + free(ctx); \ + \ + return outData; \ + } + +commonHashImpl(md5, CC_MD5_Init, CC_MD5_Update, CC_MD5_Final, CC_MD5_CTX, CC_MD5_DIGEST_LENGTH) commonHashImpl(sha1, CC_SHA1_Init, CC_SHA1_Update, CC_SHA1_Final, CC_SHA1_CTX, CC_SHA1_DIGEST_LENGTH) commonHashImpl(sha224, CC_SHA224_Init, CC_SHA224_Update, CC_SHA224_Final, CC_SHA256_CTX, CC_SHA224_DIGEST_LENGTH) commonHashImpl(sha256, CC_SHA256_Init, CC_SHA256_Update, CC_SHA256_Final, CC_SHA256_CTX, CC_SHA256_DIGEST_LENGTH); +commonHashImpl(sha384, CC_SHA384_Init, CC_SHA384_Update, CC_SHA384_Final, CC_SHA512_CTX, CC_SHA384_DIGEST_LENGTH) commonHashImpl(sha512, CC_SHA512_Init, CC_SHA512_Update, CC_SHA512_Final, CC_SHA512_CTX, CC_SHA512_DIGEST_LENGTH) commonHashImpl(ripemd160, RIPEMD160_Init, RIPEMD160_Update, RIPEMD160_Final, RIPEMD160_CTX, RIPEMD160_DIGEST_LENGTH); + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.h b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.h new file mode 100644 index 00000000..00f47e03 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.h @@ -0,0 +1,26 @@ +// +// PGPCryptoUtils.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 12/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPSecretKeyPacket; + +@interface PGPCryptoUtils : NSObject + ++ (NSUInteger)blockSizeOfSymmetricAlhorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm; ++ (NSUInteger)keySizeOfSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm; ++ (NSUInteger)hashSizeOfHashAlhorithm:(PGPHashAlgorithm)hashAlgorithm; ++ (NSData *)randomData:(NSInteger)length; ++ (nullable NSData *)decryptData:(NSData *)data usingSecretKeyPacket:(PGPSecretKeyPacket *)keyPacket; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPCryptoUtils.m b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.m similarity index 57% rename from PGPCryptoUtils.m rename to enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.m index 90ffaf07..f2b064aa 100644 --- a/PGPCryptoUtils.m +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPCryptoUtils.m @@ -7,21 +7,27 @@ // #import "PGPCryptoUtils.h" +#import "PGPRSA.h" +#import "PGPDSA.h" +#import "PGPSecretKeyPacket.h" +#import "PGPMacros+Private.h" #import <CommonCrypto/CommonCrypto.h> +#import <Security/Security.h> -#include <openssl/cast.h> -#include <openssl/idea.h> -#include <openssl/aes.h> -#include <openssl/des.h> -#include <openssl/camellia.h> -#include <openssl/blowfish.h> -#include <openssl/ripemd.h> +#import <openssl/aes.h> +#import <openssl/blowfish.h> +#import <openssl/camellia.h> +#import <openssl/cast.h> +#import <openssl/des.h> +#import <openssl/idea.h> +#import <openssl/ripemd.h> + +NS_ASSUME_NONNULL_BEGIN @implementation PGPCryptoUtils -+ (NSUInteger) blockSizeOfSymmetricAlhorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm -{ ++ (NSUInteger)blockSizeOfSymmetricAlhorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm { switch (symmetricAlgorithm) { case PGPSymmetricIDEA: return IDEA_BLOCK; @@ -43,13 +49,12 @@ return NSNotFound; } -+ (NSUInteger) keySizeOfSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm -{ ++ (NSUInteger)keySizeOfSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm { switch (symmetricAlgorithm) { case PGPSymmetricIDEA: return IDEA_KEY_LENGTH; case PGPSymmetricTripleDES: - return kCCKeySize3DES; //24 or 8 ? + return kCCKeySize3DES; // 24 or 8 ? case PGPSymmetricCAST5: return kCCKeySizeMaxCAST; case PGPSymmetricBlowfish: @@ -68,8 +73,7 @@ return NSNotFound; } -+ (NSUInteger) hashSizeOfHashAlhorithm:(PGPHashAlgorithm)hashAlgorithm -{ ++ (NSUInteger)hashSizeOfHashAlhorithm:(PGPHashAlgorithm)hashAlgorithm { switch (hashAlgorithm) { case PGPHashMD5: return CC_MD5_DIGEST_LENGTH; @@ -91,4 +95,31 @@ return NSNotFound; } ++ (NSData *)randomData:(NSInteger)length { + NSMutableData *data = [NSMutableData dataWithLength:length]; + int status = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes); + NSAssert(status == errSecSuccess, @"Failed to generate secure random bytes"); + return data; +} + ++ (nullable NSData *)decryptData:(NSData *)data usingSecretKeyPacket:(PGPSecretKeyPacket *)keyPacket { + PGPAssertClass(data, NSData); + + switch (keyPacket.publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + // return decrypted m + return [PGPRSA privateDecrypt:data withSecretKeyPacket:keyPacket]; + } break; + default: + // TODO: add algorithms + [NSException raise:@"PGPNotSupported" format:@"Algorithm not supported"]; + break; + } + return nil; +} + @end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.h b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.h new file mode 100644 index 00000000..e1ba5449 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.h @@ -0,0 +1,31 @@ +// +// PGPDSA.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 26/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPMPI.h" +#import "PGPTypes.h" +#import "PGPKeyMaterial.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPSecretKeyPacket, PGPPublicKeyPacket, PGPSignaturePacket, PGPKey; + +@interface PGPDSA : NSObject + +PGP_EMPTY_INIT_UNAVAILABLE; + +// signature ++ (BOOL)verify:(NSData *)toVerify signature:(PGPSignaturePacket *)signaturePacket withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket; ++ (NSArray<PGPMPI *> *)sign:(NSData *)toSign key:(PGPKey *)key; + +// new keys ++ (nullable PGPKeyMaterial *)generateNewKeyMPIArray:(const int)bits; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.m b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.m new file mode 100644 index 00000000..b908b51e --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPDSA.m @@ -0,0 +1,156 @@ +// +// PGPDSA.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 26/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPDSA.h" +#import "PGPMPI.h" +#import "PGPPKCSEmsa.h" +#import "PGPPartialKey.h" +#import "PGPPublicKeyPacket.h" +#import "PGPSecretKeyPacket.h" +#import "PGPSignaturePacket+Private.h" +#import "PGPBigNum+Private.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +#import <openssl/err.h> +#import <openssl/ssl.h> + +#import <openssl/bn.h> +#import <openssl/dsa.h> +#import <openssl/ecdsa.h> + +#import <Security/Security.h> + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPDSA + ++ (BOOL)verify:(NSData *)toVerify signature:(PGPSignaturePacket *)signaturePacket withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket { + DSA_SIG *sig = DSA_SIG_new(); + pgp_defer { if (sig) { DSA_SIG_free(sig); } }; + + DSA *dsa = DSA_new(); + pgp_defer { if (dsa) { DSA_free(dsa); } }; + + if (!dsa || !sig) { + return NO; + } + + dsa->p = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_P] bigNum] bignumRef]); + dsa->q = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_Q] bigNum] bignumRef]); + dsa->g = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_G] bigNum] bignumRef]); + dsa->pub_key = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_Y] bigNum] bignumRef]); + + sig->r = BN_dup([[[signaturePacket signatureMPI:PGPMPI_R] bigNum] bignumRef]); + sig->s = BN_dup([[[signaturePacket signatureMPI:PGPMPI_S] bigNum] bignumRef]); + + if (!dsa->p || !dsa->q || !dsa->g || !dsa->pub_key || sig->r || sig->s) { + PGPLogError(@"Missing DSA values."); + return NO; + } + + var hashLen = toVerify.length; + unsigned int qlen = 0; + if ((qlen = (unsigned int)BN_num_bytes(dsa->q)) < hashLen) { + hashLen = qlen; + } + + if (DSA_do_verify(toVerify.bytes, (int)hashLen, sig, dsa) < 0) { + ERR_load_crypto_strings(); + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + pgp_defer { if (errBuf) { free(errBuf); } }; + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + return NO; + } + + dsa->p = dsa->q = dsa->g = dsa->pub_key = NULL; + sig->r = sig->s = NULL; + return YES; +} + ++ (NSArray<PGPMPI *> *)sign:(NSData *)toSign key:(PGPKey *)key { + DSA *dsa = DSA_new(); + pgp_defer { if (dsa) { DSA_free(dsa); } }; + + if (!dsa) { + return @[]; + } + + let signingKeyPacket = key.signingSecretKey; + let publicKeyPacket = PGPCast(key.publicKey.primaryKeyPacket, PGPPublicKeyPacket); + + dsa->p = BN_dup([publicKeyPacket publicMPI:PGPMPI_P].bigNum.bignumRef); + dsa->q = BN_dup([publicKeyPacket publicMPI:PGPMPI_Q].bigNum.bignumRef); + dsa->g = BN_dup([publicKeyPacket publicMPI:PGPMPI_G].bigNum.bignumRef); + dsa->pub_key = BN_dup([publicKeyPacket publicMPI:PGPMPI_Y].bigNum.bignumRef); + dsa->priv_key = BN_dup([signingKeyPacket secretMPI:PGPMPI_X].bigNum.bignumRef); + + DSA_SIG * _Nullable sig = DSA_do_sign(toSign.bytes, (int)toSign.length, dsa); + if (!sig) { + ERR_load_crypto_strings(); + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + pgp_defer { if (errBuf) { free(errBuf); } }; + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + return @[]; + } + + let MPI_R = [[PGPMPI alloc] initWithBigNum:[[PGPBigNum alloc] initWithBIGNUM:sig->r] identifier:PGPMPI_R]; + let MPI_S = [[PGPMPI alloc] initWithBigNum:[[PGPBigNum alloc] initWithBIGNUM:sig->s] identifier:PGPMPI_S]; + + dsa->p = dsa->q = dsa->g = dsa->pub_key = dsa->priv_key = NULL; + + return @[MPI_R, MPI_S]; +} + + +#pragma mark - Generate + ++ (nullable PGPKeyMaterial *)generateNewKeyMPIArray:(const int)bits { + BN_CTX *ctx = BN_CTX_new(); + pgp_defer { if (ctx) { BN_CTX_free(ctx); } }; + DSA *dsa = DSA_new(); + pgp_defer { if (dsa) { DSA_free(dsa); } }; + + DSA_generate_parameters_ex(dsa, bits, NULL, 0, NULL, NULL, NULL); + if (DSA_generate_key(dsa) != 1) { + return nil; + } + + let bigP = [[PGPBigNum alloc] initWithBIGNUM:dsa->p]; + let bigQ = [[PGPBigNum alloc] initWithBIGNUM:dsa->q]; + let bigG = [[PGPBigNum alloc] initWithBIGNUM:dsa->g]; + let bigR = [[PGPBigNum alloc] initWithBIGNUM:dsa->r]; + let bigX = [[PGPBigNum alloc] initWithBIGNUM:dsa->priv_key]; + let bigY = [[PGPBigNum alloc] initWithBIGNUM:dsa->pub_key]; + + let mpiP = [[PGPMPI alloc] initWithBigNum:bigP identifier:PGPMPI_P]; + let mpiQ = [[PGPMPI alloc] initWithBigNum:bigQ identifier:PGPMPI_Q]; + let mpiG = [[PGPMPI alloc] initWithBigNum:bigG identifier:PGPMPI_G]; + let mpiR = [[PGPMPI alloc] initWithBigNum:bigR identifier:PGPMPI_R]; + let mpiX = [[PGPMPI alloc] initWithBigNum:bigX identifier:PGPMPI_X]; + let mpiY = [[PGPMPI alloc] initWithBigNum:bigY identifier:PGPMPI_Y]; + + let keyMaterial = [[PGPKeyMaterial alloc] init]; + keyMaterial.p = mpiP; + keyMaterial.q = mpiQ; + keyMaterial.g = mpiG; + keyMaterial.r = mpiR; + keyMaterial.x = mpiX; + keyMaterial.y = mpiY; + + return keyMaterial; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.h b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.h new file mode 100644 index 00000000..987a3bf8 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.h @@ -0,0 +1,25 @@ +// +// PGPKeyMaterial.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 25/08/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> +#import "PGPMPI.h" + +@interface PGPKeyMaterial: NSObject + +@property (nonatomic) PGPMPI *n; +@property (nonatomic) PGPMPI *e; +@property (nonatomic) PGPMPI *d; +@property (nonatomic) PGPMPI *p; +@property (nonatomic) PGPMPI *q; +@property (nonatomic) PGPMPI *r; +@property (nonatomic) PGPMPI *g; +@property (nonatomic) PGPMPI *u; +@property (nonatomic) PGPMPI *x; +@property (nonatomic) PGPMPI *y; + +@end diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.m b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.m new file mode 100644 index 00000000..e3b96a05 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPKeyMaterial.m @@ -0,0 +1,13 @@ +// +// PGPKeyMaterial.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 25/08/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPKeyMaterial.h" + +@implementation PGPKeyMaterial + +@end diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.h b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.h new file mode 100644 index 00000000..5202d0bd --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.h @@ -0,0 +1,35 @@ +// +// PGPPublicKeyAlgorithmRSA.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 26/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPMPI.h" +#import "PGPTypes.h" +#import "PGPKeyMaterial.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPSecretKeyPacket, PGPPublicKeyPacket; + +@interface PGPRSA : NSObject + +PGP_EMPTY_INIT_UNAVAILABLE; + +// encryption ++ (nullable NSData *)publicEncrypt:(NSData *)toEncrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket; ++ (nullable NSData *)privateDecrypt:(NSData *)toDecrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket; + +// signature ++ (nullable NSData *)publicDecrypt:(NSData *)toDecrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket; ++ (nullable NSData *)privateEncrypt:(NSData *)toEncrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket; + +// new keys ++ (nullable PGPKeyMaterial *)generateNewKeyMPIArray:(const int)bits; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.m b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.m new file mode 100644 index 00000000..90db8984 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/CryptoBox/PGPRSA.m @@ -0,0 +1,272 @@ +// +// PGPRSA.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 26/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPRSA.h" +#import "PGPMPI.h" +#import "PGPPKCSEmsa.h" +#import "PGPPartialKey.h" +#import "PGPPublicKeyPacket.h" +#import "PGPSecretKeyPacket.h" +#import "PGPBigNum+Private.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +#import <openssl/err.h> +#import <openssl/ssl.h> + +#import <openssl/bn.h> +#import <openssl/rsa.h> + +#import <Security/Security.h> + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPRSA + +// encrypts the bytes ++ (nullable NSData *)publicEncrypt:(NSData *)toEncrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket { + RSA *rsa = RSA_new(); + if (!rsa) { + return nil; + } + pgp_defer { RSA_free(rsa); }; + + rsa->n = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_N] bigNum] bignumRef]); + rsa->e = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_E] bigNum] bignumRef]); + + NSAssert(rsa->n && rsa->e, @"Missing N or E"); + if (!rsa->n || !rsa->e) { + return nil; + } + + uint8_t *encrypted_em = calloc(BN_num_bytes(rsa->n) & SIZE_T_MAX, 1); + pgp_defer { free(encrypted_em); }; + int em_len = RSA_public_encrypt(toEncrypt.length & INT_MAX, toEncrypt.bytes, encrypted_em, rsa, RSA_NO_PADDING); + if (em_len == -1 || em_len != (publicKeyPacket.keySize & INT_MAX)) { + ERR_load_crypto_strings(); + + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + free(errBuf); + return nil; + } + + // decrypted encoded EME + NSData *encryptedEm = [NSData dataWithBytes:encrypted_em length:em_len]; + + rsa->n = rsa->e = NULL; + return encryptedEm; +} + +// decrypt bytes ++ (nullable NSData *)privateDecrypt:(NSData *)toDecrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket { + RSA *rsa = RSA_new(); + if (!rsa) { + return nil; + } + pgp_defer { RSA_free(rsa); }; + + rsa->n = BN_dup([[[secretKeyPacket publicMPI:PGPMPI_N] bigNum] bignumRef]); + rsa->e = BN_dup([[[secretKeyPacket publicMPI:PGPMPI_E] bigNum] bignumRef]); + + rsa->d = BN_dup([[[secretKeyPacket secretMPI:PGPMPI_D] bigNum] bignumRef]); + rsa->p = BN_dup([[[secretKeyPacket secretMPI:PGPMPI_Q] bigNum] bignumRef]); /* p and q are round the other way in openssl */ + rsa->q = BN_dup([[[secretKeyPacket secretMPI:PGPMPI_P] bigNum] bignumRef]); + + if (rsa->d == NULL) { + return nil; + } + + if (RSA_check_key(rsa) != 1) { + ERR_load_crypto_strings(); + + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + free(errBuf); + + ERR_free_strings(); + return nil; + } + + uint8_t *outbuf = calloc(RSA_size(rsa) & SIZE_T_MAX, 1); + pgp_defer { free(outbuf); }; + int t = RSA_private_decrypt(toDecrypt.length & INT_MAX, toDecrypt.bytes, outbuf, rsa, RSA_NO_PADDING); + if (t == -1) { + ERR_load_crypto_strings(); + + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + free(errBuf); + + ERR_free_strings(); + return nil; + } + + NSData *decryptedData = [NSData dataWithBytes:outbuf length:t]; + NSAssert(decryptedData, @"Missing data"); + + rsa->n = rsa->d = rsa->p = rsa->q = rsa->e = NULL; + + return decryptedData; +} + +// sign ++ (nullable NSData *)privateEncrypt:(NSData *)toEncrypt withSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket { + let rsa = RSA_new(); + if (!rsa) { + return nil; + } + pgp_defer { RSA_free(rsa); }; + + rsa->n = BN_dup([[[secretKeyPacket publicMPI:PGPMPI_N] bigNum] bignumRef]); + rsa->d = BN_dup([[[secretKeyPacket secretMPI:PGPMPI_D] bigNum] bignumRef]); + rsa->p = BN_dup([[[secretKeyPacket secretMPI:PGPMPI_Q] bigNum] bignumRef]); /* p and q are round the other way in openssl */ + rsa->q = BN_dup([[[secretKeyPacket secretMPI:PGPMPI_P] bigNum] bignumRef]); + rsa->e = BN_dup([[[secretKeyPacket publicMPI:PGPMPI_E] bigNum] bignumRef]); + + if (toEncrypt.length > secretKeyPacket.keySize) { + return nil; + } + + /* If this isn't set, it's very likely that the programmer hasn't */ + /* decrypted the secret key. RSA_check_key segfaults in that case. */ + if (rsa->d == NULL) { + return nil; + } + + if (RSA_check_key(rsa) != 1) { + ERR_load_crypto_strings(); + + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + free(errBuf); + + ERR_free_strings(); + return nil; + } + + uint8_t *outbuf = calloc(RSA_size(rsa) & SIZE_T_MAX, 1); + pgp_defer { free(outbuf); }; + + int t = RSA_private_encrypt(toEncrypt.length & INT_MAX, (UInt8 *)toEncrypt.bytes, outbuf, rsa, RSA_NO_PADDING); + if (t == -1) { + ERR_load_crypto_strings(); + + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + free(errBuf); + + ERR_free_strings(); + return nil; + } + + NSData *encryptedData = [NSData dataWithBytes:outbuf length:t]; + NSAssert(encryptedData, @"Missing calculated data"); + + rsa->n = rsa->d = rsa->p = rsa->q = rsa->e = NULL; + + return encryptedData; +} + +// recovers the message digest ++ (nullable NSData *)publicDecrypt:(NSData *)toDecrypt withPublicKeyPacket:(PGPPublicKeyPacket *)publicKeyPacket { + RSA *rsa = RSA_new(); + if (!rsa) { + return nil; + } + pgp_defer { RSA_free(rsa); }; + + rsa->n = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_N] bigNum] bignumRef]); + rsa->e = BN_dup([[[publicKeyPacket publicMPI:PGPMPI_E] bigNum] bignumRef]); + + NSAssert(rsa->n && rsa->e, @"Missing N or E"); + if (!rsa->n || !rsa->e) { + return nil; + } + + uint8_t *decrypted_em = calloc(RSA_size(rsa) & SIZE_T_MAX, 1); // RSA_size(rsa) - 11 + pgp_defer { free(decrypted_em); }; + int em_len = RSA_public_decrypt(toDecrypt.length & INT_MAX, toDecrypt.bytes, decrypted_em, rsa, RSA_NO_PADDING); + if (em_len == -1 || em_len != (publicKeyPacket.keySize & INT_MAX)) { + ERR_load_crypto_strings(); + + unsigned long err_code = ERR_get_error(); + char *errBuf = calloc(512, sizeof(char)); + ERR_error_string(err_code, errBuf); + PGPLogDebug(@"%@", [NSString stringWithCString:errBuf encoding:NSASCIIStringEncoding]); + free(errBuf); + + return nil; + } + + // decrypted PKCS emsa + NSData *decryptedEm = [NSData dataWithBytes:decrypted_em length:em_len]; + + rsa->n = rsa->e = NULL; + + return decryptedEm; +} + +#pragma mark - Generate + ++ (nullable PGPKeyMaterial *)generateNewKeyMPIArray:(const int)bits { + BN_CTX *ctx = BN_CTX_new(); + RSA *rsa = RSA_new(); + BIGNUM *e = BN_new(); + + pgp_defer { + BN_CTX_free(ctx); + BN_clear_free(e); + RSA_free(rsa); + }; + + BN_set_word(e, 65537UL); + + if (RSA_generate_key_ex(rsa, bits, e, NULL) != 1) { + return nil; + } + + let bigN = [[PGPBigNum alloc] initWithBIGNUM:rsa->n]; + let bigE = [[PGPBigNum alloc] initWithBIGNUM:rsa->e]; + let bigD = [[PGPBigNum alloc] initWithBIGNUM:rsa->d]; + let bigP = [[PGPBigNum alloc] initWithBIGNUM:rsa->p]; + let bigQ = [[PGPBigNum alloc] initWithBIGNUM:rsa->q]; + let bigU = [[PGPBigNum alloc] initWithBIGNUM:BN_mod_inverse(NULL, rsa->p, rsa->q, ctx)]; + + let mpiN = [[PGPMPI alloc] initWithBigNum:bigN identifier:PGPMPI_N]; + let mpiE = [[PGPMPI alloc] initWithBigNum:bigE identifier:PGPMPI_E]; + let mpiD = [[PGPMPI alloc] initWithBigNum:bigD identifier:PGPMPI_D]; + let mpiP = [[PGPMPI alloc] initWithBigNum:bigP identifier:PGPMPI_P]; + let mpiQ = [[PGPMPI alloc] initWithBigNum:bigQ identifier:PGPMPI_Q]; + let mpiU = [[PGPMPI alloc] initWithBigNum:bigU identifier:PGPMPI_U]; + + let keyMaterial = [[PGPKeyMaterial alloc] init]; + keyMaterial.n = mpiN; + keyMaterial.e = mpiE; + keyMaterial.d = mpiD; + keyMaterial.p = mpiP; + keyMaterial.q = mpiQ; + keyMaterial.u = mpiU; + + return keyMaterial; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Info.plist b/enzevalos_iphone/ObjectivePGP/Info.plist new file mode 100644 index 00000000..425e1d11 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>0.8.0</string> + <key>CFBundleVersion</key> + <string>$(CURRENT_PROJECT_VERSION)</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/ObjectivePGP-Prefix.pch b/enzevalos_iphone/ObjectivePGP/ObjectivePGP-Prefix.pch similarity index 89% rename from ObjectivePGP-Prefix.pch rename to enzevalos_iphone/ObjectivePGP/ObjectivePGP-Prefix.pch index eb2007ec..22325dca 100644 --- a/ObjectivePGP-Prefix.pch +++ b/enzevalos_iphone/ObjectivePGP/ObjectivePGP-Prefix.pch @@ -6,4 +6,7 @@ #ifdef __OBJC__ #import <Foundation/Foundation.h> +// +// +// #endif diff --git a/enzevalos_iphone/ObjectivePGP/ObjectivePGP.h b/enzevalos_iphone/ObjectivePGP/ObjectivePGP.h new file mode 100644 index 00000000..163f3351 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/ObjectivePGP.h @@ -0,0 +1,51 @@ +// +// ObjectivePGP.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 05/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +//! Project version number for ObjectivePGP. +FOUNDATION_EXPORT double ObjectivePGPVersionNumber; + +//! Project version string for ObjectivePGP. +FOUNDATION_EXPORT const unsigned char ObjectivePGPVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import <ObjectivePGP/PublicHeader.h> + +#import "PGPFoundation.h" +#import "ObjectivePGPObject.h" +#import "PGPKey.h" +#import "PGPKeyGenerator.h" +#import "PGPKeyMaterial.h" +#import "PGPTypes.h" +#import "PGPArmor.h" +#import "PGPCompressedPacket.h" +#import "PGPCryptoCFB.h" +#import "PGPLiteralPacket.h" +#import "PGPLogging.h" +#import "PGPModificationDetectionCodePacket.h" +#import "PGPOnePassSignaturePacket.h" +#import "PGPSignaturePacket.h" +#import "PGPSignatureSubpacket.h" +#import "PGPSignatureSubpacketHeader.h" +#import "PGPSignatureSubpacketCreationTime.h" +#import "PGPPKCSEme.h" +#import "PGPPKCSEmsa.h" +#import "PGPPublicKeyEncryptedSessionKeyPacket.h" +#import "PGPPublicKeyPacket.h" +#import "PGPPublicSubKeyPacket.h" +#import "PGPSecretKeyPacket.h" +#import "PGPSecretSubKeyPacket.h" +#import "PGPPartialSubKey.h" +#import "PGPSymmetricallyEncryptedDataPacket.h" +#import "PGPSymmetricallyEncryptedDataPacket.h" +#import "PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h" +#import "PGPTrustPacket.h" +#import "PGPUser.h" +#import "PGPUserAttributePacket.h" +#import "PGPUserIDPacket.h" +#import "PGPPacketProtocol.h" diff --git a/enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.h b/enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.h new file mode 100644 index 00000000..4462e681 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.h @@ -0,0 +1,169 @@ +// +// ObjectivePGP.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 03/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPKey.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/// ObjectivePGP main class. +@interface ObjectivePGP : NSObject + +/// Imported keys. +@property (strong, nonatomic, readonly) NSSet<PGPKey *> *keys; + +/* + Import keys. `keys` property is updated after successfull import. + + @param path keys to load. + @return Set of loaded keys. +*/ +- (NSSet<PGPKey *> *)importKeys:(NSSet<PGPKey *> *)keys; + +/** + Import keys from the file. `keys` property is updated after successfull import. + + @param path Path to the file with the keys. + @return Set of loaded keys. + */ +- (NSSet<PGPKey *> *)importKeysFromFile:(NSString *)path; + +/** + Import keys from the data. `keys` property is updated after successfull import. + + @param data Keys data. + @return Set of loaded keys. + */ +- (NSSet<PGPKey *> *)importKeysFromData:(NSData *)data; + +/** + Delete keys + + @param keys Keys to delete from keys object +*/ +- (void)deleteKeys:(NSArray<PGPKey *> *)keys; + +/** + Import key with given identifier + + @param shortKeyStringIdentifier Short (8 characters) key identifier to load. + @param path Path to the file with the keys. + @return YES on success. + */ +- (BOOL)importKey:(NSString *)shortKeyStringIdentifier fromFile:(NSString *)path; + +/** + Read keys from the data. Does not import the keys. + + @param fileData Keys data. + @return Array of parsed keys. + */ +- (NSSet<PGPKey *> *)keysFromData:(NSData *)fileData; + +/** + Read keys from the file. Does not import the keys. + + @param path Path to the keys file. + @return Array of parsed keys. + */ +- (NSSet<PGPKey *> *)keysFromFile:(NSString *)path; + +/** + Save keys of given type (public or private) to the file. + + @param type Keys type. + @param path Full path to the destination file. + @param error Error. + @return YES on success. + */ +- (BOOL)exportKeysOfType:(PGPPartialKeyType)type toFile:(NSString *)path error:(NSError *__autoreleasing _Nullable *)error; + +/** + Export key data. + + @param key Key to export. + @param armored Choose the format. Binary or Armored (armored is a string based format) + @return Data or `nil` if can't export key. + */ +- (nullable NSData *)exportKey:(PGPKey *)key armored:(BOOL)armored; + +/** + Search for string based key identifier. + + @param keyIdentifier Key identifier. Short (8 characters, e.g: 4EF122E5) or long (16 characters, e.g: 71180E514EF122E5) identifier. + @return Key instance, or `nil` if not found. + */ +- (nullable PGPKey *)findKeyForIdentifier:(NSString *)keyIdentifier; + +/** + Search for key id. + + @param keyID Key identifier. + @return Key instance or `nil` if not found. + */ +- (nullable PGPKey *)findKeyForKeyID:(PGPKeyID *)keyID; + +/** + Search for keys for given user id. + + @param userID A string based identifier (usually name with the e-mail address). + @return Array of found keys, or empty array if not found. + */ +- (NSSet<PGPKey *> *)findKeysForUserID:(NSString *)userID; + +/** + Sign data using a key. + + @param dataToSign Data to sign. + @param key Key to be used to sign. + @param passphrase Optional. Passphrase for the key. + @param detached whether output detached signature. + @param error Error. + @return Signed data, or `nil` if fail. + */ +- (nullable NSData *)signData:(NSData *)dataToSign usingKey:(PGPKey *)key passphrase:(nullable NSString *)passphrase detached:(BOOL)detached error:(NSError *__autoreleasing _Nullable *)error; + +/** + Verify signed data. Validates with the imported keys. + + @param signedData Signed data. + @param error Error + @return YES on success. + */ +- (BOOL)verifyData:(NSData *)signedData error:(NSError *__autoreleasing _Nullable *)error; + +/** + Verify signed data, with detached signature data. + + @param signedData Signed data. + @param signatureData Detached signature data. + @param error Error + @return YES on success. + */ +- (BOOL)verifyData:(NSData *)signedData withSignature:(NSData *)signatureData error:(NSError *__autoreleasing _Nullable *)error; + +/** + Verify signed data using given key. + + @param signedData Signed data. + @param signatureData Detached signature data. + @param key Key to use. + @param error Error. + @return YES on success. + */ +- (BOOL)verifyData:(NSData *)signedData withSignature:(NSData *)signatureData usingKey:(PGPKey *)key error:(NSError *__autoreleasing _Nullable *)error; + +- (nullable NSData *)encryptData:(NSData *)dataToEncrypt usingKeys:(NSArray<PGPKey *> *)keys armored:(BOOL)armored error:(NSError *__autoreleasing _Nullable *)error; +- (nullable NSData *)encryptData:(NSData *)dataToEncrypt usingKeys:(NSArray<PGPKey *> *)keys signWithKey:(nullable PGPKey *)signKey passphrase:(nullable NSString *)passphrase armored:(BOOL)armored error:(NSError *__autoreleasing _Nullable *)error; + +- (nullable NSData *)decryptData:(NSData *)messageDataToDecrypt passphrase:(nullable NSString *)passphrase error:(NSError *__autoreleasing _Nullable *)error; +- (nullable NSData *)decryptData:(NSData *)messageDataToDecrypt passphrase:(nullable NSString *)passphrase verifyWithKey:(nullable PGPKey *)key signed:(nullable BOOL *)isSigned valid:(nullable BOOL *)isValid integrityProtected:(nullable BOOL *)isIntegrityProtected error:(NSError *__autoreleasing _Nullable *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.m b/enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.m new file mode 100644 index 00000000..e3ed7884 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/ObjectivePGPObject.m @@ -0,0 +1,905 @@ +// +// ObjectivePGPObject.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 03/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "ObjectivePGPObject.h" +#import "PGPArmor.h" +#import "PGPCompressedPacket.h" +#import "PGPCryptoUtils.h" +#import "PGPKey+Private.h" +#import "PGPKey.h" +#import "PGPLiteralPacket.h" +#import "PGPMPI.h" +#import "PGPModificationDetectionCodePacket.h" +#import "PGPOnePassSignaturePacket.h" +#import "PGPPacketFactory.h" +#import "PGPPartialKey.h" +#import "PGPPublicKeyEncryptedSessionKeyPacket.h" +#import "PGPPublicKeyPacket.h" +#import "PGPSecretKeyPacket.h" +#import "PGPSignaturePacket.h" +#import "PGPPartialSubKey.h" +#import "PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h" +#import "PGPUser.h" +#import "PGPUserIDPacket.h" +#import "NSMutableData+PGPUtils.h" +#import "NSMutableArray+PGPUtils.h" + +#import "PGPFoundation.h" +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ObjectivePGP () + +@property (strong, nonatomic, readwrite) NSSet<PGPKey *> *keys; + +@end + +@implementation ObjectivePGP + +- (instancetype)init { + if ((self = [super init])) { + _keys = [NSMutableSet<PGPKey *> set]; + } + return self; +} + +#pragma mark - Search + +- (NSSet<PGPKey *> *)findKeysForUserID:(nonnull NSString *)userID { + return [self.keys objectsPassingTest:^BOOL(PGPKey *key, __unused BOOL *stop1) { + let a = key.publicKey ? [key.publicKey.users indexOfObjectPassingTest:^BOOL(PGPUser *user, __unused NSUInteger idx, __unused BOOL *stop2) { + return [userID isEqual:user.userID]; + }] : NSNotFound; + + let b = key.secretKey ? [key.secretKey.users indexOfObjectPassingTest:^BOOL(PGPUser *user, __unused NSUInteger idx, __unused BOOL *stop2) { + return [userID isEqual:user.userID]; + }] : NSNotFound; + + return (a != NSNotFound) || (b != NSNotFound); + }]; +} + +- (nullable PGPKey *)findKeyForKeyID:(PGPKeyID *)searchKeyID { + PGPAssertClass(searchKeyID, PGPKeyID); + + return [[self.keys objectsPassingTest:^BOOL(PGPKey *key, BOOL *stop) { + // top-level keys + __block BOOL found = (key.publicKey && [key.publicKey.keyID isEqual:searchKeyID]); + if (!found) { + found = (key.secretKey && [key.secretKey.keyID isEqual:searchKeyID]); + } + + // subkeys + if (!found && key.publicKey.subKeys.count > 0) { + found = [key.publicKey.subKeys indexOfObjectPassingTest:^BOOL(PGPPartialSubKey *subkey, __unused NSUInteger idx, BOOL *stop2) { + *stop2 = [subkey.keyID isEqual:searchKeyID]; + return *stop2; + }] != NSNotFound; + } + + if (!found && key.secretKey.subKeys.count > 0) { + found = [key.secretKey.subKeys indexOfObjectPassingTest:^BOOL(PGPPartialSubKey *subkey, __unused NSUInteger idx, BOOL *stop2) { + *stop2 = [subkey.keyID isEqual:searchKeyID]; + return *stop2; + }] != NSNotFound; + } + + *stop = found; + return found; + }] anyObject]; +} + +// TODO: rename to getKeyForFingerprint or something +- (nullable PGPKey *)findKeyForIdentifier:(NSString *)keyIdentifier { + PGPAssertClass(keyIdentifier, NSString); + + if (keyIdentifier.length != 8 && keyIdentifier.length != 16) { + PGPLogDebug(@"Invalid key identifier: %@", keyIdentifier); + return nil; + } + + BOOL useShortIdentifier = keyIdentifier.length == 8; + + // public + for (PGPKey *key in self.keys) { + if (key.publicKey) { + let identifier = useShortIdentifier ? key.publicKey.keyID.shortKeyString : key.publicKey.keyID.longKeyString; + if ([identifier.uppercaseString isEqual:keyIdentifier.uppercaseString]) { + return key; + } + + for (PGPPartialSubKey *subkey in key.publicKey.subKeys) { + let subIdentifier = useShortIdentifier ? subkey.keyID.shortKeyString : subkey.keyID.longKeyString; + if ([subIdentifier.uppercaseString isEqual:keyIdentifier.uppercaseString]) { + return key; + } + } + } + + if (key.secretKey) { + let identifier = useShortIdentifier ? key.secretKey.keyID.shortKeyString : key.secretKey.keyID.longKeyString; + if ([identifier.uppercaseString isEqual:keyIdentifier.uppercaseString]) { + return key; + } + + for (PGPPartialSubKey *subkey in key.secretKey.subKeys) { + let subIdentifier = useShortIdentifier ? subkey.keyID.shortKeyString : subkey.keyID.longKeyString; + if ([subIdentifier.uppercaseString isEqual:keyIdentifier.uppercaseString]) { + return key; + } + } + } + } + + return nil; +} + +#pragma mark - Save + +- (BOOL)exportKeysOfType:(PGPPartialKeyType)type toFile:(NSString *)path error:(NSError *__autoreleasing *)error { + let exportKeys = [NSMutableArray<PGPPartialKey *> array]; + for (PGPKey *key in self.keys) { + if (type == PGPPartialKeyPublic && key.publicKey) { + [exportKeys addObject:key.publicKey]; + } + if (type == PGPPartialKeySecret && key.secretKey) { + [exportKeys addObject:key.secretKey]; + } + } + return [self exportKeys:exportKeys toFile:path error:error]; +} + +- (BOOL)exportKeys:(NSArray<PGPPartialKey *> *)keys toFile:(NSString *)path error:(NSError *__autoreleasing *)error { + NSParameterAssert(keys); + PGPAssertClass(path, NSString); + + if (keys.count == 0) { + return NO; + } + + for (PGPPartialKey *key in keys) { + if (![self appendKey:key toKeyring:path error:error]) { + return NO; + } + } + return YES; +} + +- (BOOL)appendKey:(PGPPartialKey *)key toKeyring:(NSString *)path error:(NSError *__autoreleasing *)error { + NSFileManager *fm = [NSFileManager defaultManager]; + + if (!path) { + return NO; + } + + let keyData = [key export:error]; + if (!keyData) { + return NO; + } + + BOOL result = NO; + if (![fm fileExistsAtPath:path]) { + NSDictionary *attributes = nil; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + attributes = @{ NSFileProtectionKey: NSFileProtectionComplete, NSFilePosixPermissions: @(0600) }; +#else + attributes = @{ NSFilePosixPermissions: @(0600) }; +#endif + result = [fm createFileAtPath:path contents:keyData attributes:attributes]; + } else { + @try { + NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:path]; + [fileHandle seekToEndOfFile]; + [fileHandle writeData:keyData]; + [fileHandle closeFile]; + result = YES; + } @catch (NSException *exception) { + result = NO; + } + } + return result; +} + +- (nullable NSData *)exportKey:(PGPKey *)key armored:(BOOL)armored { + PGPAssertClass(key, PGPKey); + + NSError *exportError = nil; + NSData *keyData = [key export:&exportError]; + if (!keyData || exportError) { + PGPLogDebug(@"%@", exportError); + return nil; + } + + if (armored) { + return [PGPArmor armoredData:keyData as:PGPArmorTypePublicKey]; + } else { + return keyData; + } + return nil; +} + +#pragma mark - Delete + +- (void)deleteKeys:(NSArray<PGPKey *> *)keys { + PGPAssertClass(keys, NSArray); + + let allKeys = [NSMutableSet<PGPKey *> setWithSet:self.keys]; + for (PGPKey *key in keys) { + [allKeys removeObject:key]; + } + self.keys = allKeys; +} + +#pragma mark - Encrypt & Decrypt + +- (nullable NSData *)decryptData:(NSData *)messageDataToDecrypt passphrase:(nullable NSString *)passphrase error:(NSError *__autoreleasing *)error { + return [self decryptData:messageDataToDecrypt passphrase:passphrase verifyWithKey:nil signed:nil valid:nil integrityProtected:nil error:error]; +} + +- (nullable NSData *)decryptData:(NSData *)messageDataToDecrypt passphrase:(nullable NSString *)passphrase verifyWithKey:(nullable PGPKey *)key signed:(nullable BOOL *)isSigned valid:(nullable BOOL *)isValid integrityProtected:(nullable BOOL *)isIntegrityProtected error:(NSError *__autoreleasing _Nullable *)error { + PGPAssertClass(messageDataToDecrypt, NSData); + let binaryMessages = [self convertArmoredMessage2BinaryBlocksWhenNecessary:messageDataToDecrypt]; + + // decrypt first message only + let binaryMessageToDecrypt = binaryMessages.count > 0 ? binaryMessages.firstObject : nil; + if (!binaryMessageToDecrypt) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Invalid input data" }]; + } + return nil; + } + + // parse packets + var packets = [self readPacketsFromData:binaryMessageToDecrypt]; + + PGPSymmetricAlgorithm sessionKeyAlgorithm = PGPSymmetricPlaintext; + PGPSecretKeyPacket *decryptionSecretKeyPacket = nil; // last found secret key to used to decrypt + + // 1. search for valid and known (do I have specified key?) ESK + PGPPublicKeyEncryptedSessionKeyPacket *eskPacket = nil; + for (PGPPacket *packet in packets) { + if (packet.tag == PGPPublicKeyEncryptedSessionKeyPacketTag) { + let pkESKPacket = PGPCast(packet, PGPPublicKeyEncryptedSessionKeyPacket); + let decryptionKey = [self findKeyForKeyID:pkESKPacket.keyID]; + if (!decryptionKey.secretKey) { + continue; + } + + decryptionSecretKeyPacket = PGPCast([decryptionKey.secretKey decryptionKeyPacketWithID:pkESKPacket.keyID error:error], PGPSecretKeyPacket); + if (!decryptionSecretKeyPacket) { + continue; + } + + // decrypt key with passphrase if encrypted + if (decryptionSecretKeyPacket.isEncryptedWithPassphrase) { + if (!passphrase) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorPassphraseRequired userInfo:@{ NSLocalizedDescriptionKey: @"Passphrase is required for a key" }]; + } + return nil; + } + + decryptionSecretKeyPacket = [decryptionSecretKeyPacket decryptedKeyPacket:passphrase error:error]; + if (!decryptionSecretKeyPacket || (error && *error)) { + decryptionSecretKeyPacket = nil; + continue; + } + } + eskPacket = pkESKPacket; + } + } + + if (error && *error) { + return nil; + } + + if (!eskPacket) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Valid PublicKeyEncryptedSessionKeyPacket not found" }]; + } + return nil; + } + + if (!decryptionSecretKeyPacket) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Unable to find valid secret key" }]; + } + return nil; + } + + let sessionKeyData = [eskPacket decryptSessionKeyData:decryptionSecretKeyPacket sessionKeyAlgorithm:&sessionKeyAlgorithm error:error]; + NSAssert(sessionKeyAlgorithm > 0, @"Invalid session key algorithm"); + + NSAssert(sessionKeyData, @"Missing session key data"); + if (!sessionKeyData) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Missing session key data" }]; + } + return nil; + } + + // 2 + for (PGPPacket *packet in packets) { + switch (packet.tag) { + case PGPSymmetricallyEncryptedIntegrityProtectedDataPacketTag: { + // decrypt PGPSymmetricallyEncryptedIntegrityProtectedDataPacket + let symEncryptedDataPacket = PGPCast(packet, PGPSymmetricallyEncryptedIntegrityProtectedDataPacket); + packets = [symEncryptedDataPacket decryptWithSecretKeyPacket:decryptionSecretKeyPacket sessionKeyAlgorithm:sessionKeyAlgorithm sessionKeyData:sessionKeyData isIntegrityProtected:isIntegrityProtected error:error]; + } break; + default: + break; + } + } + + if (packets.count == 0) { + return nil; + } + + PGPLiteralPacket * _Nullable literalPacket = nil; + PGPSignaturePacket * _Nullable signaturePacket = nil; + for (PGPPacket *packet in packets) { + switch (packet.tag) { + case PGPCompressedDataPacketTag: + case PGPOnePassSignaturePacketTag: + // ignore here + break; + case PGPLiteralDataPacketTag: + literalPacket = PGPCast(packet, PGPLiteralPacket); + break; + case PGPSignaturePacketTag: + signaturePacket = PGPCast(packet, PGPSignaturePacket); + break; + default: + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Unknown packet (expected literal or compressed)" }]; + } + return nil; + } + } + + BOOL dataIsSigned = signaturePacket != nil; + if (isSigned) { *isSigned = dataIsSigned; } + + // available if literalPacket is available + let _Nullable plaintextData = literalPacket.literalRawData; + if (!plaintextData) { + return nil; + } + + BOOL dataIsValid = NO; + if (signaturePacket && key.publicKey) { + let signatureData = [signaturePacket export:error]; + if (signatureData) { + dataIsValid = [self verifyData:plaintextData withSignature:signatureData usingKey:key error:nil]; + } + } + if (isValid) { *isValid = dataIsValid; } + + return plaintextData; +} + +- (nullable NSData *)encryptData:(NSData *)dataToEncrypt usingKeys:(NSArray<PGPKey *> *)keys armored:(BOOL)armored error:(NSError *__autoreleasing _Nullable *)error { + return [self encryptData:dataToEncrypt usingKeys:keys signWithKey:nil passphrase:nil armored:armored error:error]; +} + +- (nullable NSData *)encryptData:(NSData *)dataToEncrypt usingKeys:(NSArray<PGPKey *> *)keys signWithKey:(nullable PGPKey *)signKey passphrase:(nullable NSString *)passphrase armored:(BOOL)armored error:(NSError *__autoreleasing _Nullable *)error { + let publicKeys = [NSMutableArray<PGPPartialKey *> array]; + for (PGPKey *key in keys) { + [publicKeys addObject:key.publicKey]; + } + + let encryptedMessage = [NSMutableData data]; + + // PGPPublicKeyEncryptedSessionKeyPacket goes here + let preferredSymmeticAlgorithm = [PGPPartialKey preferredSymmetricAlgorithmForKeys:publicKeys]; + + // Random bytes as a string to be used as a key + NSUInteger keySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:preferredSymmeticAlgorithm]; + uint8_t buf[keySize]; + if (SecRandomCopyBytes(kSecRandomDefault, keySize, buf) == -1) { + //TODO: error + return nil; + } + + let sessionKeyData = [NSMutableData dataWithBytes:buf length:keySize]; + + for (PGPPartialKey *publicKey in publicKeys) { + // Encrypted Message :- Encrypted Data | ESK Sequence, Encrypted Data. + // Encrypted Data :- Symmetrically Encrypted Data Packet | Symmetrically Encrypted Integrity Protected Data Packet + // ESK :- Public-Key Encrypted Session Key Packet | Symmetric-Key Encrypted Session Key Packet. + + // ESK + let encryptionKeyPacket = PGPCast([publicKey encryptionKeyPacket:error], PGPPublicKeyPacket); + if (!encryptionKeyPacket) { + continue; + } + + // var pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey(); + PGPPublicKeyEncryptedSessionKeyPacket *eskKeyPacket = [[PGPPublicKeyEncryptedSessionKeyPacket alloc] init]; + eskKeyPacket.keyID = encryptionKeyPacket.keyID; + eskKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.publicKeyAlgorithm; + [eskKeyPacket encrypt:encryptionKeyPacket sessionKeyData:sessionKeyData sessionKeyAlgorithm:preferredSymmeticAlgorithm error:error]; + PGPLogWarning(@"Missing literal data"); + if (error && *error) { + return nil; + } + [encryptedMessage pgp_appendData:[eskKeyPacket export:error]]; + if (error && *error) { + return nil; + } + } + + NSData *content; + // sign data if requested + if (signKey) { + content = [self signData:dataToEncrypt usingKey:signKey passphrase:passphrase hashAlgorithm:PGPHashSHA512 detached:NO error:error]; + if (error && *error) { + return nil; + } + + } else { + // Prepare literal packet + let literalPacket = [PGPLiteralPacket literalPacket:PGPLiteralPacketBinary withData:dataToEncrypt]; + literalPacket.filename = nil; + literalPacket.timestamp = [NSDate date]; + PGPLogWarning(@"Missing literal data"); + if (error && *error) { + return nil; + } + let literalPacketData = [literalPacket export:error]; + if (error && *error) { + return nil; + } + + let compressedPacket = [[PGPCompressedPacket alloc] initWithData:literalPacketData type:PGPCompressionBZIP2]; + content = [compressedPacket export:error]; + if (error && *error) { + return nil; + } + } + + let symEncryptedDataPacket = [[PGPSymmetricallyEncryptedIntegrityProtectedDataPacket alloc] init]; + [symEncryptedDataPacket encrypt:content symmetricAlgorithm:preferredSymmeticAlgorithm sessionKeyData:sessionKeyData error:error]; + + if (error && *error) { + return nil; + } + + [encryptedMessage pgp_appendData:[symEncryptedDataPacket export:error]]; + if (error && *error) { + return nil; + } + + if (armored) { + return [PGPArmor armoredData:encryptedMessage as:PGPArmorTypeMessage]; + } + + return encryptedMessage; +} + +#pragma mark - Sign & Verify + +- (nullable NSData *)signData:(NSData *)dataToSign usingKey:(PGPKey *)key passphrase:(nullable NSString *)passphrase detached:(BOOL)detached error:(NSError *__autoreleasing *)error { + // TODO: configurable defaults for prefered hash + return [self signData:dataToSign usingKey:key passphrase:passphrase hashAlgorithm:PGPHashSHA512 detached:detached error:error]; +} + +- (nullable NSData *)signData:(NSData *)dataToSign usingKey:(PGPKey *)key passphrase:(nullable NSString *)passphrase hashAlgorithm:(PGPHashAlgorithm)preferedHashAlgorithm detached:(BOOL)detached error:(NSError *__autoreleasing *)error { + PGPAssertClass(dataToSign, NSData); + PGPAssertClass(key, PGPKey); + + let signaturePacket = [PGPSignaturePacket signaturePacket:PGPSignatureBinaryDocument hashAlgorithm:preferedHashAlgorithm]; + if (![signaturePacket signData:dataToSign withKey:key subKey:nil passphrase:passphrase userID:nil error:error]) { + PGPLogDebug(@"Can't sign data"); + return nil; + } + + NSError *exportError = nil; + let _Nullable signaturePacketData = [signaturePacket export:&exportError]; + if (exportError) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Error on export packet" }]; + } + return nil; + } + + // Signed Message :- Signature Packet, Literal Message + NSMutableData *signedMessage = [NSMutableData data]; + if (!detached) { + // OnePass + PGPOnePassSignaturePacket *onePassPacket = [[PGPOnePassSignaturePacket alloc] init]; + onePassPacket.signatureType = signaturePacket.type; + onePassPacket.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; + onePassPacket.hashAlgorith = signaturePacket.hashAlgoritm; + + onePassPacket.keyID = [signaturePacket issuerKeyID]; + + onePassPacket.notNested = YES; + NSError *onePassExportError = nil; + [signedMessage pgp_appendData:[onePassPacket export:&onePassExportError]]; + NSAssert(!onePassExportError, @"Missing one passphrase data"); + if (onePassExportError) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing one passphrase data" }]; + } + return nil; + } + + // Literal + PGPLiteralPacket *literalPacket = [PGPLiteralPacket literalPacket:PGPLiteralPacketBinary withData:dataToSign]; + literalPacket.filename = nil; + literalPacket.timestamp = [NSDate date]; + + NSError *literalExportError = nil; + [signedMessage pgp_appendData:[literalPacket export:&literalExportError]]; + NSAssert(!literalExportError, @"Missing literal data"); + if (literalExportError) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing literal data" }]; + } + return nil; + } + + // // Compressed + // NSError *literalExportError = nil; + // PGPCompressedPacket *compressedPacket = [[PGPCompressedPacket alloc] initWithData:[literalPacket exportPacket:&literalExportError] type:PGPCompressionBZIP2]; + // NSAssert(!literalExportError, @"Missing literal data"); + // if (literalExportError) { + // if (error) { + // *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing literal data"}]; + // } + // return nil; + // } + // + // NSError *compressedExportError = nil; + // [signedMessage pgp_appendData:[compressedPacket exportPacket:&compressedExportError]]; + // NSAssert(!compressedExportError, @"Missing compressed data"); + // if (compressedExportError) { + // if (error) { + // *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{NSLocalizedDescriptionKey: @"Missing compressed data"}]; + // } + // return nil; + // } + } + [signedMessage pgp_appendData:signaturePacketData]; + return signedMessage; +} + +- (BOOL)verifyData:(NSData *)signedData withSignature:(NSData *)signatureData error:(NSError *__autoreleasing _Nullable *)error { + PGPAssertClass(signedData, NSData); + PGPAssertClass(signatureData, NSData); + + // search for key in keys + let packet = [PGPPacketFactory packetWithData:signatureData offset:0 nextPacketOffset:NULL]; + if (![packet isKindOfClass:[PGPSignaturePacket class]]) { + PGPLogWarning(@"Missing key signature"); + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing signature packet" }]; + } + return NO; + } + + let signaturePacket = PGPCast(packet, PGPSignaturePacket); + if (!signaturePacket) { + return NO; + } + + let issuerKeyID = [signaturePacket issuerKeyID]; + + let issuerKey = [self findKeyForKeyID:issuerKeyID]; + if (!issuerKey) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing issuer" }]; + } + return NO; + } + + return [self verifyData:signedData withSignature:signatureData usingKey:issuerKey error:error]; +} + +- (BOOL)verifyData:(NSData *)signedData withSignature:(NSData *)signatureData usingKey:(PGPKey *)key error:(NSError *__autoreleasing _Nullable *)error { + PGPAssertClass(signedData, NSData); + PGPAssertClass(signedData, NSData); + PGPAssertClass(key, PGPKey); + + let packet = [PGPPacketFactory packetWithData:signatureData offset:0 nextPacketOffset:NULL]; + if (![packet isKindOfClass:[PGPSignaturePacket class]]) { + NSAssert(false, @"need signature"); + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing signature" }]; + } + return NO; + } + + let signaturePacket = PGPCast(packet, PGPSignaturePacket); + if (!signaturePacket) { + return NO; + } + BOOL verified = [signaturePacket verifyData:signedData withKey:key userID:nil error:error]; + + return verified; +} + +- (BOOL)verifyData:(NSData *)signedDataPackets error:(NSError *__autoreleasing *)error { + // this is propably not the best solution when it comes to memory consumption + // because literal data is copied more than once (first at parse phase, then when is come to build signature packet data + // I belive this is unecessary but require more work. Schedule to v2.0 + @autoreleasepool { + // search for signature packet + let accumulatedPackets = [NSMutableArray<PGPPacket *> array]; + NSUInteger offset = 0; + NSUInteger nextPacketOffset; + // TODO: dont parse data here, get raw data and pass to verifyData:withsignature: + while (offset < signedDataPackets.length) { + let packet = [PGPPacketFactory packetWithData:signedDataPackets offset:offset nextPacketOffset:&nextPacketOffset]; + [accumulatedPackets pgp_addObject:packet]; + + offset += nextPacketOffset; + } + + PGPSignaturePacket *signaturePacket = nil; + PGPLiteralPacket *literalDataPacket = nil; + + for (PGPPacket *packet in accumulatedPackets) { + if (packet.tag == PGPSignaturePacketTag) { + signaturePacket = PGPCast(packet, PGPSignaturePacket); + } + if (packet.tag == PGPLiteralDataPacketTag) { + literalDataPacket = PGPCast(packet, PGPLiteralPacket); + } + } + + NSAssert(signaturePacket && literalDataPacket, @"Missing signature packet or literal data packet"); + if (!signaturePacket || !literalDataPacket) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing signature packet or literal data packet" }]; + } + return NO; + } + + let signaturePacketData = [signaturePacket export:error]; + + if (signaturePacketData && (!error || (error && *error == nil))) { + return [self verifyData:literalDataPacket.literalRawData withSignature:signaturePacketData error:error]; + } + return NO; + } +} + +#pragma mark - Parse keyring + +/** + * Load keyring file (secring or pubring) + * + * @param path Path to file + * + * @return YES on success + */ +- (NSSet<PGPKey *> *)importKeysFromFile:(NSString *)path { + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + return [NSSet<PGPKey *> set]; + } + + return [self importKeysFromData:[NSData dataWithContentsOfFile:path options:NSDataReadingMappedIfSafe error:nil]]; +} + +- (NSSet<PGPKey *> *)importKeysFromData:(NSData *)data { + PGPAssertClass(data, NSData); + + let loadedKeys = [self keysFromData:data]; + return [self importKeys:loadedKeys]; +} + +- (NSSet<PGPKey *> *)importKeys:(NSSet<PGPKey *> *)keys { + PGPAssertClass(keys, NSSet); + + for (PGPKey *key in keys) { + self.keys = [self addOrUpdateCompoundKeyForKey:key.secretKey inContainer:self.keys]; + self.keys = [self addOrUpdateCompoundKeyForKey:key.publicKey inContainer:self.keys]; + } + return self.keys; +} + +- (BOOL)importKey:(NSString *)shortKeyStringIdentifier fromFile:(NSString *)path { + let fullPath = [path stringByExpandingTildeInPath]; + + let loadedKeys = [self keysFromFile:fullPath]; + if (loadedKeys.count == 0) { + return NO; + } + + let foundKey = [[loadedKeys objectsPassingTest:^BOOL(PGPKey *key, BOOL *stop) { + *stop = [key.publicKey.keyID.shortKeyString.uppercaseString isEqualToString:shortKeyStringIdentifier.uppercaseString] || [key.secretKey.keyID.shortKeyString.uppercaseString isEqualToString:shortKeyStringIdentifier.uppercaseString]; + return *stop; + + }] anyObject]; + + if (!foundKey) { + return NO; + } + + self.keys = [self.keys setByAddingObject:foundKey]; + + return YES; +} + +- (NSSet<PGPKey *> *)keysFromFile:(NSString *)path { + NSString *fullPath = [path stringByExpandingTildeInPath]; + + BOOL isDirectory = NO; + if (![[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory] || isDirectory) { + return [NSSet<PGPKey *> set]; + } + + NSError *error = nil; + NSData *fileData = [NSData dataWithContentsOfFile:fullPath options:NSDataReadingMappedIfSafe | NSDataReadingUncached error:&error]; + if (!fileData || error) { + return [NSSet<PGPKey *> set]; + } + + return [self keysFromData:fileData]; +} + +- (NSSet<PGPKey *> *)keysFromData:(NSData *)fileData { + PGPAssertClass(fileData, NSData); + + var keys = [NSSet<PGPKey *> set]; + + if (fileData.length == 0) { + PGPLogError(@"Empty input data"); + return keys; + }; + + let binRingData = [self convertArmoredMessage2BinaryBlocksWhenNecessary:fileData]; + if (!binRingData || binRingData.count == 0) { + PGPLogError(@"Invalid input data"); + return keys; + } + + for (NSData *data in binRingData) { + let readPartialKeys = [self readPartialKeysFromData:data]; + for (PGPPartialKey *key in readPartialKeys) { + keys = [self addOrUpdateCompoundKeyForKey:key inContainer:keys]; + } + } + + return keys; +} + +#pragma mark - Private + +- (NSArray<PGPPacket *> *)readPacketsFromData:(NSData *)keyringData { + PGPAssertClass(keyringData, NSData); + + if (keyringData.length == 0) { + return @[]; + } + + let accumulatedPackets = [NSMutableArray<PGPPacket *> array]; + NSUInteger offset = 0; + NSUInteger nextPacketOffset = 0; + + while (offset < keyringData.length) { + let packet = [PGPPacketFactory packetWithData:keyringData offset:offset nextPacketOffset:&nextPacketOffset]; + [accumulatedPackets pgp_addObject:packet]; + + // corrupted data. Move by one byte in hope we find some packet there, or EOF. + if (nextPacketOffset == 0) { + offset++; + } + offset += nextPacketOffset; + } + + return accumulatedPackets; +} + +// Add or update compound key. Returns updated set. +- (NSSet<PGPKey *> *)addOrUpdateCompoundKeyForKey:(nullable PGPPartialKey *)key inContainer:(NSSet<PGPKey *> *)compoundKeys { + if (!key) { + return compoundKeys; + } + + NSMutableSet *updatedContainer = [NSMutableSet<PGPKey *> setWithSet:compoundKeys]; + + let foundCompoundKey = [[compoundKeys objectsPassingTest:^BOOL(PGPKey *obj, BOOL *stop) { + *stop = [obj.publicKey.keyID isEqual:key.keyID] || [obj.secretKey.keyID isEqual:key.keyID]; + return *stop; + }] anyObject]; + + if (!foundCompoundKey) { + let compoundKey = [[PGPKey alloc] initWithSecretKey:(key.type == PGPPartialKeySecret ? key : nil) publicKey:(key.type == PGPPartialKeyPublic ? key : nil)]; + [updatedContainer addObject:compoundKey]; + } else { + if (key.type == PGPPartialKeyPublic) { + foundCompoundKey.publicKey = key; + } + if (key.type == PGPPartialKeySecret) { + foundCompoundKey.secretKey = key; + } + } + + return updatedContainer; +} + +- (NSSet<PGPPartialKey *> *)readPartialKeysFromData:(NSData *)messageData { + let keys = [NSMutableSet<PGPPartialKey *> set]; + let accumulatedPackets = [NSMutableArray<PGPPacket *> array]; + NSUInteger position = 0; + NSUInteger nextPacketPosition = 0; + + while (position < messageData.length) { + let packet = [PGPPacketFactory packetWithData:messageData offset:position nextPacketOffset:&nextPacketPosition]; + if (!packet) { + position += (nextPacketPosition > 0) ? nextPacketPosition : 1; + continue; + } + + if ((accumulatedPackets.count > 1) && ((packet.tag == PGPPublicKeyPacketTag) || (packet.tag == PGPSecretKeyPacketTag))) { + let key = [[PGPPartialKey alloc] initWithPackets:accumulatedPackets]; + [keys addObject:key]; + [accumulatedPackets removeAllObjects]; + } + + [accumulatedPackets pgp_addObject:packet]; + position += nextPacketPosition; + } + + if (accumulatedPackets.count > 1) { + let key = [[PGPPartialKey alloc] initWithPackets:accumulatedPackets]; + [keys addObject:key]; + [accumulatedPackets removeAllObjects]; + } + + return keys; +} + +- (NSArray<NSData *> *)convertArmoredMessage2BinaryBlocksWhenNecessary:(NSData *)binOrArmorData { + NSData *binRingData = binOrArmorData; + // detect if armored, check for strin -----BEGIN PGP + if ([PGPArmor isArmoredData:binRingData]) { + NSError *deadmorError = nil; + NSString *armoredString = [[NSString alloc] initWithData:binRingData encoding:NSUTF8StringEncoding]; + + // replace \n to \r\n + // propably unecessary since armore code care about \r\n or \n as newline sentence + armoredString = [armoredString stringByReplacingOccurrencesOfString:@"\r\n" withString:@"\n"]; + armoredString = [armoredString stringByReplacingOccurrencesOfString:@"\n" withString:@"\r\n"]; + + NSMutableArray *extractedBlocks = [[NSMutableArray alloc] init]; + NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:@"(-----)(BEGIN|END)[ ](PGP)[A-Z ]*(-----)" options:NSRegularExpressionDotMatchesLineSeparators error:nil]; + __block NSInteger offset = 0; + [regex enumerateMatchesInString:armoredString options:NSMatchingReportCompletion range:NSMakeRange(0, armoredString.length) usingBlock:^(NSTextCheckingResult *_Nullable result, __unused NSMatchingFlags flags, __unused BOOL *stop) { + NSString *substring = [armoredString substringWithRange:result.range]; + if ([substring containsString:@"END"]) { + NSInteger endIndex = result.range.location + result.range.length; + [extractedBlocks addObject:[armoredString substringWithRange:NSMakeRange(offset, endIndex - offset)]]; + } else if ([substring containsString:@"BEGIN"]) { + offset = result.range.location; + } + }]; + + let extractedData = [[NSMutableArray<NSData *> alloc] init]; + for (NSString *extractedString in extractedBlocks) { + binRingData = [PGPArmor readArmoredData:extractedString error:&deadmorError]; + if (deadmorError) { + return @[]; + } else { + [extractedData addObject:binRingData]; + } + } + + return extractedData; + } + return @[binRingData]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPArmor.h b/enzevalos_iphone/ObjectivePGP/PGPArmor.h new file mode 100644 index 00000000..542071e8 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPArmor.h @@ -0,0 +1,35 @@ +// +// PGPArmor.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 18/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +typedef NS_ENUM(NSUInteger, PGPArmorType) { + PGPArmorTypeMessage = 1, + PGPArmorTypePublicKey = 2, + PGPArmorTypeSecretKey = 3, + PGPArmorTypeMultipartMessagePartXOfY = 4, + PGPArmorTypeMultipartMessagePartX = 5, + PGPArmorTypeSignature = 6, + PGPArmorCleartextSignedMessage = 7, // TODO: -----BEGIN PGP SIGNED MESSAGE----- +}; + +NS_ASSUME_NONNULL_BEGIN + +/// ASCII Armor message. +@interface PGPArmor : NSObject + ++ (NSData *)armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType part:(NSUInteger)part of:(NSUInteger)ofParts; ++ (NSData *)armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType; + ++ (nullable NSData *)readArmoredData:(NSString *)armoredString error:(NSError *__autoreleasing _Nullable *)error; + ++ (BOOL)isArmoredData:(NSData *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPArmor.m b/enzevalos_iphone/ObjectivePGP/PGPArmor.m similarity index 80% rename from PGPArmor.m rename to enzevalos_iphone/ObjectivePGP/PGPArmor.m index 8cc9f1a0..34309d41 100644 --- a/PGPArmor.m +++ b/enzevalos_iphone/ObjectivePGP/PGPArmor.m @@ -7,14 +7,17 @@ // #import "PGPArmor.h" -#import "PGPPacket.h" #import "NSData+PGPUtils.h" +#import "PGPMacros+Private.h" +#import "PGPPacket.h" +NS_ASSUME_NONNULL_BEGIN @implementation PGPArmor -+ (BOOL) isArmoredData:(NSData *)data -{ ++ (BOOL)isArmoredData:(NSData *)data { + PGPAssertClass(data, NSData); + // detect if armored, check for string -----BEGIN PGP NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (str && [str hasPrefix:@"-----BEGIN PGP"]) { @@ -23,16 +26,12 @@ return NO; } -+ (NSData *) armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType -{ ++ (NSData *)armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType { return [[self class] armoredData:dataToArmor as:armorType part:NSUIntegerMax of:NSUIntegerMax]; } -+ (NSData *) armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType part:(NSUInteger)part of:(NSUInteger)ofParts -{ - NSMutableDictionary *headers = [@{@"Comment": @"This is a encrypted message.\nComment: Have a look at https://enzevalos.de for more information.", - @"Version": @"Created with ObjectivePGP", - @"Charset": @"UTF-8"} mutableCopy]; ++ (NSData *)armoredData:(NSData *)dataToArmor as:(PGPArmorType)armorType part:(NSUInteger)part of:(NSUInteger)ofParts { + NSMutableDictionary *headers = [@{ @"Version": @"ObjectivePGP", @"Comment": @"https://www.objectivepgp.com", @"Charset": @"UTF-8" } mutableCopy]; NSMutableString *headerString = [NSMutableString stringWithString:@"-----"]; NSMutableString *footerString = [NSMutableString stringWithString:@"-----"]; @@ -82,20 +81,20 @@ [armoredMessage appendString:@"\n"]; // - The ASCII-Armored data - NSString *radix64 = [dataToArmor base64EncodedStringWithOptions:(NSDataBase64Encoding76CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed)]; + NSString *radix64 = [dataToArmor base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed]; [armoredMessage appendString:radix64]; [armoredMessage appendString:@"\n"]; // - An Armor Checksum UInt32 checksum = [dataToArmor pgp_CRC24]; - UInt8 c[3]; // 24 bit - c[0] = checksum >> 16; - c[1] = checksum >> 8; - c[2] = checksum; + UInt8 c[3]; // 24 bit + c[0] = (UInt8)(checksum >> 16); + c[1] = (UInt8)(checksum >> 8); + c[2] = (UInt8)checksum; NSData *checksumData = [NSData dataWithBytes:&c length:sizeof(c)]; [armoredMessage appendString:@"="]; - [armoredMessage appendString:[checksumData base64EncodedStringWithOptions:(NSDataBase64Encoding76CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed)]]; + [armoredMessage appendString:[checksumData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed]]; [armoredMessage appendString:@"\n"]; // - The Armor Tail, which depends on the Armor Header Line @@ -104,45 +103,40 @@ return [armoredMessage dataUsingEncoding:NSASCIIStringEncoding]; }; -+ (NSData *) readArmoredData:(NSString *)armoredString error:(NSError * __autoreleasing *)error -{ ++ (nullable NSData *)readArmoredData:(NSString *)armoredString error:(NSError *__autoreleasing _Nullable *)error { + PGPAssertClass(armoredString, NSString); + NSScanner *scanner = [[NSScanner alloc] initWithString:armoredString]; scanner.charactersToBeSkipped = nil; // check header line NSString *headerLine = nil; [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&headerLine]; - if (![headerLine isEqualToString:@"-----BEGIN PGP MESSAGE-----"] && - ![headerLine isEqualToString:@"-----BEGIN PGP PUBLIC KEY BLOCK-----"] && - ![headerLine isEqualToString:@"-----BEGIN PGP PRIVATE KEY BLOCK-----"] && - ![headerLine isEqualToString:@"-----BEGIN PGP SECRET KEY BLOCK-----"] && // PGP 2.x generates the header "BEGIN PGP SECRET KEY BLOCK" instead of "BEGIN PGP PRIVATE KEY BLOCK" - ![headerLine isEqualToString:@"-----BEGIN PGP SIGNATURE-----"] && - ![headerLine hasPrefix:@"-----BEGIN PGP MESSAGE, PART"]) - { + if (![headerLine isEqualToString:@"-----BEGIN PGP MESSAGE-----"] && ![headerLine isEqualToString:@"-----BEGIN PGP PUBLIC KEY BLOCK-----"] && ![headerLine isEqualToString:@"-----BEGIN PGP PRIVATE KEY BLOCK-----"] && ![headerLine isEqualToString:@"-----BEGIN PGP SECRET KEY BLOCK-----"] && // PGP 2.x generates the header "BEGIN PGP SECRET KEY BLOCK" instead of "BEGIN PGP PRIVATE KEY BLOCK" + ![headerLine isEqualToString:@"-----BEGIN PGP SIGNATURE-----"] && ![headerLine hasPrefix:@"-----BEGIN PGP MESSAGE, PART"]) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Invalid header"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Invalid header" }]; } return nil; } - + // consume newline [scanner scanString:@"\r" intoString:nil]; [scanner scanString:@"\n" intoString:nil]; NSString *line = nil; - + if (![scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:nil]) { // Scan headers (Optional) [scanner scanUpToCharactersFromSet:[[NSCharacterSet newlineCharacterSet] invertedSet] intoString:nil]; - while ([scanner scanCharactersFromSet:[[NSCharacterSet newlineCharacterSet] invertedSet] intoString:&line]) - { + while ([scanner scanCharactersFromSet:[[NSCharacterSet newlineCharacterSet] invertedSet] intoString:&line]) { // consume newline [scanner scanString:@"\r" intoString:nil]; [scanner scanString:@"\n" intoString:nil]; } } - + // skip blank line [scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:nil]; @@ -153,14 +147,14 @@ // consume newline [scanner scanString:@"\r" intoString:nil]; [scanner scanString:@"\n" intoString:nil]; - + if ([line hasPrefix:@"="]) { scanner.scanLocation = scanner.scanLocation - (line.length + 2); base64Section = NO; } else { [base64String appendFormat:@"%@\n", line]; } - } + } // read checksum NSString *checksumString = nil; @@ -168,7 +162,7 @@ // consume newline [scanner scanString:@"\r" intoString:nil]; [scanner scanString:@"\n" intoString:nil]; - + if ([scanner scanString:@"=" intoString:nil]) { [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&checksumString]; // consume newline @@ -178,30 +172,29 @@ if (!checksumString) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Missing checksum"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Missing checksum" }]; } return nil; } - //read footer + // read footer BOOL footerMatchHeader = NO; [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&line]; // consume newline [scanner scanString:@"\r" intoString:nil]; [scanner scanString:@"\n" intoString:nil]; - + if ([line hasSuffix:[headerLine substringFromIndex:12]]) { footerMatchHeader = YES; } if (!footerMatchHeader) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Footer don't match to header"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Footer don't match to header" }]; } return nil; } - // binary data from base64 part NSData *binaryData = [[NSData alloc] initWithBase64EncodedString:base64String options:NSDataBase64DecodingIgnoreUnknownCharacters]; @@ -214,7 +207,7 @@ NSData *calculatedCRC24Data = [NSData dataWithBytes:&calculatedCRC24 length:3]; if (![calculatedCRC24Data isEqualToData:readChecksumData]) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Checksum mismatch"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Checksum mismatch" }]; } return nil; } @@ -223,3 +216,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPBigNum+Private.h b/enzevalos_iphone/ObjectivePGP/PGPBigNum+Private.h new file mode 100644 index 00000000..d8dd38ed --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPBigNum+Private.h @@ -0,0 +1,26 @@ +// +// PGPBigNum.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 26/06/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <ObjectivePGP/PGPBigNum.h> +#import <ObjectivePGP/PGPMacros.h> +#import <openssl/bn.h> +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPBigNum () + +@property (nonatomic, readonly) BIGNUM *bignumRef; + +PGP_EMPTY_INIT_UNAVAILABLE; + +- (instancetype)initWithBIGNUM:(BIGNUM *)bignumRef; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPBigNum.h b/enzevalos_iphone/ObjectivePGP/PGPBigNum.h new file mode 100644 index 00000000..688e9c29 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPBigNum.h @@ -0,0 +1,21 @@ +// +// PGPBigNum.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 26/06/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPBigNum : NSObject <NSCopying> + +@property (nonatomic, readonly) unsigned int bitsCount; +@property (nonatomic, readonly) unsigned int bytesCount; +@property (nonatomic, readonly) NSData *data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPBigNum.m b/enzevalos_iphone/ObjectivePGP/PGPBigNum.m new file mode 100644 index 00000000..19add90c --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPBigNum.m @@ -0,0 +1,54 @@ +// +// PGPBigNum.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 26/06/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPBigNum.h" +#import "PGPBigNum+Private.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPBigNum + +- (instancetype)initWithBIGNUM:(BIGNUM *)bignumRef { + NSParameterAssert(bignumRef); + + if ((self = [super init])) { + _bignumRef = BN_dup(bignumRef); + } + return self; +} + +- (unsigned int)bitsCount { + return BN_num_bits(self.bignumRef); +} + +- (unsigned int)bytesCount { + return BN_num_bytes(self.bignumRef); +} + +- (NSData *)data { + let buflen = self.bytesCount; + let buf = calloc(buflen, 1); + pgp_defer { if (buf) { free(buf); } }; + BN_bn2bin(self.bignumRef, buf); + return [NSData dataWithBytes:buf length:buflen]; +} + +- (void)dealloc { + BN_clear_free(_bignumRef); +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(nullable NSZone *)zone { + return [[PGPBigNum alloc] initWithBIGNUM:BN_dup(self.bignumRef)]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.h b/enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.h new file mode 100644 index 00000000..d47e4c0b --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.h @@ -0,0 +1,29 @@ +// +// PGPCryptoCFB.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 05/06/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPS2K.h" +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPCryptoCFB : NSObject + ++ (nullable NSData *)decryptData:(NSData *)encryptedData + sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase + symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm + iv:(NSData *)ivData; + ++ (nullable NSData *)encryptData:(NSData *)encryptedData + sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase + symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm + iv:(NSData *)ivData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPCryptoCFB.m b/enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.m similarity index 58% rename from PGPCryptoCFB.m rename to enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.m index 9adf23eb..a0243749 100644 --- a/PGPCryptoCFB.m +++ b/enzevalos_iphone/ObjectivePGP/PGPCryptoCFB.m @@ -7,142 +7,137 @@ // #import "PGPCryptoCFB.h" -#import "PGPTypes.h" -#import "PGPS2K.h" -#import "PGPCryptoUtils.h" #import "NSData+PGPUtils.h" +#import "PGPCryptoUtils.h" +#import "PGPS2K.h" +#import "PGPTypes.h" +#import "PGPMacros+Private.h" #import <CommonCrypto/CommonCrypto.h> -#import <CommonCrypto/CommonDigest.h> #import <CommonCrypto/CommonCryptor.h> +#import <CommonCrypto/CommonDigest.h> + +#import <openssl/aes.h> +#import <openssl/blowfish.h> +#import <openssl/camellia.h> +#import <openssl/cast.h> +#import <openssl/des.h> +#import <openssl/idea.h> +#import <openssl/sha.h> -#include <openssl/cast.h> -#include <openssl/idea.h> -#include <openssl/aes.h> -#include <openssl/sha.h> -#include <openssl/des.h> -#include <openssl/camellia.h> -#include <openssl/blowfish.h> +NS_ASSUME_NONNULL_BEGIN @implementation PGPCryptoCFB -+ (NSData *) decryptData:(NSData *)encryptedData - sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase - symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm - iv:(NSData *)ivData -{ - return [[self class] manipulateData:encryptedData sessionKeyData:sessionKeyData symmetricAlgorithm:symmetricAlgorithm iv:ivData decrypt:YES]; ++ (nullable NSData *)decryptData:(NSData *)encryptedData + sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase + symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm + iv:(NSData *)ivData { + return [self manipulateData:encryptedData sessionKeyData:sessionKeyData symmetricAlgorithm:symmetricAlgorithm iv:ivData decrypt:YES]; } -+ (NSData *) encryptData:(NSData *)encryptedData - sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase - symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm - iv:(NSData *)ivData -{ - return [[self class] manipulateData:encryptedData sessionKeyData:sessionKeyData symmetricAlgorithm:symmetricAlgorithm iv:ivData decrypt:NO]; ++ (nullable NSData *)encryptData:(NSData *)encryptedData + sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase + symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm + iv:(NSData *)ivData { + return [self manipulateData:encryptedData sessionKeyData:sessionKeyData symmetricAlgorithm:symmetricAlgorithm iv:ivData decrypt:NO]; } #pragma mark - Private // key binary string representation of key to be used to decrypt the ciphertext. -+ (NSData *) manipulateData:(NSData *)encryptedData - sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase - symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm - iv:(NSData *)ivData - decrypt:(BOOL)decrypt -{ - NSAssert(ivData.length > 0, @"Missing IV"); ++ (nullable NSData *)manipulateData:(NSData *)encryptedData + sessionKeyData:(NSData *)sessionKeyData // s2k produceSessionKeyWithPassphrase + symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm + iv:(NSData *)ivData + decrypt:(BOOL)decrypt { NSAssert(sessionKeyData.length > 0, @"Missing session key"); NSAssert(encryptedData.length > 0, @"Missing data"); - + NSAssert(ivData.length > 0, @"Missing IV"); + if (ivData.length == 0 || sessionKeyData.length == 0 || encryptedData.length == 0) { return nil; } - + NSUInteger keySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:symmetricAlgorithm]; - NSAssert(keySize <= 32, @"invalid keySize"); - + NSAssert(keySize <= 32, @"Invalid key size"); + NSAssert(sessionKeyData.length >= keySize, @"Invalid session key."); + unsigned char *iv = calloc(1, ivData.length); + pgp_defer { if (iv) { free(iv); } }; if (!iv) { return nil; } memcpy(iv, ivData.bytes, ivData.length); - const void *encryptedBytes = encryptedData.bytes; + let encryptedBytes = encryptedData.bytes; NSUInteger outBufferLength = encryptedData.length; UInt8 *outBuffer = calloc(outBufferLength, sizeof(UInt8)); - + pgp_defer { if (outBuffer) { free(outBuffer); } }; + NSData *decryptedData = nil; - + // decrypt with CFB switch (symmetricAlgorithm) { case PGPSymmetricAES128: case PGPSymmetricAES192: - case PGPSymmetricAES256: - { + case PGPSymmetricAES256: { AES_KEY aes_key; - AES_set_encrypt_key(sessionKeyData.bytes, (unsigned int)keySize * 8, &aes_key); - - int num = 0; - AES_cfb128_encrypt(encryptedBytes, outBuffer, outBufferLength, &aes_key, iv, &num, decrypt ? AES_DECRYPT : AES_ENCRYPT); + AES_set_encrypt_key(sessionKeyData.bytes, MIN((unsigned int)keySize * 8, (unsigned int)sessionKeyData.length * 8), &aes_key); + + int blocksNum = 0; + AES_cfb128_encrypt(encryptedBytes, outBuffer, outBufferLength, &aes_key, iv, &blocksNum, decrypt ? AES_DECRYPT : AES_ENCRYPT); decryptedData = [NSData dataWithBytes:outBuffer length:outBufferLength]; - + memset(&aes_key, 0, sizeof(AES_KEY)); - } - break; - case PGPSymmetricIDEA: - { + } break; + case PGPSymmetricIDEA: { IDEA_KEY_SCHEDULE encrypt_key; idea_set_encrypt_key(sessionKeyData.bytes, &encrypt_key); - + IDEA_KEY_SCHEDULE decrypt_key; idea_set_decrypt_key(&encrypt_key, &decrypt_key); - + int num = 0; idea_cfb64_encrypt(encryptedBytes, outBuffer, outBufferLength, decrypt ? &decrypt_key : &encrypt_key, iv, &num, decrypt ? CAST_DECRYPT : CAST_ENCRYPT); decryptedData = [NSData dataWithBytes:outBuffer length:outBufferLength]; - + memset(&encrypt_key, 0, sizeof(IDEA_KEY_SCHEDULE)); memset(&decrypt_key, 0, sizeof(IDEA_KEY_SCHEDULE)); - } - break; - case PGPSymmetricTripleDES: - { + } break; + case PGPSymmetricTripleDES: { DES_key_schedule *keys = calloc(3, sizeof(DES_key_schedule)); - + pgp_defer { if (keys) { free(keys); } }; + for (NSUInteger n = 0; n < 3; ++n) { - DES_set_key((DES_cblock *)(void *)(ivData.bytes + n * 8),&keys[n]); + DES_set_key((DES_cblock *)(void *)(sessionKeyData.bytes + n * 8), &keys[n]); } - - int num = 0; - DES_ede3_cfb64_encrypt(encryptedBytes, outBuffer, outBufferLength, &keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)iv, &num, decrypt ? DES_DECRYPT : DES_ENCRYPT); + + int blocksNum = 0; + DES_ede3_cfb64_encrypt(encryptedBytes, outBuffer, outBufferLength, &keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)iv, &blocksNum, decrypt ? DES_DECRYPT : DES_ENCRYPT); decryptedData = [NSData dataWithBytes:outBuffer length:outBufferLength]; - + if (keys) { memset(keys, 0, 3 * sizeof(DES_key_schedule)); - free(keys); } - } - break; - case PGPSymmetricCAST5: - { + } break; + case PGPSymmetricCAST5: { // initialize CAST_KEY encrypt_key; - CAST_set_key(&encrypt_key, (unsigned int)keySize, sessionKeyData.bytes); - + CAST_set_key(&encrypt_key, MIN((unsigned int)keySize, (unsigned int)sessionKeyData.length), sessionKeyData.bytes); + // see __ops_decrypt_init block_encrypt siv,civ,iv comments. siv is needed for weird v3 resync, // wtf civ ??? // CAST_ecb_encrypt(in, out, encrypt_key, CAST_ENCRYPT); int num = 0; // how much of the 64bit block we have used CAST_cfb64_encrypt(encryptedBytes, outBuffer, outBufferLength, &encrypt_key, iv, &num, decrypt ? CAST_DECRYPT : CAST_ENCRYPT); decryptedData = [NSData dataWithBytes:outBuffer length:outBufferLength]; - + memset(&encrypt_key, 0, sizeof(CAST_KEY)); - } - break; + } break; case PGPSymmetricBlowfish: case PGPSymmetricTwofish256: - //TODO: implement blowfish and twofish + // TODO: implement blowfish and twofish [NSException raise:@"PGPNotSupported" format:@"Twofish not supported"]; break; case PGPSymmetricPlaintext: @@ -151,15 +146,14 @@ default: break; } - + if (outBuffer) { memset(outBuffer, 0, outBufferLength); - free(outBuffer); } - - free(iv); - + return [decryptedData copy]; } @end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPExportableProtocol.h b/enzevalos_iphone/ObjectivePGP/PGPExportableProtocol.h new file mode 100644 index 00000000..8e4aec98 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPExportableProtocol.h @@ -0,0 +1,19 @@ +// +// PGPExportableProtocol.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 11/06/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@protocol PGPExportable <NSObject> + +- (nullable NSData *)export:(NSError *_Nullable __autoreleasing *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPFingerprint.h b/enzevalos_iphone/ObjectivePGP/PGPFingerprint.h similarity index 50% rename from PGPFingerprint.h rename to enzevalos_iphone/ObjectivePGP/PGPFingerprint.h index d4460bb7..b20e5fc4 100644 --- a/PGPFingerprint.h +++ b/enzevalos_iphone/ObjectivePGP/PGPFingerprint.h @@ -9,13 +9,11 @@ #import <Foundation/Foundation.h> @interface PGPFingerprint : NSObject -@property (copy) NSData *hashedData; -@property (copy) NSData *keyData; +@property (nonatomic, copy) NSData *hashedData; +@property (nonatomic, copy) NSData *keyData; -- (instancetype) initWithData:(NSData *)data; -- (NSString *) description; -- (NSUInteger) hashLength; - -- (BOOL) isEqualToFingerprint:(PGPFingerprint *)fingerprint; +- (instancetype)initWithData:(NSData *)data; +- (NSString *)description; +- (NSUInteger)hashLength; @end diff --git a/PGPFingerprint.m b/enzevalos_iphone/ObjectivePGP/PGPFingerprint.m similarity index 54% rename from PGPFingerprint.m rename to enzevalos_iphone/ObjectivePGP/PGPFingerprint.m index f2c46bf3..1c3dda41 100644 --- a/PGPFingerprint.m +++ b/enzevalos_iphone/ObjectivePGP/PGPFingerprint.m @@ -8,11 +8,11 @@ #import "PGPFingerprint.h" #import "NSData+PGPUtils.h" +#import "PGPFoundation.h" @implementation PGPFingerprint -- (instancetype) initWithData:(NSData *)keyData -{ +- (instancetype)initWithData:(NSData *)keyData { if (self = [self init]) { _keyData = keyData; _hashedData = [keyData pgp_SHA1]; @@ -20,8 +20,7 @@ return self; } -- (NSString *)description -{ +- (NSString *)description { NSMutableString *sbuf = [NSMutableString stringWithCapacity:self.hashedData.length * 2]; const unsigned char *buf = self.hashedData.bytes; for (NSUInteger i = 0; i < self.hashedData.length; ++i) { @@ -30,37 +29,29 @@ return [sbuf copy]; } -- (NSUInteger) hashLength -{ +#pragma mark - isEqual + +- (NSUInteger)hashLength { return self.hashedData.length; } -- (NSUInteger)hash -{ - const NSUInteger prime = 31; - NSUInteger result = 1; - result = prime * result + [_hashedData hash]; - result = prime * result + [_keyData hash]; - return result; +- (BOOL)isEqual:(id)other { + if (self == other) { return YES; } + if ([other isKindOfClass:self.class]) { + return [self isEqualToFingerprintPacket:other]; + } + return NO; } -- (BOOL)isEqual:(id)object -{ - if (self == object) { - return YES; - } - - if ([self class] != [object class]) { - return NO; - } - - PGPFingerprint *other = object; - return [self.keyData isEqualToData:other.keyData] && [self.hashedData isEqualToData:other.hashedData]; +- (BOOL)isEqualToFingerprintPacket:(PGPFingerprint *)packet { + return PGPEqualObjects(self.hashedData,packet.hashedData) && PGPEqualObjects(self.keyData,packet.keyData); } -- (BOOL) isEqualToFingerprint:(PGPFingerprint *)fingerprint -{ - return [self isEqual:fingerprint]; +- (NSUInteger)hash { + NSUInteger result = 1; + result = 31 * result + self.hashedData.hash; + result = 31 * result + self.keyData.hash; + return result; } @end diff --git a/enzevalos_iphone/ObjectivePGP/PGPFoundation.h b/enzevalos_iphone/ObjectivePGP/PGPFoundation.h new file mode 100644 index 00000000..acbe5492 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPFoundation.h @@ -0,0 +1,24 @@ + +// +// PGPFoundation.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 31/05/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +#define PGPCast(obj, c) ((c * _Nullable) _pgp__cast(obj, c.class)) + +id _Nullable _pgp__cast(id _Nullable obj, Class objClass); + +BOOL PGPEqualObjects(id _Nullable obj1, id _Nullable obj2); + +@interface PGPFoundation : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPFoundation.m b/enzevalos_iphone/ObjectivePGP/PGPFoundation.m new file mode 100644 index 00000000..8fc44d7b --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPFoundation.m @@ -0,0 +1,24 @@ +// +// PGPFoundation.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 31/05/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPFoundation.h" +#import "PGPMacros+Private.h" + +@implementation PGPFoundation + +@end + +OBJC_EXTERN inline id _pgp__cast(id obj, Class objClass) { + NSCParameterAssert(objClass); + return [obj isKindOfClass:objClass] ? obj : nil; +} + +BOOL PGPEqualObjects(id _Nullable obj1, id _Nullable obj2) { + return obj1 == obj2 || [obj1 isEqual:obj2]; +} + diff --git a/enzevalos_iphone/ObjectivePGP/PGPKey+Private.h b/enzevalos_iphone/ObjectivePGP/PGPKey+Private.h new file mode 100644 index 00000000..79ac8103 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPKey+Private.h @@ -0,0 +1,21 @@ +// +// PGPKey+Private.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/06/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPKey.h" +#import "PGPPartialKey.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPKey () + +@property (nonatomic, nullable, readwrite) PGPPartialKey *secretKey; +@property (nonatomic, nullable, readwrite) PGPPartialKey *publicKey; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPKey.h b/enzevalos_iphone/ObjectivePGP/PGPKey.h new file mode 100644 index 00000000..b9cc5883 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPKey.h @@ -0,0 +1,44 @@ +// +// PGPKey.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 31/05/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPacket.h" +#import "PGPPartialKey.h" +#import "PGPTypes.h" + +#import "PGPExportableProtocol.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/// Public + Private key with the same ID. +@interface PGPKey : NSObject <PGPExportable> + +PGP_EMPTY_INIT_UNAVAILABLE; + +/// Key ID +@property (nonatomic, readonly) PGPKeyID *keyID; +@property (nonatomic, nullable, readonly) PGPPartialKey *secretKey; +@property (nonatomic, nullable, readonly) PGPPartialKey *publicKey; +@property (nonatomic, nullable, readonly) NSDate *expirationDate; + +/// Whether key is secret. +@property (nonatomic, readonly) BOOL isSecret; +/// Whether key is public. +@property (nonatomic, readonly) BOOL isPublic; + +@property (nonatomic, nullable, readonly) PGPSecretKeyPacket *signingSecretKey; + +- (instancetype)initWithSecretKey:(nullable PGPPartialKey *)secretKey publicKey:(nullable PGPPartialKey *)publicKey NS_DESIGNATED_INITIALIZER; + +/// The binary format. +/// @discussion If you need ASCII format, you can use `PGPArmor`. +- (nullable NSData *)export:(PGPPartialKeyType)keyType error:(NSError *__autoreleasing _Nullable *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPKey.m b/enzevalos_iphone/ObjectivePGP/PGPKey.m new file mode 100644 index 00000000..3c204ee1 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPKey.m @@ -0,0 +1,145 @@ +// +// PGPKey.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 31/05/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPKey.h" +#import "PGPKey+Private.h" +#import "PGPPartialSubKey.h" +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +#import "PGPSecretKeyPacket.h" +#import "PGPSecretKeyPacket+Private.h" +#import "PGPSignaturePacket+Private.h" +#import "PGPSignatureSubpacket+Private.h" +#import "PGPRSA.h" +#import "PGPDSA.h" +#import "NSMutableData+PGPUtils.h" + +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPKey + +- (instancetype)initWithSecretKey:(nullable PGPPartialKey *)secretKey publicKey:(nullable PGPPartialKey *)publicKey { + if ((self = [super init])) { + _secretKey = secretKey; + _publicKey = publicKey; + } + return self; +} + +- (BOOL)isSecret { + return self.secretKey != nil; +} + +- (BOOL)isPublic { + return self.publicKey != nil; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@, publicKey: %@, secretKey: %@", super.description, self.publicKey.keyID, self.secretKey.keyID]; +} + +- (nullable NSDate *)expirationDate { + return self.publicKey.expirationDate ?: self.secretKey.expirationDate; +} + +- (PGPKeyID *)keyID { + return self.publicKey.keyID ?: self.secretKey.keyID; +} + +- (nullable PGPSecretKeyPacket *)signingSecretKey { + if (!self.secretKey) { + PGPLogDebug(@"Need secret key to sign"); + return nil; + } + + // find secret key based on the public key signature (unless self signed secret key) + let signingPacket = PGPCast(self.secretKey.signingKeyPacket, PGPSecretKeyPacket); + if (!signingPacket) { + PGPLogWarning(@"Need secret key to sign"); + } + + return signingPacket; +} + +#pragma mark - isEqual + +- (BOOL)isEqual:(id)other { + if (self == other) { return YES; } + if ([other isKindOfClass:self.class]) { + return [self isEqualToKey:other]; + } + return NO; +} + +- (BOOL)isEqualToKey:(PGPKey *)other { + return PGPEqualObjects(self.secretKey,other.secretKey) && PGPEqualObjects(self.publicKey,other.publicKey); +} + +- (NSUInteger)hash { + NSUInteger prime = 31; + NSUInteger result = 1; + + result = prime * result + self.secretKey.hash; + result = prime * result + self.publicKey.hash; + + return result; +} + + +#pragma mark - PGPExportable + +/// Export public and secret keys together. +- (nullable NSData *)export:(NSError *__autoreleasing _Nullable *)error { + let exportData = [NSMutableData data]; + if (self.publicKey) { + [exportData pgp_appendData:[self export:PGPPartialKeyPublic error:error]]; + } + + if (self.secretKey) { + [exportData pgp_appendData:[self export:PGPPartialKeySecret error:error]]; + } + + return exportData; +} + +- (nullable NSData *)export:(PGPPartialKeyType)keyType error:(NSError *__autoreleasing _Nullable *)error { + switch (keyType) { + case PGPPartialKeyPublic: { + if (!self.publicKey) { + return nil; + } + + return [self.publicKey export:error]; + } + break; + case PGPPartialKeySecret: { + if (!self.secretKey) { + return nil; + } + + return [self.secretKey export:error]; + } + break; + default: { + PGPLogError(@"Can't export unknown key type: %@", self); + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Can't export unknown key type"}]; + } + } + break; + } + + return nil; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.h b/enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.h new file mode 100644 index 00000000..e59ef2e3 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.h @@ -0,0 +1,29 @@ +// +// PGPKeyGenerator.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 25/08/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> +#import "PGPTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +@class PGPKey; + +@interface PGPKeyGenerator : NSObject + +@property (nonatomic) int keyBitsLength; +@property (nonatomic) PGPPublicKeyAlgorithm keyAlgorithm; +@property (nonatomic) PGPSymmetricAlgorithm cipherAlgorithm; +@property (nonatomic) PGPHashAlgorithm hashAlgorithm; +@property (nonatomic) UInt8 version; +@property (nonatomic) NSDate *createDate; + +- (PGPKey *)generateFor:(NSString *)userID passphrase:(nullable NSString *)passphrase; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.m b/enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.m new file mode 100644 index 00000000..55e65820 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPKeyGenerator.m @@ -0,0 +1,296 @@ +// +// PGPKeyGenerator.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 25/08/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPKeyGenerator.h" +#import "PGPTypes.h" +#import "PGPPublicKeyPacket+Private.h" +#import "PGPSecretKeyPacket+Private.h" +#import "PGPSignaturePacket+Private.h" +#import "PGPMacros+Private.h" +#import "NSData+PGPUtils.h" +#import "NSMutableData+PGPUtils.h" +#import "PGPCryptoHash.h" +#import "PGPCryptoUtils.h" +#import "PGPRSA.h" +#import "PGPDSA.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPKeyGenerator () + +@end + +@implementation PGPKeyGenerator + +- (instancetype)init { + if ((self = [super init])) { + _keyAlgorithm = PGPPublicKeyAlgorithmRSA; + _keyBitsLength = 2048; + _createDate = NSDate.date; + _version = 0x04; + _cipherAlgorithm = PGPSymmetricAES256; + _hashAlgorithm = PGPHashSHA256; + } + return self; +} + +- (nullable PGPKeyMaterial *)fillMPIForPublic:(PGPPublicKeyPacket *)publicKeyPacket andSecret:(PGPSecretKeyPacket *)secretKeyPacket withKeyAlgorithm:(PGPPublicKeyAlgorithm)algorithm bits:(int)bits { + PGPKeyMaterial *keyMaterial = nil; + + switch (algorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + keyMaterial = [PGPRSA generateNewKeyMPIArray:bits]; + publicKeyPacket.publicMPIArray = @[keyMaterial.n, keyMaterial.e]; + secretKeyPacket.secretMPIArray = @[keyMaterial.d, keyMaterial.p, keyMaterial.q, keyMaterial.u]; + } break; + case PGPPublicKeyAlgorithmDSA: + case PGPPublicKeyAlgorithmECDSA: { + keyMaterial = [PGPDSA generateNewKeyMPIArray:bits]; + publicKeyPacket.publicMPIArray = @[keyMaterial.p, keyMaterial.q, keyMaterial.g, keyMaterial.y]; + secretKeyPacket.secretMPIArray = @[keyMaterial.x]; + } break; + default: + NSAssert(NO, @"Not supported"); + return nil; + } + + secretKeyPacket.publicMPIArray = publicKeyPacket.publicMPIArray; + return keyMaterial; +} + +- (nullable PGPKey *)buildKeyWithPassphrase:(nullable NSString *)passphrase { + // Public key + let publicKeyPacket = [[PGPPublicKeyPacket alloc] init]; + publicKeyPacket.version = self.version; + publicKeyPacket.publicKeyAlgorithm = self.keyAlgorithm; + publicKeyPacket.createDate = self.createDate; + + // Secret Key + let secretKeyPacket = [[PGPSecretKeyPacket alloc] init]; + secretKeyPacket.version = self.version; + secretKeyPacket.publicKeyAlgorithm = publicKeyPacket.publicKeyAlgorithm; + secretKeyPacket.symmetricAlgorithm = self.cipherAlgorithm; + secretKeyPacket.createDate = publicKeyPacket.createDate; + + // Fill MPIs + [self fillMPIForPublic:publicKeyPacket andSecret:secretKeyPacket withKeyAlgorithm:self.keyAlgorithm bits:self.keyBitsLength]; + + // Encrypt with passphrase + NSUInteger blockSize = [PGPCryptoUtils blockSizeOfSymmetricAlhorithm:secretKeyPacket.symmetricAlgorithm]; + if (!passphrase) { + secretKeyPacket.s2kUsage = PGPS2KUsageNonEncrypted; + secretKeyPacket.s2k = [[PGPS2K alloc] initWithSpecifier:PGPS2KSpecifierSimple hashAlgorithm:self.hashAlgorithm]; + secretKeyPacket.ivData = [NSMutableData dataWithLength:blockSize]; + } else { + secretKeyPacket.ivData = [PGPCryptoUtils randomData:blockSize]; + secretKeyPacket.s2kUsage = PGPS2KUsageEncryptedAndHashed; + + let s2k = [[PGPS2K alloc] initWithSpecifier:PGPS2KSpecifierIteratedAndSalted hashAlgorithm:self.hashAlgorithm]; + secretKeyPacket.s2k = s2k; + + // build encryptedMPIPartData + let plaintextMPIPartData = [NSMutableData data]; + + for (PGPMPI *mpi in secretKeyPacket.secretMPIArray) { + [plaintextMPIPartData pgp_appendData:[mpi exportMPI]]; + } + + switch (secretKeyPacket.s2kUsage) { + case PGPS2KUsageEncryptedAndHashed: { + // a 20-octet SHA-1 hash of the plaintext of the algorithm-specific portion + let hashData = plaintextMPIPartData.pgp_SHA1; + [plaintextMPIPartData pgp_appendData:hashData]; + } break; + case PGPS2KUsageEncrypted: { + // a two-octet checksum of the plaintext of the algorithm-specific portion + UInt16 checksum = CFSwapInt16HostToBig(plaintextMPIPartData.pgp_Checksum); + [plaintextMPIPartData appendBytes:&checksum length:2]; + } break; + default: + break; + } + + let sessionKeyData = [s2k produceSessionKeyWithPassphrase:passphrase symmetricAlgorithm:self.cipherAlgorithm]; + if (sessionKeyData) { + secretKeyPacket.encryptedMPIPartData = [PGPCryptoCFB encryptData:plaintextMPIPartData sessionKeyData:sessionKeyData symmetricAlgorithm:self.cipherAlgorithm iv:secretKeyPacket.ivData]; + } + } + + // Create Key + let partialPublicKey = [[PGPPartialKey alloc] initWithPackets:@[publicKeyPacket]]; + let partialSecretKey = [[PGPPartialKey alloc] initWithPackets:@[secretKeyPacket]]; + return [[PGPKey alloc] initWithSecretKey:partialSecretKey publicKey:partialPublicKey]; +} + +- (PGPKey *)addSubKeyTo:(PGPKey *)parentKey { + let publicSubKeyPacket = [[PGPPublicSubKeyPacket alloc] init]; + publicSubKeyPacket.version = self.version; + publicSubKeyPacket.publicKeyAlgorithm = self.keyAlgorithm; + publicSubKeyPacket.createDate = self.createDate; + + // Secret Key + let secretSubKeyPacket = [[PGPSecretSubKeyPacket alloc] init]; + secretSubKeyPacket.version = self.version; + secretSubKeyPacket.publicKeyAlgorithm = publicSubKeyPacket.publicKeyAlgorithm; + secretSubKeyPacket.s2kUsage = PGPS2KUsageNonEncrypted; + secretSubKeyPacket.s2k = [[PGPS2K alloc] initWithSpecifier:PGPS2KSpecifierSimple hashAlgorithm:self.hashAlgorithm]; + secretSubKeyPacket.symmetricAlgorithm = self.cipherAlgorithm; + NSUInteger blockSize = [PGPCryptoUtils blockSizeOfSymmetricAlhorithm:secretSubKeyPacket.symmetricAlgorithm]; + secretSubKeyPacket.ivData = [NSMutableData dataWithLength:blockSize]; + secretSubKeyPacket.createDate = publicSubKeyPacket.createDate; + + [self fillMPIForPublic:publicSubKeyPacket andSecret:secretSubKeyPacket withKeyAlgorithm:self.keyAlgorithm bits:self.keyBitsLength]; + + // Create Key + let publicSubKey = [[PGPPartialSubKey alloc] initWithPackets:@[publicSubKeyPacket]]; + let secretSubKey = [[PGPPartialSubKey alloc] initWithPackets:@[secretSubKeyPacket]]; + + parentKey.publicKey.subKeys = [parentKey.publicKey.subKeys arrayByAddingObject:publicSubKey]; + parentKey.secretKey.subKeys = [parentKey.secretKey.subKeys arrayByAddingObject:secretSubKey]; + + return [[PGPKey alloc] initWithSecretKey:secretSubKey publicKey:publicSubKey]; +} + +- (NSArray<PGPSignatureSubpacket *> *)signatureCommonHashedSubpackets { + return @[ + [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeSignatureCreationTime andValue:self.createDate], + [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeKeyFlags andValue:@[@(PGPSignatureFlagAllowSignData), @(PGPSignatureFlagAllowCertifyOtherKeys)]], + [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypePreferredHashAlgorithm andValue:@[@(PGPHashSHA256), @(PGPHashSHA384), @(PGPHashSHA512)]], + [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypePreferredSymetricAlgorithm andValue:@[@(PGPSymmetricAES256), @(PGPSymmetricAES192), @(PGPSymmetricAES128), @(PGPSymmetricCAST5), @(PGPSymmetricTripleDES), @(PGPSymmetricIDEA)]], + [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypePreferredCompressionAlgorithm andValue:@[@(PGPCompressionBZIP2), @(PGPCompressionZLIB), @(PGPCompressionZIP)]], + [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeFeatures andValue:@[@(PGPFeatureModificationDetection)]], + [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeKeyServerPreference andValue:@[@(PGPKeyServerPreferenceNoModify)]] + ]; +} + +- (nullable PGPSignaturePacket *)buildPublicSignaturePacketFor:(PGPKey *)key { + let publicKeyPacket = PGPCast(key.publicKey.primaryKeyPacket, PGPPublicKeyPacket); + + let publicKeySignaturePacket = [PGPSignaturePacket signaturePacket:PGPSignaturePositiveCertificationUserIDandPublicKey hashAlgorithm:self.hashAlgorithm]; + publicKeySignaturePacket.version = publicKeyPacket.version; + publicKeySignaturePacket.publicKeyAlgorithm = publicKeyPacket.publicKeyAlgorithm; + + let issuerKeyIDSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeIssuerKeyID andValue:publicKeyPacket.keyID]; + + publicKeySignaturePacket.hashedSubpackets = [self.signatureCommonHashedSubpackets arrayByAddingObject:[[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypePrimaryUserID andValue:@(YES)]]; + publicKeySignaturePacket.unhashedSubpackets = @[issuerKeyIDSubpacket]; + + // self sign the signature + NSError *error; + let userID = key.publicKey.users.firstObject.userID; + if (![publicKeySignaturePacket signData:nil withKey:key subKey:nil passphrase:nil userID:userID error:&error]) { + return nil; + } + + return publicKeySignaturePacket; +} + +- (nullable PGPSignaturePacket *)buildSecretSignaturePacketFor:(PGPKey *)key { + let secretKeyPacket = PGPCast(key.secretKey.primaryKeyPacket, PGPSecretKeyPacket); + + let secretKeySignaturePacket = [PGPSignaturePacket signaturePacket:PGPSignaturePositiveCertificationUserIDandPublicKey hashAlgorithm:self.hashAlgorithm]; + secretKeySignaturePacket.version = secretKeyPacket.version; + secretKeySignaturePacket.publicKeyAlgorithm = secretKeyPacket.publicKeyAlgorithm; + + let issuerKeyIDSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeIssuerKeyID andValue:secretKeyPacket.keyID]; + + secretKeySignaturePacket.hashedSubpackets = self.signatureCommonHashedSubpackets; + secretKeySignaturePacket.unhashedSubpackets = @[issuerKeyIDSubpacket]; + + // self sign the signature + NSError *error; + let userID = key.secretKey.users.firstObject.userID; + if (![secretKeySignaturePacket signData:nil withKey:key subKey:nil passphrase:nil userID:userID error:&error]) { + return nil; + } + + return secretKeySignaturePacket; +} + + +- (nullable PGPSignaturePacket *)buildPublicSignaturePacketForSubKey:(PGPKey *)subKey parentKey:(PGPKey *)parentKey { + let publicSubKeyPacket = PGPCast(subKey.publicKey.primaryKeyPacket, PGPPublicSubKeyPacket); + + let publicSubKeySignaturePacket = [PGPSignaturePacket signaturePacket:PGPSignatureSubkeyBinding hashAlgorithm:self.hashAlgorithm]; + publicSubKeySignaturePacket.version = publicSubKeyPacket.version; + publicSubKeySignaturePacket.publicKeyAlgorithm = publicSubKeyPacket.publicKeyAlgorithm; + + let creationTimeSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeSignatureCreationTime andValue:NSDate.date]; + let keyFlagsSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeKeyFlags andValue:@[@(PGPSignatureFlagAllowEncryptCommunications), @(PGPSignatureFlagAllowEncryptStorage)]]; + let issuerKeyIDSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeIssuerKeyID andValue:parentKey.signingSecretKey.keyID]; + + publicSubKeySignaturePacket.hashedSubpackets = @[creationTimeSubpacket, keyFlagsSubpacket]; + publicSubKeySignaturePacket.unhashedSubpackets = @[issuerKeyIDSubpacket]; + + // self sign the signature + NSError *error; + let userID = parentKey.publicKey.users.firstObject.userID; + if (![publicSubKeySignaturePacket signData:nil withKey:parentKey subKey:subKey passphrase:nil userID:userID error:&error]) { + return nil; + } + + return publicSubKeySignaturePacket; +} + +- (nullable PGPSignaturePacket *)buildSecretSignaturePacketForSubKey:(PGPKey *)subKey parentKey:(PGPKey *)parentKey { + let secretSubKeyPacket = PGPCast(subKey.secretKey.primaryKeyPacket, PGPSecretSubKeyPacket); + + let secretSubKeySignaturePacket = [PGPSignaturePacket signaturePacket:PGPSignatureSubkeyBinding hashAlgorithm:self.hashAlgorithm]; + secretSubKeySignaturePacket.version = secretSubKeyPacket.version; + secretSubKeySignaturePacket.publicKeyAlgorithm = secretSubKeyPacket.publicKeyAlgorithm; + + let creationTimeSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeSignatureCreationTime andValue:NSDate.date]; + let keyFlagsSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeKeyFlags andValue:@[@(PGPSignatureFlagAllowEncryptCommunications), @(PGPSignatureFlagAllowEncryptStorage)]]; + let issuerKeyIDSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeIssuerKeyID andValue:parentKey.signingSecretKey.keyID]; + + secretSubKeySignaturePacket.hashedSubpackets = @[creationTimeSubpacket, keyFlagsSubpacket]; + secretSubKeySignaturePacket.unhashedSubpackets = @[issuerKeyIDSubpacket]; + + // self sign the signature + NSError *error; + let userID = parentKey.secretKey.users.firstObject.userID; + if (![secretSubKeySignaturePacket signData:nil withKey:parentKey subKey:subKey passphrase:nil userID:userID error:&error]) { + return nil; + } + + return secretSubKeySignaturePacket; +} + +- (PGPKey *)generateFor:(NSString *)userID passphrase:(nullable NSString *)passphrase { + let key = [self buildKeyWithPassphrase:passphrase]; + let subKey = [self addSubKeyTo:key]; + + let userPublic = [[PGPUser alloc] initWithUserIDPacket:[[PGPUserIDPacket alloc] initWithUserID:userID]]; + let userSecret = [[PGPUser alloc] initWithUserIDPacket:[[PGPUserIDPacket alloc] initWithUserID:userID]]; + key.publicKey.users = @[userPublic]; + key.secretKey.users = @[userSecret]; + + // Public + + let publicKeySignaturePacket = [self buildPublicSignaturePacketFor:key]; + userPublic.selfCertifications = [userPublic.selfCertifications arrayByAddingObject:publicKeySignaturePacket]; + + let publicSubKeySignaturePacket = [self buildPublicSignaturePacketForSubKey:subKey parentKey:key]; + key.publicKey.subKeys.firstObject.bindingSignature = publicSubKeySignaturePacket; + + // Secret + + let secretKeySignaturePacket = [self buildSecretSignaturePacketFor:key]; + userSecret.selfCertifications = [userSecret.selfCertifications arrayByAddingObject:secretKeySignaturePacket]; + + let secretSubKeySignaturePacket = [self buildSecretSignaturePacketForSubKey:subKey parentKey:key]; + key.secretKey.subKeys.firstObject.bindingSignature = secretSubKeySignaturePacket; + + return key; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPKeyID.h b/enzevalos_iphone/ObjectivePGP/PGPKeyID.h new file mode 100644 index 00000000..31aac76a --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPKeyID.h @@ -0,0 +1,38 @@ +// +// PGPKeyID.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 06/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPMacros.h" +#import "PGPExportableProtocol.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPFingerprint; + +/// The eight-octet Key ID +@interface PGPKeyID : NSObject <PGPExportable> + +/// The eight-octet Key identifier +@property (readonly, copy, nonatomic) NSData *longKey; +@property (readonly, nonatomic) NSString *longKeyString; + +/// The four-octet Key identifier +@property (readonly, nonatomic) NSData *shortKey; +@property (readonly, nonatomic) NSString *shortKeyString; + +PGP_EMPTY_INIT_UNAVAILABLE + +/// Initialize with eight-octet key identifier +- (instancetype)initWithLongKey:(NSData *)longKeyData NS_DESIGNATED_INITIALIZER; + +/// Initialize with fingerprint +- (instancetype)initWithFingerprint:(PGPFingerprint *)fingerprint; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPKeyID.m b/enzevalos_iphone/ObjectivePGP/PGPKeyID.m new file mode 100644 index 00000000..b0e7e8bf --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPKeyID.m @@ -0,0 +1,94 @@ +// +// PGPKeyID.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 06/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// +// Fingerprint: 4772 3A3C EE12 760F 7DC8 4AE0 1B63 BCB7 E810 38C6 +// Long Key ID: 1B63 BCB7 E810 38C6 <- this +// Short Key ID: E810 38C6 + +#import "PGPKeyID.h" +#import "PGPMacros.h" +#import "PGPFingerprint.h" +#import "PGPFoundation.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPKeyID + +- (instancetype)initWithLongKey:(NSData *)longKeyData { + if (longKeyData.length != 8) { + return nil; + } + + if (self = [super init]) { + _longKey = [longKeyData copy]; + } + return self; +} + +- (instancetype)initWithFingerprint:(PGPFingerprint *)fingerprint { + PGPAssertClass(fingerprint, PGPFingerprint); + PGPAssertClass(fingerprint.hashedData, NSData); + return ((self = [self initWithLongKey:[fingerprint.hashedData subdataWithRange:(NSRange){fingerprint.hashLength - 8, 8}]])); +} + +- (NSString *)description { + return [self longKeyString]; +} + +- (NSData *)shortKey { + return [self.longKey subdataWithRange:(NSRange){4, 4}]; +} + +- (NSString *)shortKeyString { + NSData *sKey = self.shortKey; + NSMutableString *sbuf = [NSMutableString stringWithCapacity:sKey.length * 2]; + const unsigned char *buf = sKey.bytes; + for (NSUInteger i = 0; i < sKey.length; ++i) { + [sbuf appendFormat:@"%02X", (unsigned int)buf[i]]; + } + return sbuf.copy; +} + +- (NSString *)longKeyString { + NSData *lKey = self.longKey; + NSMutableString *sbuf = [NSMutableString stringWithCapacity:lKey.length * 2]; + const unsigned char *buf = lKey.bytes; + for (NSUInteger i = 0; i < lKey.length; ++i) { + [sbuf appendFormat:@"%02X", (unsigned int)buf[i]]; + } + return sbuf.copy; +} + +#pragma mark - isEqual + +- (BOOL)isEqual:(id)other { + if (self == other) { return YES; } + if ([other isKindOfClass:self.class]) { + return [self isEqualToKeyID:other]; + } + return NO; +} + +- (BOOL)isEqualToKeyID:(PGPKeyID *)packet { + return PGPEqualObjects(self.longKey,packet.longKey); +} + +- (NSUInteger)hash { + NSUInteger result = 1; + result = 31 * result + self.longKey.hash; + return result; +} + +#pragma mark - PGPExportable + +- (nullable NSData *)export:(NSError *__autoreleasing _Nullable *)error { + return self.longKey.copy; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPLogging.h b/enzevalos_iphone/ObjectivePGP/PGPLogging.h new file mode 100644 index 00000000..01124be8 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPLogging.h @@ -0,0 +1,33 @@ +// +// PGPLogging.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 14/05/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +#define PGPLogMacro(_level, _tag, _message) NSLog(@"[%s] %@ %s/%tu %@", _tag, @(_level), __PRETTY_FUNCTION__, __LINE__, _message()) + +#ifdef DEBUG +#define PGPLogDebug(format, ...) \ + PGPLogMacro(0, "ObjectivePGP", (^{ \ + return [NSString stringWithFormat:(@"" format), ##__VA_ARGS__]; \ + })) +#else +#define PGPLogDebug(format, ...) +#endif + +#define PGPLogWarning(format, ...) \ + PGPLogMacro(1, "ObjectivePGP", (^{ \ + return [NSString stringWithFormat:(@"" format), ##__VA_ARGS__]; \ + })) +#define PGPLogError(format, ...) \ + PGPLogMacro(2, "ObjectivePGP", (^{ \ + return [NSString stringWithFormat:(@"" format), ##__VA_ARGS__]; \ + })) + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPMPI.h b/enzevalos_iphone/ObjectivePGP/PGPMPI.h new file mode 100644 index 00000000..6dc9daa4 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPMPI.h @@ -0,0 +1,47 @@ +// +// OpenPGPMPI.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPBigNum.h" +#import "PGPMacros.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +OBJC_EXTERN NSString * const PGPMPI_N; +OBJC_EXTERN NSString * const PGPMPI_E; +OBJC_EXTERN NSString * const PGPMPI_P; +OBJC_EXTERN NSString * const PGPMPI_G; +OBJC_EXTERN NSString * const PGPMPI_Q; +OBJC_EXTERN NSString * const PGPMPI_D; +OBJC_EXTERN NSString * const PGPMPI_U; +OBJC_EXTERN NSString * const PGPMPI_X; +OBJC_EXTERN NSString * const PGPMPI_R; +OBJC_EXTERN NSString * const PGPMPI_S; +OBJC_EXTERN NSString * const PGPMPI_Y; +OBJC_EXTERN NSString * const PGPMPI_M; + +@interface PGPMPI : NSObject <NSCopying> + +@property (nonatomic, copy, readonly) NSString *identifier; +@property (nonatomic, readonly) PGPBigNum *bigNum; +/** + * Total bytes, header + body + */ +@property (nonatomic, readonly) NSUInteger packetLength; + +PGP_EMPTY_INIT_UNAVAILABLE; + +- (instancetype)initWithData:(NSData *)dataToMPI identifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithBigNum:(PGPBigNum *)bigNum identifier:(NSString *)identifier; +- (instancetype)initWithMPIData:(NSData *)mpiData identifier:(NSString *)identifier atPosition:(NSUInteger)position; +- (nullable NSData *)exportMPI; +- (nullable NSData *)bodyData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPMPI.m b/enzevalos_iphone/ObjectivePGP/PGPMPI.m new file mode 100644 index 00000000..76062480 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPMPI.m @@ -0,0 +1,119 @@ +// +// OpenPGPMPI.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// +// Multiprecision integers (also called MPIArray) are unsigned integers used +// to hold large integers such as the ones used in cryptographic +// calculations. + +#import "PGPMPI.h" +#import "PGPBigNum+Private.h" +#import "PGPLogging.h" +#import "PGPMacros+Private.h" +#import <openssl/bn.h> + +NS_ASSUME_NONNULL_BEGIN + +NSString * const PGPMPI_N = @"N"; +NSString * const PGPMPI_E = @"E"; +NSString * const PGPMPI_P = @"P"; +NSString * const PGPMPI_G = @"G"; +NSString * const PGPMPI_Q = @"Q"; +NSString * const PGPMPI_D = @"D"; +NSString * const PGPMPI_U = @"U"; +NSString * const PGPMPI_X = @"X"; +NSString * const PGPMPI_R = @"R"; +NSString * const PGPMPI_S = @"S"; +NSString * const PGPMPI_Y = @"Y"; +NSString * const PGPMPI_M = @"M"; + +@interface PGPMPI () + +@property (nonatomic, readwrite) PGPBigNum *bigNum; +@property (nonatomic, readwrite) NSUInteger packetLength; + +@end + +@implementation PGPMPI + +- (instancetype)initWithData:(NSData *)dataToMPI identifier:(NSString *)identifier { + if ((self = [super init])) { + _bigNum = [[PGPBigNum alloc] initWithBIGNUM:BN_bin2bn(dataToMPI.bytes, dataToMPI.length & INT_MAX, NULL)]; + _packetLength = dataToMPI.length + 2; + _identifier = [identifier copy]; + } + return self; +} + +- (instancetype)initWithBigNum:(PGPBigNum *)bigNum identifier:(NSString *)identifier { + return (self = [self initWithData:bigNum.data identifier:identifier]); +} + +// parse mpi "packet" +- (instancetype)initWithMPIData:(NSData *)mpiData identifier:(NSString *)identifier atPosition:(NSUInteger)position { + UInt16 bitsBE = 0; + [mpiData getBytes:&bitsBE range:(NSRange){position, 2}]; + UInt16 bits = CFSwapInt16BigToHost(bitsBE); + NSUInteger mpiBytesLength = (bits + 7) / 8; + + let intData = [mpiData subdataWithRange:(NSRange){position + 2, mpiBytesLength}]; + return (self = [self initWithData:intData identifier:identifier]); +} + +- (nullable NSData *)bodyData { + if (!self.bigNum) { + PGPLogDebug(@"Missing bignum"); + return nil; + } + + BIGNUM *mpi_BN = BN_dup(self.bigNum.bignumRef); + NSInteger mpi_BN_length = (BN_num_bits(mpi_BN) + 7) / 8; + UInt8 *bn_bin = calloc(mpi_BN_length, sizeof(UInt8)); + NSUInteger len = BN_bn2bin(mpi_BN, bn_bin); + BN_clear_free(mpi_BN); + + NSData *data = [NSData dataWithBytes:bn_bin length:len]; + free(bn_bin); + return data; +} + +- (nullable NSData *)exportMPI { + if (!self.bigNum) { + return nil; + } + + let outData = [NSMutableData data]; + + // length + UInt16 bits = (UInt16)BN_num_bits(self.bigNum.bignumRef); + UInt16 bitsBE = CFSwapInt16HostToBig(bits); + [outData appendBytes:&bitsBE length:2]; + + // mpi + UInt8 *buf = calloc(BN_num_bytes(self.bigNum.bignumRef), sizeof(UInt8)); + pgp_defer { free(buf); }; + UInt16 bytes = (bits + 7) / 8; + BN_bn2bin(self.bigNum.bignumRef, buf); + [outData appendBytes:buf length:bytes]; + + return outData; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@, \"%@\", %@ bytes, total: %@ bytes", [super description], self.identifier, @(self.bigNum.bytesCount), @(self.packetLength)]; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(nullable NSZone *)zone { + let copy = [[PGPMPI alloc] initWithBigNum:self.bigNum identifier:self.identifier]; + copy.packetLength = self.packetLength; + return copy; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPMacros+Private.h b/enzevalos_iphone/ObjectivePGP/PGPMacros+Private.h new file mode 100644 index 00000000..18b801a1 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPMacros+Private.h @@ -0,0 +1,51 @@ +// +// PGPMacros.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 11/06/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPMacros.h" + +#define let const __auto_type +#define var __auto_type + +#define weakify(var) __weak typeof(var) PGPWeak_##var = var; + +#define strongify(var) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wshadow\"") \ + __strong typeof(var) var = PGPWeak_##var; \ + _Pragma("clang diagnostic pop") + +#define PGP_CLASS_EXPORT __attribute__((visibility("default"))) + +#define PGP_EMPTY_INIT_UNAVAILABLE \ + -(instancetype)init __attribute__((unavailable("Not the designated initializer"))); \ + +(instancetype)new __attribute__((unavailable("Not the designated initializer"))); + +#define PGPAssertClass(object, allowedClass) \ + do { \ + NSAssert([object isKindOfClass:[allowedClass class]], @"Object type not satisfying: '%@' must be of type '%s' but is '%@'.", object, #allowedClass, (object ? NSStringFromClass((Class)[object class]) : @"(null)")); \ + } while (0); + +#define PGPNN(thing) \ + ^{ \ + __auto_type _Nonnull thang = thing; \ + NSCAssert(thang != nil, @"'" #thing "' Object must exist"); \ + return thang; \ + }() + +// Similar to defer in Swift +#define pgp_defer_block_name_with_prefix(prefix, suffix) prefix##suffix +#define pgp_defer_block_name(suffix) pgp_defer_block_name_with_prefix(pgp_defer_, suffix) +#define pgp_defer __strong void (^pgp_defer_block_name(__LINE__))(void) __attribute__((cleanup(pgp_defer_cleanup_block), unused)) = ^ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +static void pgp_defer_cleanup_block(__strong void (^ _Nonnull * _Nonnull block)(void)) { (*block)(); } +#pragma clang diagnostic pop + +#define PGPDataAppendPropertyBytes(d,var,len) \ + [d appendBytes:&self->_##var length:len] + diff --git a/enzevalos_iphone/ObjectivePGP/PGPMacros.h b/enzevalos_iphone/ObjectivePGP/PGPMacros.h new file mode 100644 index 00000000..e86ddf84 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPMacros.h @@ -0,0 +1,25 @@ +// +// PGPMacros.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 11/06/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#define PGP_CLASS_EXPORT __attribute__((visibility("default"))) + +#define PGP_EMPTY_INIT_UNAVAILABLE \ + -(instancetype)init __attribute__((unavailable("Not the designated initializer"))); \ + +(instancetype)new __attribute__((unavailable("Not the designated initializer"))); + +#define PGPAssertClass(object, allowedClass) \ + do { \ + NSAssert([object isKindOfClass:[allowedClass class]], @"Object type not satisfying: '%@' must be of type '%s' but is '%@'.", object, #allowedClass, (object ? NSStringFromClass((Class)[object class]) : @"(null)")); \ + } while (0); + +#define PGPNN(thing) \ + ^{ \ + __auto_type _Nonnull thang = thing; \ + NSCAssert(thang != nil, @"'" #thing "' Object must exist"); \ + return thang; \ + }() diff --git a/PGPPKCSEme.h b/enzevalos_iphone/ObjectivePGP/PGPPKCSEme.h similarity index 54% rename from PGPPKCSEme.h rename to enzevalos_iphone/ObjectivePGP/PGPPKCSEme.h index 02d1dc42..e727f9e4 100644 --- a/PGPPKCSEme.h +++ b/enzevalos_iphone/ObjectivePGP/PGPPKCSEme.h @@ -10,7 +10,7 @@ @interface PGPPKCSEme : NSObject -+ (NSData *) encodeMessage:(NSData *)m keyModulusLength:(NSUInteger)k error:(NSError * __autoreleasing *)error; -+ (NSData *) decodeMessage:(NSData *)m error:(NSError * __autoreleasing *)error; ++ (NSData *)encodeMessage:(NSData *)m keyModulusLength:(NSUInteger)k error:(NSError *__autoreleasing *)error; ++ (NSData *)decodeMessage:(NSData *)m error:(NSError *__autoreleasing *)error; @end diff --git a/PGPPKCSEme.m b/enzevalos_iphone/ObjectivePGP/PGPPKCSEme.m similarity index 78% rename from PGPPKCSEme.m rename to enzevalos_iphone/ObjectivePGP/PGPPKCSEme.m index 24902243..c640d938 100644 --- a/PGPPKCSEme.m +++ b/enzevalos_iphone/ObjectivePGP/PGPPKCSEme.m @@ -7,30 +7,31 @@ // #import "PGPPKCSEme.h" -#import "PGPTypes.h" #import "NSData+PGPUtils.h" #import "PGPCryptoUtils.h" +#import "PGPTypes.h" +#import "PGPMacros+Private.h" @implementation PGPPKCSEme -+ (NSData *) encodeMessage:(NSData *)m keyModulusLength:(NSUInteger)k error:(NSError * __autoreleasing *)error -{ ++ (NSData *)encodeMessage:(NSData *)m keyModulusLength:(NSUInteger)k error:(NSError *__autoreleasing *)error { if (m.length > k - 11) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Message to long"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Message to long" }]; } return nil; } - + // Generate an octet string PS of length k - mLen - 3 consisting of // pseudo-randomly generated nonzero octets. The length of PS will // be at least eight octets. + let psLen = MAX((k - m.length) - 3, (NSUInteger)8); NSMutableData *psData = [NSMutableData data]; - for (NSUInteger i = 0; i < (k - m.length) - 3; i++) { - UInt8 b = arc4random_uniform(254) + 1; + for (NSUInteger i = 0; i < psLen; i++) { + UInt8 b = (UInt8)arc4random_uniform(254) + 1; [psData appendBytes:&b length:1]; } - + NSMutableData *emData = [NSMutableData data]; UInt8 emPrefix[] = {0x00, 0x02}; UInt8 emSuffix[] = {0x00}; @@ -41,13 +42,12 @@ return [emData copy]; } -+ (NSData *)decodeMessage:(NSData *)m error:(NSError * __autoreleasing *)error -{ ++ (NSData *)decodeMessage:(NSData *)m error:(NSError *__autoreleasing *)error { NSUInteger position = 0; UInt8 emPrefix[2]; [m getBytes:&emPrefix range:(NSRange){position, sizeof(emPrefix)}]; position = position + sizeof(emPrefix); - + // read until 0x00 NSUInteger *psLength = 0; Byte b = 0; diff --git a/PGPPKCSEmsa.h b/enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.h similarity index 62% rename from PGPPKCSEmsa.h rename to enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.h index c3481344..95fa8ea9 100644 --- a/PGPPKCSEmsa.h +++ b/enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.h @@ -6,11 +6,11 @@ // Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. // -#import <Foundation/Foundation.h> #import "PGPTypes.h" +#import <Foundation/Foundation.h> @interface PGPPKCSEmsa : NSObject -+ (NSData *) encode:(PGPHashAlgorithm)hashAlgorithm message:(NSData *)m encodedMessageLength:(NSUInteger)emLen error:(NSError * __autoreleasing *)error; ++ (NSData *)encode:(PGPHashAlgorithm)hashAlgorithm message:(NSData *)m encodedMessageLength:(NSUInteger)emLen error:(NSError *__autoreleasing *)error; @end diff --git a/PGPPKCSEmsa.m b/enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.m similarity index 53% rename from PGPPKCSEmsa.m rename to enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.m index 2ea4668e..ba55a95a 100644 --- a/PGPPKCSEmsa.m +++ b/enzevalos_iphone/ObjectivePGP/PGPPKCSEmsa.m @@ -7,50 +7,24 @@ // #import "PGPPKCSEmsa.h" -#import "PGPTypes.h" #import "NSData+PGPUtils.h" +#import "PGPMacros+Private.h" #import "PGPCryptoUtils.h" +#import "PGPTypes.h" -static UInt8 prefix_md5[] = { - 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, - 0x04, 0x10 -}; - -static UInt8 prefix_sha1[] = { - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, - 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 -}; +static UInt8 prefix_md5[] = {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; -static UInt8 prefix_sha224[] = { - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, - 0x00, 0x04, 0x1C -}; +static UInt8 prefix_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; -static UInt8 prefix_sha256[] = { - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, - 0x00, 0x04, 0x20 -}; +static UInt8 prefix_sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C}; -static UInt8 prefix_sha384[] = { - 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, - 0x00, 0x04, 0x30 -}; +static UInt8 prefix_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; -static UInt8 prefix_sha512[] = { - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40 -}; +static UInt8 prefix_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; -static UInt8 prefix_ripemd160[] = { - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, - 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 -}; +static UInt8 prefix_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; +static UInt8 prefix_ripemd160[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14}; @implementation PGPPKCSEmsa @@ -63,67 +37,52 @@ static UInt8 prefix_ripemd160[] = { * * @return encoded message */ -+ (NSData *) encode:(PGPHashAlgorithm)hashAlgorithm message:(NSData *)m encodedMessageLength:(NSUInteger)emLength error:(NSError * __autoreleasing *)error -{ - NSMutableData *tData = [NSMutableData data]; // prefix + hash ++ (NSData *)encode:(PGPHashAlgorithm)hashAlgorithm message:(NSData *)m encodedMessageLength:(NSUInteger)emLength error:(NSError *__autoreleasing *)error { + let tData = [NSMutableData data]; // prefix + hash switch (hashAlgorithm) { - case PGPHashMD5: - { + case PGPHashMD5: { NSData *hashPrefixData = [NSData dataWithBytes:prefix_md5 length:sizeof(prefix_md5)]; [tData appendData:hashPrefixData]; - [tData appendData:[m pgp_MD5]]; - } - break; - case PGPHashSHA1: - { + [tData appendData:m.pgp_MD5]; + } break; + case PGPHashSHA1: { NSData *hashPrefixData = [NSData dataWithBytes:prefix_sha1 length:sizeof(prefix_sha1)]; [tData appendData:hashPrefixData]; - [tData appendData:[m pgp_SHA1]]; - } - break; - case PGPHashSHA224: - { + [tData appendData:m.pgp_SHA1]; + } break; + case PGPHashSHA224: { NSData *hashPrefixData = [NSData dataWithBytes:prefix_sha224 length:sizeof(prefix_sha224)]; [tData appendData:hashPrefixData]; - [tData appendData:[m pgp_SHA224]]; - } - break; - case PGPHashSHA256: - { + [tData appendData:m.pgp_SHA224]; + } break; + case PGPHashSHA256: { NSData *hashPrefixData = [NSData dataWithBytes:prefix_sha256 length:sizeof(prefix_sha256)]; [tData appendData:hashPrefixData]; - [tData appendData:[m pgp_SHA256]]; - } - break; - case PGPHashSHA384: - { + [tData appendData:m.pgp_SHA256]; + } break; + case PGPHashSHA384: { NSData *hashPrefixData = [NSData dataWithBytes:prefix_sha384 length:sizeof(prefix_sha384)]; [tData appendData:hashPrefixData]; - [tData appendData:[m pgp_SHA384]]; - } - break; - case PGPHashSHA512: - { + [tData appendData:m.pgp_SHA384]; + } break; + case PGPHashSHA512: { NSData *hashPrefixData = [NSData dataWithBytes:prefix_sha512 length:sizeof(prefix_sha512)]; [tData appendData:hashPrefixData]; - [tData appendData:[m pgp_SHA512]]; - } - break; - case PGPHashRIPEMD160: - { + [tData appendData:m.pgp_SHA512]; + } break; + case PGPHashRIPEMD160: { NSData *hashPrefixData = [NSData dataWithBytes:prefix_ripemd160 length:sizeof(prefix_ripemd160)]; [tData appendData:hashPrefixData]; - [tData appendData:[m pgp_RIPEMD160]]; - } - break; + [tData appendData:m.pgp_RIPEMD160]; + } break; default: - NSAssert(false,@"Missing implementation"); + NSAssert(false, @"Missing implementation"); break; } - + if (emLength < tData.length + 11) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"intended encoded message length too short"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"intended encoded message length too short" }]; } return nil; } diff --git a/PGPPacketFactory.h b/enzevalos_iphone/ObjectivePGP/PGPPacketFactory.h similarity index 59% rename from PGPPacketFactory.h rename to enzevalos_iphone/ObjectivePGP/PGPPacketFactory.h index 7bd5e70e..15f3c746 100644 --- a/PGPPacketFactory.h +++ b/enzevalos_iphone/ObjectivePGP/PGPPacketFactory.h @@ -6,12 +6,16 @@ // Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. // -#import <Foundation/Foundation.h> -#import "PGPTypes.h" #import "PGPPacket.h" +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN @interface PGPPacketFactory : NSObject -+ (PGPPacket *) packetWithData:(NSData *)packetsData offset:(NSUInteger)offset nextPacketOffset:(NSUInteger *)nextPacketOffset; ++ (nullable PGPPacket *)packetWithData:(NSData *)packetsData offset:(NSUInteger)offset nextPacketOffset:(nullable NSUInteger *)nextPacketOffset; @end + +NS_ASSUME_NONNULL_END diff --git a/PGPPacketFactory.m b/enzevalos_iphone/ObjectivePGP/PGPPacketFactory.m similarity index 77% rename from PGPPacketFactory.m rename to enzevalos_iphone/ObjectivePGP/PGPPacketFactory.m index eaa94423..dd2464dd 100644 --- a/PGPPacketFactory.m +++ b/enzevalos_iphone/ObjectivePGP/PGPPacketFactory.m @@ -7,49 +7,49 @@ // #import "PGPPacketFactory.h" +#import "PGPCompressedPacket.h" +#import "PGPLiteralPacket.h" +#import "PGPModificationDetectionCodePacket.h" +#import "PGPOnePassSignaturePacket.h" +#import "PGPPublicKeyEncryptedSessionKeyPacket.h" #import "PGPPublicKeyPacket.h" #import "PGPPublicSubKeyPacket.h" -#import "PGPSignaturePacket.h" -#import "PGPUserIDPacket.h" -#import "PGPTrustPacket.h" #import "PGPSecretKeyPacket.h" #import "PGPSecretSubKeyPacket.h" -#import "PGPLiteralPacket.h" -#import "PGPModificationDetectionCodePacket.h" -#import "PGPUserAttributePacket.h" -#import "PGPOnePassSignaturePacket.h" -#import "PGPCompressedPacket.h" +#import "PGPSignaturePacket.h" #import "PGPSymmetricallyEncryptedDataPacket.h" #import "PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h" -#import "PGPPublicKeyEncryptedSessionKeyPacket.h" +#import "PGPTrustPacket.h" +#import "PGPUserAttributePacket.h" +#import "PGPUserIDPacket.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN @implementation PGPPacketFactory /** * Parse packet data and return packet object instance *cc - * @param packetsData Data with all packets. Packet sequence data. Keyring. - * @param offset offset of current packet + * @param packetData Data with all the packets. Packet sequence data. Keyring. + * @param offset offset of current packet * * @return Packet instance object */ -+ (PGPPacket * ) packetWithData:(NSData *)packetData offset:(NSUInteger)offset nextPacketOffset:(NSUInteger *)nextPacketOffset -{ - ++ (nullable PGPPacket *)packetWithData:(NSData *)packetData offset:(NSUInteger)offset nextPacketOffset:(nullable NSUInteger *)nextPacketOffset { // parse header and get actual header data - PGPPacketTag packetTag = 0; - NSData *data = [packetData subdataWithRange:(NSRange) {offset, packetData.length - offset}]; - UInt32 headerLength; - BOOL indeterminateLength; - NSData *packetBodyData = [PGPPacket parsePacketHeader:data headerLength:&headerLength nextPacketOffset:nextPacketOffset packetTag:&packetTag indeterminateLength:&indeterminateLength]; - NSData *packetHeaderData = [packetData subdataWithRange:(NSRange) {offset, headerLength}]; + UInt32 headerLength = 0; + BOOL indeterminateLength = NO; + let data = [packetData subdataWithRange:(NSRange){offset, packetData.length - offset}]; + let packetBodyData = [PGPPacket parsePacketHeader:data headerLength:&headerLength nextPacketOffset:nextPacketOffset packetTag:&packetTag indeterminateLength:&indeterminateLength]; + let packetHeaderData = [packetData subdataWithRange:(NSRange){offset, headerLength}]; - if (packetHeaderData.length > 0) { - // Analyze body0 - PGPPacket * packet = nil; + PGPPacket *packet = nil; switch (packetTag) { case PGPPublicKeyPacketTag: packet = [[PGPPublicKeyPacket alloc] initWithHeader:packetHeaderData body:packetBodyData]; @@ -87,9 +87,9 @@ case PGPCompressedDataPacketTag: packet = [[PGPCompressedPacket alloc] initWithHeader:packetHeaderData body:packetBodyData]; break; -// case PGPSymmetricallyEncryptedDataPacketTag: -// packet = [[PGPSymmetricallyEncryptedDataPacket alloc] initWithHeader:packetHeaderData body:packetBodyData]; -// break; + // case PGPSymmetricallyEncryptedDataPacketTag: + // packet = [[PGPSymmetricallyEncryptedDataPacket alloc] initWithHeader:packetHeaderData body:packetBodyData]; + // break; case PGPSymmetricallyEncryptedIntegrityProtectedDataPacketTag: packet = [[PGPSymmetricallyEncryptedIntegrityProtectedDataPacket alloc] initWithHeader:packetHeaderData body:packetBodyData]; break; @@ -97,14 +97,11 @@ packet = [[PGPPublicKeyEncryptedSessionKeyPacket alloc] initWithHeader:packetHeaderData body:packetBodyData]; break; default: - #ifdef DEBUG - NSLog(@"Warning %s Packet tag %d is not supported", __PRETTY_FUNCTION__, packetTag); - #endif - + PGPLogWarning(@"Packet tag %@ is not supported", @(packetTag)); packet = [[PGPPacket alloc] initWithHeader:packetHeaderData body:packetBodyData]; break; } - + if (indeterminateLength) { packet.indeterminateLength = YES; } @@ -114,3 +111,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPPartialKey.h b/enzevalos_iphone/ObjectivePGP/PGPPartialKey.h new file mode 100644 index 00000000..e38f9332 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPPartialKey.h @@ -0,0 +1,70 @@ +// +// PGPTransferableKey.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 13/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPExportableProtocol.h" +#import "PGPKeyID.h" +#import "PGPPacket.h" +#import "PGPSignaturePacket.h" +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, PGPPartialKeyType) { PGPPartialKeyUnknown = 0, PGPPartialKeySecret = 1, PGPPartialKeyPublic = 2 }; + +@class PGPSecretKeyPacket, PGPPartialSubKey; + +/// Single Private or Public key. +@interface PGPPartialKey : NSObject <PGPExportable> + +@property (nonatomic, readonly) PGPPartialKeyType type; +@property (nonatomic) PGPPacket *primaryKeyPacket; +@property (nonatomic, readonly) BOOL isEncrypted; +@property (nonatomic, copy) NSArray<PGPUser *> *users; +@property (nonatomic, copy) NSArray<PGPPartialSubKey *> *subKeys; // TODO: nullable +@property (nonatomic, nullable, copy) NSArray<PGPSignaturePacket *> *directSignatures; +@property (nonatomic, nullable) PGPPacket *revocationSignature; +@property (nonatomic, nullable, readonly) NSDate *expirationDate; + +@property (nonatomic, readonly) PGPKeyID *keyID; +@property (nonatomic, readonly) PGPFingerprint *fingerprint; + +PGP_EMPTY_INIT_UNAVAILABLE; + +- (instancetype)initWithPackets:(NSArray<PGPPacket *> *)packets NS_DESIGNATED_INITIALIZER; + +/** + * Decrypts all secret key and subkey packets + * Note: After decryption encrypted packets are replaced with new decrypted instances on key. + * Warning: It is not good idea to keep decrypted key around + * + * @param passphrase Passphrase + * @param error error + * + * @return YES on success. + */ +- (BOOL)decrypt:(NSString *)passphrase error:(NSError *__autoreleasing *)error; + +/** + * Signing key packet + * + * @return PGPSecureKeyPacket that can be used to signing + */ +@property (nonatomic, nullable, readonly) PGPPacket *signingKeyPacket; + +- (nullable PGPPacket *)signingKeyPacketWithKeyID:(PGPKeyID *)keyID; +- (nullable PGPPacket *)encryptionKeyPacket:(NSError *__autoreleasing *)error; +- (nullable PGPSecretKeyPacket *)decryptionKeyPacketWithID:(PGPKeyID *)keyID error:(NSError *__autoreleasing *)error; + +- (NSArray<PGPPacket *> *)allKeyPackets; +- (PGPSymmetricAlgorithm)preferredSymmetricAlgorithm; ++ (PGPSymmetricAlgorithm)preferredSymmetricAlgorithmForKeys:(NSArray<PGPPartialKey *> *)keys; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPPartialKey.m b/enzevalos_iphone/ObjectivePGP/PGPPartialKey.m new file mode 100644 index 00000000..5a593168 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPPartialKey.m @@ -0,0 +1,498 @@ +// +// PGPTransferableKey.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 13/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPartialKey.h" +#import "PGPLogging.h" +#import "PGPPublicKeyPacket.h" +#import "PGPPublicSubKeyPacket.h" +#import "PGPSecretKeyPacket.h" +#import "PGPSecretSubKeyPacket.h" +#import "PGPSignaturePacket.h" +#import "PGPSignatureSubpacket.h" +#import "PGPPartialSubKey.h" +#import "PGPUser.h" +#import "PGPUserAttributePacket.h" +#import "PGPUserAttributeSubpacket.h" +#import "PGPMacros+Private.h" +#import "PGPFoundation.h" +#import "NSMutableData+PGPUtils.h" +#import "PGPFoundation.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPPartialKey + +- (instancetype)initWithPackets:(NSArray<PGPPacket *> *)packets { + if ((self = [super init])) { + _subKeys = [NSArray<PGPPartialSubKey *> array]; + _directSignatures = [NSArray<PGPSignaturePacket *> array]; + _users = [NSArray<PGPUser *> array]; + [self loadPackets:packets]; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"Type %@, %@ primary key: %@", self.type == PGPPartialKeyPublic ? @"public" : @"secret", [super description], self.primaryKeyPacket]; +} + +- (BOOL)isEncrypted { + if (self.type == PGPPartialKeySecret) { + return PGPCast(self.primaryKeyPacket, PGPSecretKeyPacket).isEncryptedWithPassphrase; + } + return NO; +} + +- (nullable NSDate *)expirationDate { + PGPSignaturePacket * _Nullable primaryUserSelfCertificate = nil; + [self primaryUserAndSelfCertificate:&primaryUserSelfCertificate]; + if (primaryUserSelfCertificate.expirationDate) { + return primaryUserSelfCertificate.expirationDate; + } + + for (PGPPartialSubKey *subKey in self.subKeys) { + if (PGPEqualObjects(subKey.keyID,self.keyID)) { + let _Nullable signaturePacket = subKey.bindingSignature; + if (signaturePacket && signaturePacket.expirationDate) { + return signaturePacket.expirationDate; + } + } + } + return nil; +} + +- (PGPPartialKeyType)type { + PGPPartialKeyType t = PGPPartialKeyUnknown; + + switch (self.primaryKeyPacket.tag) { + case PGPPublicKeyPacketTag: + case PGPPublicSubkeyPacketTag: + t = PGPPartialKeyPublic; + break; + case PGPSecretKeyPacketTag: + case PGPSecretSubkeyPacketTag: + t = PGPPartialKeySecret; + break; + default: + break; + } + + return t; +} + +- (PGPKeyID *)keyID { + let primaryKeyPacket = PGPCast(self.primaryKeyPacket, PGPPublicKeyPacket); + NSParameterAssert(primaryKeyPacket); + return [[PGPKeyID alloc] initWithFingerprint:primaryKeyPacket.fingerprint]; +} + +- (PGPFingerprint *)fingerprint { + let primaryKeyPacket = PGPCast(self.primaryKeyPacket, PGPPublicKeyPacket); + NSParameterAssert(primaryKeyPacket); + return primaryKeyPacket.fingerprint; +} + +- (void)loadPackets:(NSArray<PGPPacket *> *)packets { + // based on packetlist2structure + PGPKeyID *primaryKeyID; + PGPPartialSubKey *subKey; + PGPUser *user; + + for (PGPPacket *packet in packets) { + switch (packet.tag) { + case PGPPublicKeyPacketTag: + primaryKeyID = PGPCast(packet, PGPPublicKeyPacket).keyID; + self.primaryKeyPacket = packet; + break; + case PGPSecretKeyPacketTag: + primaryKeyID = PGPCast(packet, PGPPublicKeyPacket).keyID; + self.primaryKeyPacket = packet; + break; + case PGPUserAttributePacketTag: + if (!user) { + continue; + } + user.userAttribute = PGPCast(packet, PGPUserAttributePacket); + break; + case PGPUserIDPacketTag: { + let parsedUser = [[PGPUser alloc] initWithUserIDPacket:(PGPUserIDPacket *)packet]; + if (!user) { + user = parsedUser; + } + self.users = [self.users arrayByAddingObject:parsedUser]; + } break; + case PGPPublicSubkeyPacketTag: + case PGPSecretSubkeyPacketTag: + user = nil; + subKey = [[PGPPartialSubKey alloc] initWithPackets:@[packet]]; + self.subKeys = [self.subKeys arrayByAddingObject:subKey]; + break; + case PGPSignaturePacketTag: { + let signaturePacket = PGPCast(packet, PGPSignaturePacket); + switch (signaturePacket.type) { + case PGPSignatureGenericCertificationUserIDandPublicKey: + case PGPSignatureCasualCertificationUserIDandPublicKey: + case PGPSignaturePositiveCertificationUserIDandPublicKey: + case PGPSignaturePersonalCertificationUserIDandPublicKey: + if (!user) { + continue; + } + if (PGPEqualObjects(signaturePacket.issuerKeyID,primaryKeyID)) { + user.selfCertifications = [user.selfCertifications arrayByAddingObject:signaturePacket]; + } else { + user.otherSignatures = [user.otherSignatures arrayByAddingObject:signaturePacket]; + } + break; + case PGPSignatureCertificationRevocation: + if (user) { + user.revocationSignatures = [user.revocationSignatures arrayByAddingObject:signaturePacket]; + } else { + self.directSignatures = [self.directSignatures arrayByAddingObject:signaturePacket]; + } + break; + case PGPSignatureDirectlyOnKey: + self.directSignatures = [self.directSignatures arrayByAddingObject:signaturePacket]; + break; + case PGPSignatureSubkeyBinding: + if (!subKey) { + continue; + } + subKey.bindingSignature = PGPCast(packet, PGPSignaturePacket); + break; + case PGPSignatureKeyRevocation: + self.revocationSignature = PGPCast(packet, PGPSignaturePacket); + break; + case PGPSignatureSubkeyRevocation: + if (!subKey) { + continue; + } + subKey.revocationSignature = PGPCast(packet, PGPSignaturePacket); + break; + default: + break; + } + } break; + default: + break; + } + } +} + +// signature packet that is available for signing data +- (nullable PGPPacket *)signingKeyPacket { + // It's private key for sign and public for verify as so thi can't be checked here + + NSAssert(self.type == PGPPartialKeySecret, @"Need secret key to sign"); + if (self.type == PGPPartialKeyPublic) { + PGPLogDebug(@"Need secret key to sign\n %@", [NSThread callStackSymbols]); + return nil; + } + + // check primary user self certificates + PGPSignaturePacket *primaryUserSelfCertificate = nil; + [self primaryUserAndSelfCertificate:&primaryUserSelfCertificate]; + if (primaryUserSelfCertificate) { + if (primaryUserSelfCertificate.canBeUsedToSign) { + return self.primaryKeyPacket; + } + } + + for (PGPPartialSubKey *subKey in self.subKeys) { + PGPSignaturePacket *signaturePacket = subKey.bindingSignature; + if (signaturePacket.canBeUsedToSign) { + return subKey.primaryKeyPacket; + } + } + + // By convention, the top-level key provides signature services + return PGPCast(self.primaryKeyPacket, PGPSecretKeyPacket); +} + +// signature packet that is available for verifying signature with a keyID +- (nullable PGPPacket *)signingKeyPacketWithKeyID:(PGPKeyID *)keyID { + // check primary user self certificates + PGPSignaturePacket *primaryUserSelfCertificate = nil; + [self primaryUserAndSelfCertificate:&primaryUserSelfCertificate]; + if (primaryUserSelfCertificate) { + if (PGPEqualObjects(self.keyID,keyID)) { + if (primaryUserSelfCertificate.canBeUsedToSign) { + return self.primaryKeyPacket; + } + } + } + + for (PGPPartialSubKey *subKey in self.subKeys) { + if (PGPEqualObjects(subKey.keyID,keyID)) { + PGPSignaturePacket *signaturePacket = subKey.bindingSignature; + if (signaturePacket.canBeUsedToSign) { + return subKey.primaryKeyPacket; + } + } + } + + // By convention, the top-level key provides signature services + return PGPCast(self.primaryKeyPacket, PGPSecretKeyPacket); +} + +// signature packet that is available for signing data +- (nullable PGPPacket *)encryptionKeyPacket:(NSError *__autoreleasing *)error { + NSAssert(self.type == PGPPartialKeyPublic, @"Need public key to encrypt"); + if (self.type == PGPPartialKeySecret) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Wrong key type, require public key" }]; + } + PGPLogWarning(@"Need public key to encrypt"); + return nil; + } + + for (PGPPartialSubKey *subKey in self.subKeys) { + let signaturePacket = subKey.bindingSignature; + if (signaturePacket.canBeUsedToEncrypt) { + return subKey.primaryKeyPacket; + } + } + + // check primary user self certificates + PGPSignaturePacket *primaryUserSelfCertificate = nil; + [self primaryUserAndSelfCertificate:&primaryUserSelfCertificate]; + if (primaryUserSelfCertificate) { + if (primaryUserSelfCertificate.canBeUsedToEncrypt) { + return self.primaryKeyPacket; + } + } + + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Encryption key not found" }]; + } + + return nil; +} + +- (nullable PGPSecretKeyPacket *)decryptionKeyPacketWithID:(PGPKeyID *)keyID error:(NSError *__autoreleasing *)error { + NSAssert(self.type == PGPPartialKeySecret, @"Need secret key to encrypt"); + if (self.type == PGPPartialKeyPublic) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Wrong key type, require secret key" }]; + } + PGPLogWarning(@"Need public key to encrypt"); + return nil; + } + + for (PGPPartialSubKey *subKey in self.subKeys) { + let signaturePacket = subKey.bindingSignature; + if (signaturePacket.canBeUsedToEncrypt && PGPEqualObjects(PGPCast(subKey.primaryKeyPacket, PGPSecretKeyPacket).keyID, keyID)) { + return PGPCast(subKey.primaryKeyPacket, PGPSecretKeyPacket); + } + } + + // assume primary key is always cabable + if (PGPEqualObjects(PGPCast(self.primaryKeyPacket, PGPSecretKeyPacket).keyID, keyID)) { + return PGPCast(self.primaryKeyPacket, PGPSecretKeyPacket); + } + return nil; +} + +// Note: After decryption encrypted packets are replaced with new decrypted instances on key. +// TODO: return error +- (BOOL)decrypt:(NSString *)passphrase error:(NSError *__autoreleasing *)error { + let primarySecretPacket = PGPCast(self.primaryKeyPacket, PGPSecretKeyPacket); + if (!primarySecretPacket) { + return NO; + } + + // decrypt primary packet + var decryptedPrimaryPacket = [primarySecretPacket decryptedKeyPacket:passphrase error:error]; + if (!decryptedPrimaryPacket) { + return NO; + } + + // decrypt subkeys packets + for (PGPPartialSubKey *subKey in self.subKeys) { + let subKeySecretPacket = PGPCast(subKey.primaryKeyPacket, PGPSecretKeyPacket); + if (subKeySecretPacket) { + let subKeyDecryptedPacket = [subKeySecretPacket decryptedKeyPacket:passphrase error:error]; + if (!subKeyDecryptedPacket) { + return NO; + } + subKey.primaryKeyPacket = subKeyDecryptedPacket; + } + } + + self.primaryKeyPacket = decryptedPrimaryPacket; + return YES; +} + +#pragma mark - isEqual + +- (BOOL)isEqual:(id)other { + if (self == other) { return YES; } + if ([other isKindOfClass:self.class]) { + return [self isEqualToPartialKey:other]; + } + return NO; +} + +- (BOOL)isEqualToPartialKey:(PGPPartialKey *)other { + return self.type == other.type && + self.isEncrypted == other.isEncrypted && + PGPEqualObjects(self.primaryKeyPacket, other.primaryKeyPacket) && + PGPEqualObjects(self.users, other.users) && + PGPEqualObjects(self.subKeys, other.subKeys) && + PGPEqualObjects(self.directSignatures, other.directSignatures) && + PGPEqualObjects(self.revocationSignature, other.revocationSignature) && + PGPEqualObjects(self.keyID, other.keyID); +} + +- (NSUInteger)hash { + NSUInteger prime = 31; + NSUInteger result = 1; + + result = prime * result + self.type; + result = prime * result + self.isEncrypted; + result = prime * result + self.primaryKeyPacket.hash; + result = prime * result + self.users.hash; + result = prime * result + self.subKeys.hash; + result = prime * result + self.directSignatures.hash; + result = prime * result + self.revocationSignature.hash; + result = prime * result + self.keyID.hash; + + return result; +} + +#pragma mark - PGPExportable + +- (nullable NSData *)export:(NSError *_Nullable __autoreleasing *)error { + let result = [NSMutableData data]; + + for (PGPPacket *packet in self.allPacketsArray) { + let exported = [packet export:error]; + if (!exported) { + continue; + } + + [result pgp_appendData:exported]; // TODO: decode secret key first + if (error) { + NSAssert(*error == nil, @"Error while export public key"); + if (*error) { + return nil; + } + } + } + return result; +} + +#pragma mark - Verification + +// Returns primary user with self certificate +- (nullable PGPUser *)primaryUserAndSelfCertificate:(PGPSignaturePacket *__autoreleasing *)selfCertificateOut { + PGPUser *foundUser = nil; + + for (PGPUser *user in self.users) { + if (!user.userID || user.userID.length == 0) { + continue; + } + + let selfCertificate = [user validSelfCertificate:self]; + if (!selfCertificate) { + continue; + } + + if (selfCertificate.isPrimaryUserID) { + foundUser = user; + } else if (!foundUser) { + foundUser = user; + } + *selfCertificateOut = selfCertificate; + } + return foundUser; +} + +#pragma mark - Preferences + +- (PGPSymmetricAlgorithm)preferredSymmetricAlgorithm { + return [[self class] preferredSymmetricAlgorithmForKeys:@[self]]; +} + ++ (PGPSymmetricAlgorithm)preferredSymmetricAlgorithmForKeys:(NSArray<PGPPartialKey *> *)keys { + // 13.2. Symmetric Algorithm Preferences + // Since TripleDES is the MUST-implement algorithm, if it is not explicitly in the list, it is tacitly at the end. + + let preferecesArray = [NSMutableArray<NSArray<NSNumber *> *> array]; + for (PGPPartialKey *key in keys) { + let keyAlgorithms = [NSMutableArray<NSNumber *> array]; + + PGPSignaturePacket *selfCertificate = nil; + let primaryUser = [key primaryUserAndSelfCertificate:&selfCertificate]; + if (primaryUser && selfCertificate) { + let signatureSubpacket = [[selfCertificate subpacketsOfType:PGPSignatureSubpacketTypePreferredSymetricAlgorithm] firstObject]; + NSArray<NSNumber *> * _Nullable preferredSymetricAlgorithms = PGPCast(signatureSubpacket.value, NSArray); + if (preferredSymetricAlgorithms) { + [keyAlgorithms addObjectsFromArray:preferredSymetricAlgorithms]; + } + } + + if (keyAlgorithms.count > 0) { + [preferecesArray addObject:keyAlgorithms]; + } + } + + // intersect + if (preferecesArray.count > 0) { + let set = [NSMutableOrderedSet<NSNumber *> orderedSetWithArray:preferecesArray[0]]; + for (NSArray<NSNumber *> *prefArray in preferecesArray) { + [set intersectSet:[NSSet setWithArray:prefArray]]; + } + return (PGPSymmetricAlgorithm)[set[0] unsignedIntValue]; + } + + return PGPSymmetricTripleDES; +} + +#pragma mark - Private + +/** + * Ordered list of packets. Trust Packet is not exported. + * + * @return array + */ +- (NSArray<PGPPacket *> *)allPacketsArray { + // TODO: handle trust packet somehow. The Trust packet is used only within keyrings and is not normally exported. + let arr = [NSMutableArray<PGPPacket *> array]; + + [arr addObject:self.primaryKeyPacket]; + + if (self.revocationSignature) { + [arr addObject:PGPNN(self.revocationSignature)]; + } + + for (PGPSignaturePacket *packet in self.directSignatures) { + [arr addObject:packet]; + } + + for (PGPUser *user in self.users) { + [arr addObjectsFromArray:[user allPackets]]; + } + + for (PGPPartialSubKey *subKey in self.subKeys) { + [arr addObjectsFromArray:[subKey allPackets]]; + } + + return arr; +} + +- (NSArray<PGPPacket *> *)allKeyPackets { + let arr = [NSMutableArray<PGPPacket *> arrayWithObject:self.primaryKeyPacket]; + for (PGPPartialSubKey *subKey in self.subKeys) { + [arr addObject:subKey.primaryKeyPacket]; + } + return arr; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.h b/enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.h new file mode 100644 index 00000000..886a89a9 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.h @@ -0,0 +1,27 @@ +// +// PGPPartialSubKey.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 16/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPKeyID.h" +#import "PGPPartialKey.h" + +NS_ASSUME_NONNULL_BEGIN + +@class PGPSignaturePacket; + +@interface PGPPartialSubKey : PGPPartialKey + +PGP_EMPTY_INIT_UNAVAILABLE + +@property (nonatomic, nullable) PGPSignaturePacket *bindingSignature; +@property (nonatomic, readonly) PGPKeyID *keyID; + +- (NSArray<PGPPacket *> *)allPackets; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.m b/enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.m new file mode 100644 index 00000000..6bf2d399 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPPartialSubKey.m @@ -0,0 +1,52 @@ +// +// PGPPartialSubKey.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 16/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPartialSubKey.h" +#import "PGPPublicKeyPacket.h" +#import "PGPFoundation.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPPartialSubKey + +- (instancetype)initWithPackets:(NSArray<PGPPacket *> *)packets { + if ((self = [super initWithPackets:@[]])) { + self.primaryKeyPacket = packets.firstObject; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %@", super.description, self.primaryKeyPacket.description]; +} + +- (PGPKeyID *)keyID { + // note: public key packet because this is main class for public and secret class + let primaryKeyPacket = PGPCast(self.primaryKeyPacket, PGPPublicKeyPacket); + NSCAssert(primaryKeyPacket, @"Invalid packet"); + return [[PGPKeyID alloc] initWithFingerprint:primaryKeyPacket.fingerprint]; +} + +- (NSArray<PGPPacket *> *)allPackets { + let arr = [NSMutableArray<PGPPacket *> arrayWithObject:self.primaryKeyPacket]; + + if (self.revocationSignature) { + [arr addObject:PGPNN(self.revocationSignature)]; + } + + if (self.bindingSignature) { + [arr addObject:PGPNN(self.bindingSignature)]; + } + + return arr; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPS2K.h b/enzevalos_iphone/ObjectivePGP/PGPS2K.h new file mode 100644 index 00000000..21b59166 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPS2K.h @@ -0,0 +1,36 @@ +// +// PGPS2K.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 07/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPMacros.h" +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPS2K : NSObject <NSCopying> + +@property (nonatomic, readonly) PGPS2KSpecifier specifier; +@property (nonatomic, readonly) PGPHashAlgorithm hashAlgorithm; +// random 8 bytes. +@property (nonatomic, copy, readonly) NSData *salt; +// Iteration count. +@property (nonatomic) UInt32 iterationsCount; + +PGP_EMPTY_INIT_UNAVAILABLE + +- (instancetype)initWithSpecifier:(PGPS2KSpecifier)specifier hashAlgorithm:(PGPHashAlgorithm)hashAlgorithm NS_DESIGNATED_INITIALIZER; + ++ (PGPS2K *)S2KFromData:(NSData *)data atPosition:(NSUInteger)position length:(nullable NSUInteger *)length; + +- (nullable NSData *)buildKeyDataForPassphrase:(NSData *)passphrase prefix:(nullable NSData *)prefix salt:(NSData *)salt codedCount:(UInt32)codedCount; +- (nullable NSData *)produceSessionKeyWithPassphrase:(NSString *)passphrase symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm; +- (nullable NSData *)export:(NSError *__autoreleasing *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPS2K.m b/enzevalos_iphone/ObjectivePGP/PGPS2K.m new file mode 100644 index 00000000..d2a48e5c --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPS2K.m @@ -0,0 +1,263 @@ +// +// PGPS2K.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 07/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// +// A string to key (S2K) specifier encodes a mechanism for producing a key to be used with a symmetric block cipher from a string of octets. +// + +#import "PGPS2K.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +#import <CommonCrypto/CommonCrypto.h> +#import <CommonCrypto/CommonDigest.h> + +#import "NSData+PGPUtils.h" +#import "NSMutableData+PGPUtils.h" +#import "PGPCryptoHash.h" +#import "PGPCryptoUtils.h" +#import "PGPFoundation.h" + +NS_ASSUME_NONNULL_BEGIN + +static const unsigned int PGP_SALT_SIZE = 8; +static const unsigned int PGP_DEFAULT_ITERATIONS_COUNT = 215; + +@interface PGPS2K () + +@property (nonatomic, copy, readwrite) NSData *salt; + +@end + +@implementation PGPS2K + +- (instancetype)initWithSpecifier:(PGPS2KSpecifier)specifier hashAlgorithm:(PGPHashAlgorithm)hashAlgorithm { + if ((self = [super init])) { + _specifier = specifier; + _hashAlgorithm = hashAlgorithm; + _salt = [PGPCryptoUtils randomData:PGP_SALT_SIZE]; + _iterationsCount = PGP_DEFAULT_ITERATIONS_COUNT; + } + return self; +} + ++ (PGPS2K *)S2KFromData:(NSData *)data atPosition:(NSUInteger)position length:(nullable NSUInteger *)length { + PGPAssertClass(data, NSData); + + PGPS2K *s2k = [[PGPS2K alloc] initWithSpecifier:PGPS2KSpecifierSimple hashAlgorithm:PGPHashSHA1]; // just default values, overriden in next line + NSUInteger positionAfter = [s2k parseS2K:data atPosition:position]; + if (length) { + *length = MAX(positionAfter - position, (NSUInteger)0); + } + return s2k; +} + +- (NSUInteger)parseS2K:(NSData *)data atPosition:(NSUInteger)startingPosition { + // S2K + + // string-to-key specifier is being given + NSUInteger position = startingPosition; + [data getBytes:&_specifier range:(NSRange){position, 1}]; + position = position + 1; + + NSAssert(_specifier == PGPS2KSpecifierIteratedAndSalted || _specifier == PGPS2KSpecifierSalted || _specifier == PGPS2KSpecifierSimple || _specifier == PGPS2KSpecifierGnuDummy, @"Bad s2k specifier"); + + // this is not documented, but now I need to read S2K key specified by s2kSpecifier + // 3.7.1.1. Simple S2K + + // Octet 1: hash algorithm + [data getBytes:&_hashAlgorithm range:(NSRange){position, 1}]; + position = position + 1; + + // Octets 2-9: 8-octet salt value + if (self.specifier == PGPS2KSpecifierSalted || self.specifier == PGPS2KSpecifierIteratedAndSalted) { + // read salt 8 bytes + self.salt = [data subdataWithRange:(NSRange){position, PGP_SALT_SIZE}]; + position = position + self.salt.length; + } + + // Octet 10: count, a one-octet, coded value + if (_specifier == PGPS2KSpecifierIteratedAndSalted) { + [data getBytes:&self->_iterationsCount range:(NSRange){position, 1}]; + position = position + 1; + } + + if (self.specifier == PGPS2KSpecifierGnuDummy) { + // read 3 bytes, and check if it's "GNU" followed by 0x01 || 0x02 + let gnuMarkerSize = 4; + let gnuString = [[NSString alloc] initWithData:[data subdataWithRange:(NSRange){position, gnuMarkerSize - 1}] encoding:NSASCIIStringEncoding]; + if (PGPEqualObjects(gnuString,@"GNU")) { + position = position + gnuMarkerSize; + } else { + PGPLogWarning(@"Unknown S2K"); + } + } + + return position; +} + +- (UInt32)codedIterationsCount { + if (self.iterationsCount > 65011712) { + return 255; + } + + return ((UInt32)16 + (self.iterationsCount & 15)) << ((self.iterationsCount >> 4) + 6); +} + +- (nullable NSData *)export:(NSError *__autoreleasing *)error { + NSMutableData *data = [NSMutableData data]; + [data appendBytes:&_specifier length:1]; + [data appendBytes:&_hashAlgorithm length:1]; + + if (self.specifier == PGPS2KSpecifierSalted || self.specifier == PGPS2KSpecifierIteratedAndSalted) { + [data appendData:self.salt]; + } + + if (self.specifier == PGPS2KSpecifierIteratedAndSalted) { + if (self.iterationsCount == 0) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Unexpected count: 0" }]; + } + return nil; + } + + [data appendBytes:&self->_iterationsCount length:1]; + } + + return data; +} + +- (nullable NSData *)buildKeyDataForPassphrase:(NSData *)passphrase prefix:(nullable NSData *)prefix salt:(NSData *)salt codedCount:(UInt32)codedCount { + PGPUpdateBlock updateBlock = nil; + switch (self.specifier) { + case PGPS2KSpecifierGnuDummy: + // no secret key + break; + case PGPS2KSpecifierSimple: { + let data = [NSMutableData dataWithData:prefix ?: [NSData data]]; + [data pgp_appendData:passphrase]; + + // passphrase + updateBlock = ^(PGP_NOESCAPE void (^update)(const void *data, int length)) { + update(data.bytes, (int)data.length); + }; + } break; + case PGPS2KSpecifierSalted: { + // salt + passphrase + // This includes a "salt" value in the S2K specifier -- some arbitrary + // data -- that gets hashed along with the passphrase string, to help + // prevent dictionary attacks. + let data = [NSMutableData dataWithData:prefix ?: [NSData data]]; + [data appendData:salt]; + [data pgp_appendData:passphrase]; + + updateBlock = ^(PGP_NOESCAPE void (^update)(const void *data, int length)) { + update(data.bytes, (int)data.length); + }; + } break; + case PGPS2KSpecifierIteratedAndSalted: { + // iterated (salt + passphrase) + let data = [NSMutableData dataWithData:salt]; + [data pgp_appendData:passphrase]; + + updateBlock = ^(PGP_NOESCAPE void (^update)(const void *data, int length)) { + // prefix first + update(prefix.bytes, (int)prefix.length); + + // then iterate + int iterations = 0; + while (iterations * data.length < codedCount) { + let nextTotalLength = (iterations + 1) * data.length; + if (nextTotalLength > codedCount) { + let totalLength = iterations * data.length; + let remainder = [data subdataWithRange:(NSRange){0, codedCount - totalLength}]; + update(remainder.bytes, (int)remainder.length); + } else { + update(data.bytes, (int)data.length); + } + iterations++; + } + }; + } break; + default: + // unknown or unsupported + break; + } + + if (updateBlock) { + return PGPCalculateHash(self.hashAlgorithm, updateBlock); + } + + return nil; +} + +/** + * Calculate key for given passphrase + * An S2K specifier can be stored in the secret keyring to specify how + * to convert the passphrase to a key that unlocks the secret data. + * Simple S2K hashes the passphrase to produce the session key. + * + * @param passphrase Passphrase + * @param symmetricAlgorithm Cipher algorithm + * + * @return NSData with key + */ +- (nullable NSData *)produceSessionKeyWithPassphrase:(NSString *)passphrase symmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm { + PGPAssertClass(passphrase, NSString); + + let passphraseData = [passphrase dataUsingEncoding:NSUTF8StringEncoding]; + var hashData = [self buildKeyDataForPassphrase:passphraseData prefix:nil salt:self.salt codedCount:self.codedIterationsCount]; + if (!hashData) { + return nil; + } + + // Keysize + NSUInteger keySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:symmetricAlgorithm]; + NSAssert(keySize <= 32, @"invalid keySize"); + + /* + If the hash size is less than the key size, multiple instances of the + hash context are created -- enough to produce the required key data. + These instances are preloaded with 0, 1, 2, ... octets of zeros (that + is to say, the first instance has no preloading, the second gets + preloaded with 1 octet of zero, the third is preloaded with two + octets of zeros, and so forth). + */ + if (hashData.length < keySize) { + var level = 1; + Byte zero = 0; + let prefix = [NSMutableData data]; + let expandedHashData = [NSMutableData dataWithData:hashData]; + while (expandedHashData.length < keySize) { + for (int i = 0; i < level; i++) { + [prefix appendBytes:&zero length:1]; + } + + let prefixedHashData = [self buildKeyDataForPassphrase:passphraseData prefix:prefix salt:self.salt codedCount:self.codedIterationsCount]; + [expandedHashData appendData:prefixedHashData]; + + level++; + } + hashData = expandedHashData.copy; + } + + // the high-order (leftmost) octets of the hash are used as the key. + return [hashData subdataWithRange:(NSRange){0, MIN(hashData.length, keySize)}]; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(nullable NSZone *)zone { + let copy = [[PGPS2K alloc] initWithSpecifier:self.specifier hashAlgorithm:self.hashAlgorithm]; + copy.salt = [self.salt copyWithZone:zone]; + copy.iterationsCount = self.iterationsCount; + return copy; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/PGPTypes.h b/enzevalos_iphone/ObjectivePGP/PGPTypes.h new file mode 100644 index 00000000..afbbaec7 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPTypes.h @@ -0,0 +1,188 @@ +// +// PGPTypes.h +// PGPKeyring +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +#ifndef NS_DESIGNATED_INITIALIZER +#define NS_DESIGNATED_INITIALIZER +#endif + +#define PGP_NOESCAPE __attribute__((noescape)) + +static NSString *const PGPErrorDomain = @"ObjectivePGP"; + +typedef NS_ENUM(NSInteger, PGPErrorCode) { + PGPErrorGeneral = -1, + PGPErrorPassphraseRequired = 5, + PGPErrorPassphraseInvalid = 6 +}; + +typedef NS_ENUM(NSInteger, PGPFormatType) { + PGPFormatUnknown = 0, + PGPFormatOld = 1, + PGPFormatNew = 2 +}; + +typedef NS_ENUM(NSUInteger, PGPHeaderPacketTag) { + PGPHeaderPacketTagNewFormat = 0x40, + PGPHeaderPacketTagAllwaysSet = 0x80 +}; + +typedef NS_ENUM(UInt8, PGPPacketTag) { + PGPInvalidPacketTag = 0, + PGPPublicKeyEncryptedSessionKeyPacketTag = 1, + PGPSignaturePacketTag = 2, + PGPSymetricKeyEncryptedSessionKeyPacketTag = 3, // TODO + PGPOnePassSignaturePacketTag = 4, + PGPSecretKeyPacketTag = 5, + PGPPublicKeyPacketTag = 6, + PGPSecretSubkeyPacketTag = 7, + PGPCompressedDataPacketTag = 8, + PGPSymmetricallyEncryptedDataPacketTag = 9, // TODO + PGPMarkerPacketTag = 10, // Ignored (Obsolete Literal Packet) + PGPLiteralDataPacketTag = 11, + PGPTrustPacketTag = 12, + PGPUserIDPacketTag = 13, + PGPPublicSubkeyPacketTag = 14, + PGPUserAttributePacketTag = 17, + PGPSymmetricallyEncryptedIntegrityProtectedDataPacketTag = 18, + PGPModificationDetectionCodePacketTag = 19, +}; + +// 9.1. Public-Key Algorithms +typedef NS_ENUM(UInt8, PGPPublicKeyAlgorithm) { + PGPPublicKeyAlgorithmRSA = 1, + PGPPublicKeyAlgorithmRSAEncryptOnly = 2, + PGPPublicKeyAlgorithmRSASignOnly = 3, + PGPPublicKeyAlgorithmElgamal = 16, // Elgamal (Encrypt-Only) + PGPPublicKeyAlgorithmDSA = 17, + PGPPublicKeyAlgorithmElliptic = 18, + PGPPublicKeyAlgorithmECDSA = 19, + PGPPublicKeyAlgorithmElgamalEncryptorSign = 20, // Deprecated ? + PGPPublicKeyAlgorithmDiffieHellman = 21, + PGPPublicKeyAlgorithmPrivate1 = 100, + PGPPublicKeyAlgorithmPrivate2 = 101, + PGPPublicKeyAlgorithmPrivate3 = 102, + PGPPublicKeyAlgorithmPrivate4 = 103, + PGPPublicKeyAlgorithmPrivate5 = 104, + PGPPublicKeyAlgorithmPrivate6 = 105, + PGPPublicKeyAlgorithmPrivate7 = 106, + PGPPublicKeyAlgorithmPrivate8 = 107, + PGPPublicKeyAlgorithmPrivate9 = 108, + PGPPublicKeyAlgorithmPrivate10 = 109, + PGPPublicKeyAlgorithmPrivate11 = 110 +}; + +// 9.2. Symmetric-Key Algorithms +typedef NS_ENUM(UInt8, PGPSymmetricAlgorithm) { + PGPSymmetricPlaintext = 0, + PGPSymmetricIDEA = 1, // 8 bytes (64-bit) block size, key length: 2 bytes (16 bit) + PGPSymmetricTripleDES = 2, // 8 bytes (64-bit) block size + PGPSymmetricCAST5 = 3, // aka CAST-128 is a symmetric block cipher with a block-size of 8 bytes (64bit) and a variable key-size of up to 16 bytes (128 bits). + PGPSymmetricBlowfish = 4, // 8 bytes (64 bit) block size, key length: 16 bits (4-56 bits) + PGPSymmetricAES128 = 7, // 16 bytes (128 bit), key length 128 bit + PGPSymmetricAES192 = 8, // 16 bytes (128 bit), key length 192 bit + PGPSymmetricAES256 = 9, // 16 bytes (128 bit), key length 256 bit + PGPSymmetricTwofish256 = 10, // 16 bytes (128 bit) + PGPSymmetricMax +}; + +// 9.4. Hash Algorithms +typedef NS_ENUM(UInt8, PGPHashAlgorithm) { + PGPHashUnknown = 0, + PGPHashMD5 = 1, // MD5 - deprecated + PGPHashSHA1 = 2, // SHA1 - required + PGPHashRIPEMD160 = 3, // RIPEMD160 + PGPHashSHA256 = 8, // SHA256 + PGPHashSHA384 = 9, // SHA384 + PGPHashSHA512 = 10, // SHA512 + PGPHashSHA224 = 11 // SHA224 +}; + +typedef NS_ENUM(UInt8, PGPSignatureType) { + PGPSignatureBinaryDocument = 0x00, + PGPSignatureCanonicalTextDocument = 0x01, + PGPSignatureStandalone = 0x02, + PGPSignatureGenericCertificationUserIDandPublicKey = 0x10, // Self-Signature + PGPSignaturePersonalCertificationUserIDandPublicKey = 0x11, // Self-Signature + PGPSignatureCasualCertificationUserIDandPublicKey = 0x12, // Self-Signature + PGPSignaturePositiveCertificationUserIDandPublicKey = 0x13, // Self-Signature + PGPSignatureSubkeyBinding = 0x18, // Self-Signature + PGPSignaturePrimaryKeyBinding = 0x19, + PGPSignatureDirectlyOnKey = 0x1F, // 0x1F: Signature directly on a key (key) - Self-Signature + PGPSignatureKeyRevocation = 0x20, // 0x20: Key revocation signature (key_revocation) + PGPSignatureSubkeyRevocation = 0x28, // 0x28: Subkey revocation signature (subkey_revocation) + PGPSignatureCertificationRevocation = 0x30, // 0x30: Certification revocation signature (cert_revocation) + PGPSignatureTimestamp = 0x40, + PGPSignature3PartyConfirmation = 0x50 +}; + +typedef NS_ENUM(UInt8, PGPSignatureSubpacketType) { + PGPSignatureSubpacketTypeUnknown = 0, // Unknown + PGPSignatureSubpacketTypeSignatureCreationTime = 2, + PGPSignatureSubpacketTypeSignatureExpirationTime = 3, + PGPSignatureSubpacketTypeExportableCertification = 4, + PGPSignatureSubpacketTypeTrustSignature = 5, // TODO + PGPSignatureSubpacketTypeRegularExpression = 6, // TODO + PGPSignatureSubpacketTypeRevocable = 7, // TODO + PGPSignatureSubpacketTypeKeyExpirationTime = 9, + PGPSignatureSubpacketTypePreferredSymetricAlgorithm = 11, + PGPSignatureSubpacketTypeRevocationKey = 12, // TODO + PGPSignatureSubpacketTypeIssuerKeyID = 16, + PGPSignatureSubpacketTypeNotationData = 20, // TODO + PGPSignatureSubpacketTypePreferredHashAlgorithm = 21, + PGPSignatureSubpacketTypePreferredCompressionAlgorithm = 22, + PGPSignatureSubpacketTypeKeyServerPreference = 23, + PGPSignatureSubpacketTypePreferredKeyServer = 24, + PGPSignatureSubpacketTypePrimaryUserID = 25, + PGPSignatureSubpacketTypePolicyURI = 26, + PGPSignatureSubpacketTypeKeyFlags = 27, + PGPSignatureSubpacketTypeSignerUserID = 28, + PGPSignatureSubpacketTypeReasonForRevocation = 29, + PGPSignatureSubpacketTypeFeatures = 30, + PGPSignatureSubpacketTypeSignatureTarget = 31, // TODO + PGPSignatureSubpacketTypeEmbeddedSignature = 32 // TODO +}; + +// 5.2.3.21. Key Flags +typedef NS_ENUM(UInt8, PGPSignatureFlags) { + PGPSignatureFlagUnknown = 0x00, + PGPSignatureFlagAllowCertifyOtherKeys = 0x01, // indicates that this key may be used to certify other keys + PGPSignatureFlagAllowSignData = 0x02, // indicates that this key may be used to sign data. + PGPSignatureFlagAllowEncryptCommunications = 0x04, // indicates that this key may be used to encrypt communication. + PGPSignatureFlagAllowEncryptStorage = 0x08, // indicates that this key may be used to encrypt storage. + PGPSignatureFlagSecretComponentMayBeSplit = 0x10, // indicates that the secret components of this key may have been split using a secret-sharing mechanism. + PGPSignatureFlagAllowAuthentication = 0x20, // indicates that this key may be used for authentication. + PGPSignatureFlagPrivateKeyMayBeInThePossesionOfManyPersons = 0x80 // indicates that the secret components of this key may be in the possession of more than one person. +}; + +// 5.2.3.17. Key Server Preferences +typedef NS_ENUM(UInt8, PGPKeyServerPreferenceFlags) { + PGPKeyServerPreferenceUnknown = 0x00, + PGPKeyServerPreferenceNoModify = 0x80 // No-modify +}; + +// 5.2.3.24. Features +typedef NS_ENUM(UInt8, PGPFeature) { + PGPFeatureModificationUnknown = 0x00, + PGPFeatureModificationDetection = 0x01 // Modification Detection (packets 18 and 19) +}; + +// 3.7.1. String-to-Key (S2K) Specifier Types +typedef NS_ENUM(UInt8, PGPS2KSpecifier) { + PGPS2KSpecifierSimple = 0, + PGPS2KSpecifierSalted = 1, + PGPS2KSpecifierIteratedAndSalted = 3, + PGPS2KSpecifierGnuDummy = 101 // The "gnu-dummy S2K" is the marker which will tell that this file does *not* actually contain the secret key. +}; + +typedef NS_ENUM(UInt8, PGPS2KUsage) { + PGPS2KUsageNonEncrypted = 0, // no passphrase + PGPS2KUsageEncryptedAndHashed = 254, + PGPS2KUsageEncrypted = 255 +}; diff --git a/enzevalos_iphone/ObjectivePGP/PGPUser.h b/enzevalos_iphone/ObjectivePGP/PGPUser.h new file mode 100644 index 00000000..f70a5283 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/PGPUser.h @@ -0,0 +1,35 @@ +// +// PGPUser.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 15/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPMacros.h" +#import "PGPPacket.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPUserIDPacket, PGPUserAttributePacket, PGPSignaturePacket, PGPPartialKey; + +@interface PGPUser : NSObject + +@property (nonatomic, copy) NSString *userID; +@property (nonatomic) PGPUserAttributePacket *userAttribute; +@property (nonatomic) NSArray<PGPSignaturePacket *> *selfCertifications; +@property (nonatomic) NSArray<PGPSignaturePacket *> *otherSignatures; +@property (nonatomic) NSArray<PGPSignaturePacket *> *revocationSignatures; + +@property (nonatomic) PGPUserIDPacket *userIDPacket; +@property (nonatomic) NSArray<PGPPacket *> *allPackets; + +PGP_EMPTY_INIT_UNAVAILABLE + +- (instancetype)initWithUserIDPacket:(PGPUserIDPacket *)userPacket NS_DESIGNATED_INITIALIZER; +- (nullable PGPSignaturePacket *)validSelfCertificate:(PGPPartialKey *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPUser.m b/enzevalos_iphone/ObjectivePGP/PGPUser.m similarity index 59% rename from PGPUser.m rename to enzevalos_iphone/ObjectivePGP/PGPUser.m index ac01ceb7..c9b5cab1 100644 --- a/PGPUser.m +++ b/enzevalos_iphone/ObjectivePGP/PGPUser.m @@ -7,68 +7,53 @@ // #import "PGPUser.h" -#import "PGPSignaturePacket.h" +#import "PGPPartialKey.h" #import "PGPPublicKeyPacket.h" -#import "PGPUserIDPacket.h" -#import "PGPKey.h" +#import "PGPSignaturePacket.h" #import "PGPUserAttributePacket.h" +#import "PGPUserIDPacket.h" +#import "PGPMacros+Private.h" +#import "PGPFoundation.h" + +NS_ASSUME_NONNULL_BEGIN @implementation PGPUser -- (instancetype) initWithUserIDPacket:(PGPUserIDPacket *)userPacket -{ - if (self = [self init]) { +- (instancetype)initWithUserIDPacket:(PGPUserIDPacket *)userPacket { + PGPAssertClass(userPacket, PGPUserIDPacket); + + if (self = [super init]) { _userIDPacket = userPacket; } return self; } -- (NSString *)userID -{ +- (NSString *)userID { return self.userIDPacket.userID; } -- (NSUInteger)hash -{ - NSUInteger prime = 31; - NSUInteger result = 1; - - result = prime * result + [_userID hash]; - result = prime * result + [_userAttribute hash]; - result = prime * result + [_selfCertifications hash]; - result = prime * result + [_otherSignatures hash]; - result = prime * result + [_revocationSignatures hash]; - result = prime * result + [_userIDPacket hash]; - - return result; -} - -- (NSArray *)otherSignatures -{ +- (NSArray *)otherSignatures { if (!_otherSignatures) { _otherSignatures = [NSArray array]; } return _otherSignatures; } -- (NSArray *)revocationSignatures -{ +- (NSArray *)revocationSignatures { if (!_revocationSignatures) { _revocationSignatures = [NSArray array]; } return _revocationSignatures; } -- (NSArray *)selfCertifications -{ +- (NSArray *)selfCertifications { if (!_selfCertifications) { _selfCertifications = [NSArray array]; } return _selfCertifications; } -- (PGPUserIDPacket *)userIDPacket -{ +- (PGPUserIDPacket *)userIDPacket { if (!_userIDPacket) { NSAssert(false, @"wat?"); // build userIDPacket @@ -76,17 +61,15 @@ return _userIDPacket; } -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ %@",[super description], self.userID]; +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %@", [super description], self.userID]; } -- (NSArray *) allPackets -{ - NSMutableArray *arr = [NSMutableArray array]; +- (NSArray<PGPPacket *> *)allPackets { + let arr = [NSMutableArray<PGPPacket *> array]; if (self.userIDPacket) { - [arr addObject:self.userIDPacket]; //TODO: || [arr addObject:self.userAttribute] + [arr addObject:self.userIDPacket]; // TODO: || [arr addObject:self.userAttribute] } for (id packet in self.revocationSignatures) { @@ -101,11 +84,11 @@ [arr addObject:packet]; } - return [arr copy]; + return arr; } -//TODO: -//User.prototype.getValidSelfCertificate = function(primaryKey) { +// TODO: +// User.prototype.getValidSelfCertificate = function(primaryKey) { // if (!this.selfCertifications) { // return null; // } @@ -130,15 +113,14 @@ //}; // Returns the most significant (latest valid) self signature of the user -- (PGPSignaturePacket *) validSelfCertificate:(PGPKey *)key -{ +- (nullable PGPSignaturePacket *)validSelfCertificate:(PGPPartialKey *)key { if (self.selfCertifications.count == 0) { return nil; } NSMutableArray *certs = [NSMutableArray array]; for (PGPSignaturePacket *signature in self.selfCertifications) { - //TODO: check for revocation + // TODO: check for revocation if (signature.isExpired) { continue; @@ -147,7 +129,7 @@ // This only worked as verify wasn't implemented correctly // TODO: find a better solution // - // // (this is craziest think I ever seen today) + // // (this is the craziest thing I ever seen today) // NSError *error; // [signature verifyData:nil withKey:key signingKeyPacket:(PGPPublicKeyPacket *)key.primaryKeyPacket userID:self.userID error:&error]; // //BOOL status = [signature verifyData:nil withKey:key signingKeyPacket:(PGPPublicKeyPacket *)key.primaryKeyPacket userID:self.userID error:&error]; @@ -162,12 +144,50 @@ } [certs sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { - PGPSignaturePacket *sig1 = obj1; - PGPSignaturePacket *sig2 = obj2; - return [sig1.creationDate compare:sig2.creationDate]; + let sig1 = PGPCast(obj1, PGPSignaturePacket); + let sig2 = PGPCast(obj2, PGPSignaturePacket); + if (sig1.creationDate && sig2.creationDate) { + return [PGPNN(sig1.creationDate) compare:PGPNN(sig2.creationDate)]; + } + return NSOrderedSame; }]; return [certs firstObject]; } +#pragma mark - isEqual + +- (BOOL)isEqual:(id)other { + if (self == other) { return YES; } + if ([other isKindOfClass:self.class]) { + return [self isEqualToUser:other]; + } + return NO; +} + +- (BOOL)isEqualToUser:(PGPUser *)other { + return PGPEqualObjects(self.userID,other.userID) && + PGPEqualObjects(self.userAttribute,other.userAttribute) && + PGPEqualObjects(self.selfCertifications,other.selfCertifications) && + PGPEqualObjects(self.otherSignatures,other.otherSignatures) && + PGPEqualObjects(self.revocationSignatures,other.revocationSignatures) && + PGPEqualObjects(self.userIDPacket,other.userIDPacket); +} + +- (NSUInteger)hash { + NSUInteger prime = 31; + NSUInteger result = 1; + + result = prime * result + self.userID.hash; + result = prime * result + self.userAttribute.hash; + result = prime * result + self.selfCertifications.hash; + result = prime * result + self.otherSignatures.hash; + result = prime * result + self.revocationSignatures.hash; + result = prime * result + self.userIDPacket.hash; + + return result; +} + @end + +NS_ASSUME_NONNULL_END diff --git a/PGPCompressedPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.h similarity index 65% rename from PGPCompressedPacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.h index de05a34f..02649c8f 100644 --- a/PGPCompressedPacket.h +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.h @@ -11,14 +11,14 @@ // 9.3. Compression Algorithms typedef NS_ENUM(UInt8, PGPCompressionAlgorithm) { PGPCompressionUncompressed = 0, - PGPCompressionZIP = 1, //TODO: Unsupported - PGPCompressionZLIB = 2, - PGPCompressionBZIP2 = 3 + PGPCompressionZIP = 1, // TODO: Unsupported + PGPCompressionZLIB = 2, + PGPCompressionBZIP2 = 3 }; @interface PGPCompressedPacket : PGPPacket -@property (assign, readonly) PGPCompressionAlgorithm compressionType; -@property (strong) NSData *decompressedData; +@property (nonatomic, readonly) PGPCompressionAlgorithm compressionType; +@property (nonatomic) NSData *decompressedData; - (instancetype)initWithData:(NSData *)dataToCompress type:(PGPCompressionAlgorithm)type; diff --git a/PGPCompressedPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.m similarity index 74% rename from PGPCompressedPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.m index 3cda6b44..63ddf941 100644 --- a/PGPCompressedPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPCompressedPacket.m @@ -9,11 +9,12 @@ #import "PGPCompressedPacket.h" #import "NSData+compression.h" +#import "NSMutableData+PGPUtils.h" +#import "PGPMacros+Private.h" @implementation PGPCompressedPacket -- (instancetype)initWithData:(NSData *)dataToCompress type:(PGPCompressionAlgorithm)type -{ +- (instancetype)initWithData:(NSData *)dataToCompress type:(PGPCompressionAlgorithm)type { if (self = [self init]) { self->_decompressedData = dataToCompress; self->_compressionType = type; @@ -21,13 +22,11 @@ return self; } -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPCompressedDataPacketTag; } -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = [super parsePacketBody:packetBody error:error]; // - One octet that gives the algorithm used to compress the packet. @@ -37,7 +36,7 @@ // - Compressed data, which makes up the remainder of the packet. NSData *compressedData = [packetBody subdataWithRange:(NSRange){position, packetBody.length - position}]; - //TODO: for ZIP use AgileBits/objective-zip + // TODO: for ZIP use AgileBits/objective-zip switch (self.compressionType) { case PGPCompressionZLIB: case PGPCompressionZIP: @@ -49,7 +48,7 @@ default: if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"This type of compression is not supported"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"This type of compression is not supported" }]; } @throw [NSException exceptionWithName:@"Unsupported Compression" reason:@"Compression type is not supported" userInfo:nil]; break; @@ -59,41 +58,37 @@ return position; } -- (NSData *)exportPacket:(NSError *__autoreleasing *)error -{ - NSMutableData *bodyData = [NSMutableData data]; - +- (NSData *)export:(NSError *__autoreleasing *)error { + let bodyData = [NSMutableData data]; + // - One octet that gives the algorithm used to compress the packet. [bodyData appendBytes:&_compressionType length:sizeof(_compressionType)]; - + // - Compressed data, which makes up the remainder of the packet. - NSData *compressedData = nil; + NSData * _Nullable compressedData = nil; switch (self.compressionType) { case PGPCompressionZLIB: compressedData = [self.decompressedData zlibCompressed:error]; break; case PGPCompressionBZIP2: - compressedData =[self.decompressedData bzip2Compressed:error]; + compressedData = [self.decompressedData bzip2Compressed:error]; break; - + default: if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"This type of compression is not supported"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"This type of compression is not supported" }]; } return nil; break; } NSAssert(compressedData, @"Compression failed"); - [bodyData appendData:compressedData]; - - NSMutableData *data = [NSMutableData data]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - - return [data copy]; + [bodyData pgp_appendData:compressedData]; + + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return bodyData; + }]; } @end -//ret = (int)inflateInit2(&z.zstream, -15) +// ret = (int)inflateInit2(&z.zstream, -15) diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.h new file mode 100644 index 00000000..df904b66 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.h @@ -0,0 +1,29 @@ +// +// PGPLiteralPacket.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 24/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPExportableProtocol.h" +#import "PGPPacket.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(UInt8, PGPLiteralPacketFormat) { PGPLiteralPacketBinary = 'b', PGPLiteralPacketText = 't', PGPLiteralPacketTextUTF8 = 'u' }; + +@interface PGPLiteralPacket : PGPPacket <PGPExportable> + +@property (nonatomic) PGPLiteralPacketFormat format; +@property (nonatomic) NSDate *timestamp; +@property (nonatomic, nullable) NSString *filename; + +@property (nonatomic) NSData *literalRawData; + +- (instancetype)initWithData:(NSData *)rawData; ++ (PGPLiteralPacket *)literalPacket:(PGPLiteralPacketFormat)format withData:(NSData *)rawData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPLiteralPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.m similarity index 79% rename from PGPLiteralPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.m index 072c03ad..81c1167c 100644 --- a/PGPLiteralPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPLiteralPacket.m @@ -8,43 +8,41 @@ #import "PGPLiteralPacket.h" #import "PGPTypes.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN @interface PGPLiteralPacket () @end @implementation PGPLiteralPacket -- (id)init -{ +- (instancetype)init { if (self = [super init]) { _format = PGPLiteralPacketBinary; } return self; } -- (instancetype) initWithData:(NSData *)rawData -{ +- (instancetype)initWithData:(NSData *)rawData { if (self = [self init]) { _literalRawData = rawData; } return self; } -+ (PGPLiteralPacket *) literalPacket:(PGPLiteralPacketFormat)format withData:(NSData *)rawData -{ - PGPLiteralPacket *literalPacket = [[PGPLiteralPacket alloc] init]; ++ (PGPLiteralPacket *)literalPacket:(PGPLiteralPacketFormat)format withData:(NSData *)rawData { + let literalPacket = [[PGPLiteralPacket alloc] init]; literalPacket.format = format; literalPacket.literalRawData = rawData; return literalPacket; } -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPLiteralDataPacketTag; } -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = [super parsePacketBody:packetBody error:error]; // A one-octet field that describes how the data is formatted. @@ -52,8 +50,7 @@ position = position + 1; NSAssert(self.format == PGPLiteralPacketBinary || self.format == PGPLiteralPacketText || self.format == PGPLiteralPacketTextUTF8, @"Unkown data format"); - if (self.format != PGPLiteralPacketBinary && self.format != PGPLiteralPacketText && self.format != PGPLiteralPacketTextUTF8) - { + if (self.format != PGPLiteralPacketBinary && self.format != PGPLiteralPacketText && self.format != PGPLiteralPacketTextUTF8) { // skip return 1 + packetBody.length; } @@ -76,7 +73,7 @@ creationTimestamp = CFSwapInt32BigToHost(creationTimestamp); self.timestamp = [NSDate dateWithTimeIntervalSince1970:creationTimestamp]; position = position + 4; - NSData *data = [packetBody subdataWithRange:(NSRange){position, packetBody.length - position}]; + let data = [packetBody subdataWithRange:(NSRange){position, packetBody.length - position}]; switch (self.format) { case PGPLiteralPacketBinary: @@ -92,21 +89,20 @@ return position; } -- (NSData *) exportPacket:(NSError *__autoreleasing *)error -{ +- (nullable NSData *)export:(NSError *_Nullable __autoreleasing *)error { NSAssert(self.literalRawData, @"Missing literal data"); if (!self.literalRawData) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Missing literal data"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Missing literal data" }]; } return nil; } - NSMutableData *bodyData = [NSMutableData data]; + let bodyData = [NSMutableData data]; [bodyData appendBytes:&_format length:1]; if (self.filename) { - UInt8 filenameLength = [self.filename lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + UInt8 filenameLength = (UInt8)[self.filename lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; [bodyData appendBytes:&filenameLength length:1]; [bodyData appendBytes:[self.filename cStringUsingEncoding:NSUTF8StringEncoding] length:filenameLength]; } else { @@ -119,7 +115,7 @@ timestampBytes = CFSwapInt32HostToBig(timestampBytes); [bodyData appendBytes:×tampBytes length:4]; } else { - UInt8 zero4[] = {0,0,0,0}; + UInt8 zero4[] = {0, 0, 0, 0}; [bodyData appendBytes:&zero4 length:4]; } @@ -133,13 +129,11 @@ break; } - NSMutableData *data = [NSMutableData data]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - - return [data copy]; + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return bodyData; + }]; } - @end + +NS_ASSUME_NONNULL_END diff --git a/PGPModificationDetectionCodePacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.h similarity index 86% rename from PGPModificationDetectionCodePacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.h index 99bcf5c4..b075bbc8 100644 --- a/PGPModificationDetectionCodePacket.h +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.h @@ -9,7 +9,7 @@ #import "PGPPacket.h" @interface PGPModificationDetectionCodePacket : PGPPacket -@property (strong, readonly) NSData *hashData; +@property (nonatomic, readonly) NSData *hashData; - (instancetype)initWithData:(NSData *)data; diff --git a/PGPModificationDetectionCodePacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.m similarity index 56% rename from PGPModificationDetectionCodePacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.m index a5a71e4d..8984d1cf 100644 --- a/PGPModificationDetectionCodePacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPModificationDetectionCodePacket.m @@ -14,42 +14,33 @@ @implementation PGPModificationDetectionCodePacket -- (instancetype)initWithData:(NSData *)data -{ +- (instancetype)initWithData:(NSData *)data { if (self = [self init]) { self->_hashData = [data pgp_SHA1]; } return self; } -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPModificationDetectionCodePacketTag; // 19 } -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = [super parsePacketBody:packetBody error:error]; // 5.14. Modification Detection Code Packet (Tag 19) - NSAssert(self.bodyData.length == CC_SHA1_DIGEST_LENGTH, @"A Modification Detection Code packet MUST have a length of 20 octets"); + NSAssert(packetBody.length == CC_SHA1_DIGEST_LENGTH, @"A Modification Detection Code packet MUST have a length of 20 octets"); - self->_hashData = [packetBody subdataWithRange:(NSRange){position,CC_SHA1_DIGEST_LENGTH}]; + self->_hashData = [packetBody subdataWithRange:(NSRange){position, CC_SHA1_DIGEST_LENGTH}]; position = position + self.hashData.length; return position; } -- (NSData *)exportPacket:(NSError *__autoreleasing *)error -{ - NSData *bodyData = [self.hashData subdataWithRange:(NSRange) {0,CC_SHA1_DIGEST_LENGTH}]; // force limit to 20 octets - - NSMutableData *data = [NSMutableData data]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - - return [data copy]; +- (NSData *)export:(NSError *__autoreleasing *)error { + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return [self.hashData subdataWithRange:(NSRange){0, CC_SHA1_DIGEST_LENGTH}]; // force limit to 20 octets + }]; } @end diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.h new file mode 100644 index 00000000..cbbb2a92 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.h @@ -0,0 +1,27 @@ +// +// PGPOnePassSignaturePacket.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 29/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPacket.h" +#import "PGPExportableProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@class PGPKeyID; + +@interface PGPOnePassSignaturePacket : PGPPacket <PGPExportable> + +@property (nonatomic) UInt8 version; // The current version is 3. +@property (nonatomic) PGPSignatureType signatureType; +@property (nonatomic) PGPHashAlgorithm hashAlgorith; +@property (nonatomic) PGPPublicKeyAlgorithm publicKeyAlgorithm; +@property (nonatomic) PGPKeyID *keyID; // 8 +@property (nonatomic) BOOL notNested; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPOnePassSignaturePacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.m similarity index 61% rename from PGPOnePassSignaturePacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.m index a1bed836..d82db8c1 100644 --- a/PGPOnePassSignaturePacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPOnePassSignaturePacket.m @@ -8,24 +8,24 @@ #import "PGPOnePassSignaturePacket.h" #import "PGPKeyID.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN @implementation PGPOnePassSignaturePacket -- (id)init -{ +- (id)init { if (self = [super init]) { _version = 0x03; } return self; } -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPOnePassSignaturePacketTag; } -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = [super parsePacketBody:packetBody error:error]; [packetBody getBytes:&_version range:(NSRange){position, 1}]; @@ -50,26 +50,28 @@ return position; } -- (NSData *)exportPacket:(NSError *__autoreleasing *)error -{ - NSAssert(self.keyID, @"Missing keyID"); +#pragma mark - PGPExportable - NSMutableData *bodyData = [NSMutableData data]; +- (nullable NSData *)export:(NSError *__autoreleasing _Nullable *)error { + NSAssert(self.keyID, @"Missing keyID"); - [bodyData appendBytes:&_version length:1]; - [bodyData appendBytes:&_signatureType length:1]; - [bodyData appendBytes:&_hashAlgorith length:1]; - [bodyData appendBytes:&_publicKeyAlgorithm length:1]; - [bodyData appendData:[self.keyID exportKeyData]]; + weakify(self); + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + strongify(self) + let bodyData = [NSMutableData data]; - [bodyData appendBytes:&_notNested length:1]; + [bodyData appendBytes:&self->_version length:1]; + [bodyData appendBytes:&self->_signatureType length:1]; + [bodyData appendBytes:&self->_hashAlgorith length:1]; + [bodyData appendBytes:&self->_publicKeyAlgorithm length:1]; + [bodyData appendData:[self.keyID export:nil]]; - NSMutableData *data = [NSMutableData data]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; + [bodyData appendBytes:&self->_notNested length:1]; - return [data copy]; + return bodyData; + }]; } @end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket+Private.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket+Private.h new file mode 100644 index 00000000..ca4d3c6a --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket+Private.h @@ -0,0 +1,20 @@ +// +// PGPPacket+Private.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 09/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPacket.h" +#import <ObjectivePGP/ObjectivePGP.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPPacket () + ++ (NSData *)buildNewFormatLengthDataForData:(NSData *)bodyData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.h new file mode 100644 index 00000000..a4a7d0d8 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.h @@ -0,0 +1,32 @@ +// +// PGPPacket.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 06/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPExportableProtocol.h" +#import "PGPPacketProtocol.h" +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +extern const UInt32 PGPUnknownLength; + +@interface PGPPacket : NSObject <PGPPacketProtocol, NSCopying, PGPExportable> +@property (nonatomic) BOOL indeterminateLength; // should not be used, but gpg use it + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithHeader:(NSData *)headerData body:(NSData *)bodyData; + ++ (nullable NSData *)parsePacketHeader:(NSData *)data headerLength:(UInt32 *)headerLength nextPacketOffset:(nullable NSUInteger *)nextPacketOffset packetTag:(PGPPacketTag *)tag indeterminateLength:(BOOL *)indeterminateLength; +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error; + ++ (NSData *)buildPacketOfType:(PGPPacketTag)tag withBody:(PGP_NOESCAPE NSData *(^)(void))body; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.m new file mode 100644 index 00000000..e8590db2 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacket.m @@ -0,0 +1,374 @@ +// +// PGPPacket.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 06/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPacket.h" +#import "PGPPacket+Private.h" +#import "NSData+PGPUtils.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +const UInt32 PGPUnknownLength = UINT32_MAX; + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPPacket + +@synthesize tag = _tag; + +- (instancetype)init { + return [super init]; +} + +- (instancetype)initWithHeader:(NSData *)headerData body:(NSData *)bodyData { + if ((self = [self init])) { + NSError *error = nil; + [self parsePacketBody:bodyData error:&error]; + if (error) { + return nil; + } + } + return self; +} + +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + PGPAssertClass(packetBody, NSData); + return 0; +} + +- (nullable NSData *)export:(NSError *__autoreleasing *)error { + [NSException raise:@"MissingExportMethod" format:@"export: selector not overriden"]; + return nil; +} + +#pragma mark - isEqual + +- (BOOL)isEqual:(id)other { + if (self == other) { return YES; } + if ([super isEqual:other] && [other isKindOfClass:self.class]) { + return [self isEqualToPacket:other]; + } + return NO; +} + +- (BOOL)isEqualToPacket:(PGPPacket *)packet { + return self.tag == packet.tag && self.indeterminateLength == packet.indeterminateLength; +} + +- (NSUInteger)hash { + NSUInteger prime = 31; + NSUInteger result = 1; + result = prime * result + self.tag; + result = prime * result + self.indeterminateLength; + return result; +} + +#pragma mark - Packet header + +// 4.2. Packet Headers +/** + * Parse header + * + * @param data header data + * + * @return Body data, headerLength, packetTag, nextPacketOffset and if body has indeterminateLength + */ ++ (nullable NSData *)parsePacketHeader:(NSData *)data headerLength:(UInt32 *)headerLength nextPacketOffset:(nullable NSUInteger *)nextPacketOffset packetTag:(PGPPacketTag *)tag indeterminateLength:(BOOL *)indeterminateLength { + UInt8 headerByte = 0; + [data getBytes:&headerByte range:(NSRange){0, 1}]; + + BOOL isPGPHeader = !!(headerByte & PGPHeaderPacketTagAllwaysSet); + BOOL isNewFormat = !!(headerByte & PGPHeaderPacketTagNewFormat); + BOOL isPartialBodyLength = NO; + + if (!isPGPHeader) { + // not a valida data, skip the whole data. + if (nextPacketOffset) { + *nextPacketOffset = data.length; + } + return nil; + } + + UInt32 bodyLength = 0; + if (isNewFormat) { + *headerLength = [self parseNewFormatHeaderPacket:data bodyLength:&bodyLength packetTag:tag partialBodyLength:&isPartialBodyLength]; + } else { + *headerLength = [self parseOldFormatHeaderPacket:data bodyLength:&bodyLength packetTag:tag]; + } + + if (indeterminateLength) { + *indeterminateLength = NO; + } + + if (bodyLength == PGPUnknownLength) { + bodyLength = (UInt32)data.length - *headerLength; + + if (indeterminateLength) { + *indeterminateLength = YES; + } + } + + if (nextPacketOffset) { + *nextPacketOffset = bodyLength + *headerLength; + } + + if (isPartialBodyLength) { + UInt32 offset = *headerLength; + let resultData = [NSMutableData dataWithData:[data subdataWithRange:(NSRange){offset, bodyLength}]]; + offset += bodyLength; + + do { + // assume new header format + PGPPacketTag nextTag = PGPInvalidPacketTag; + UInt32 packetBodyLength = 0; + UInt32 packetHeaderLength = [self parseNewFormatHeaderPacket:[data subdataWithRange:(NSRange){offset - 1, data.length - (offset - 1)}] bodyLength:&packetBodyLength packetTag:&nextTag partialBodyLength:&isPartialBodyLength] - 1; + offset += packetHeaderLength; + if (nextPacketOffset != NULL) { + *nextPacketOffset += packetHeaderLength + packetBodyLength; + } + [resultData appendData:[data subdataWithRange:(NSRange){offset, MIN(packetBodyLength, data.length - offset)}]]; + offset += packetBodyLength; + } while (isPartialBodyLength); + + return resultData; + } + return [data subdataWithRange:(NSRange){*headerLength, bodyLength}]; +} + +/** + * 4.2. Packet Headers + * + * @param headerData Packet header + * + * @return Header length + */ ++ (UInt32)parseNewFormatHeaderPacket:(NSData *)headerData bodyLength:(UInt32 *)length packetTag:(PGPPacketTag *)tag partialBodyLength:(BOOL *)isPartialBodyLength { + NSParameterAssert(headerData); + + UInt8 headerByte = 0; + [headerData getBytes:&headerByte length:1]; + // Bits 5-0 -- packet tag + UInt8 packetTag = (UInt8)(headerByte << 2); + packetTag = (packetTag >> 2); + *tag = packetTag; + + // body length + *isPartialBodyLength = NO; + UInt32 bodyLength = 0; + UInt32 headerLength = 2; + + const UInt8 *lengthOctets = [headerData subdataWithRange:(NSRange){1, MIN((NSUInteger)5, headerData.length - 1)}].bytes; + UInt8 firstOctet = lengthOctets[0]; + + if (lengthOctets[0] < 192) { + // 4.2.2.1. One-Octet Length + // bodyLen = 1st_octet; + bodyLength = lengthOctets[0]; + headerLength = 1 + 1; // 2 + } else if (lengthOctets[0] >= 192 && lengthOctets[0] < 224) { + // 4.2.2.2. Two-Octet Lengths + // bodyLen = ((1st_octet - 192) << 8) + (2nd_octet) + 192 + bodyLength = ((lengthOctets[0] - 192) << 8) + (lengthOctets[1]) + 192; + headerLength = 1 + 2; + } else if (lengthOctets[0] >= 224 && lengthOctets[0] < 255) { + // 4.2.2.4. Partial Body Length + // partialBodyLen = 1 << (1st_octet & 0x1F); + UInt32 partianBodyLength = 1 << (lengthOctets[0] & 0x1F); + bodyLength = partianBodyLength; + headerLength = 1 + 1; + *isPartialBodyLength = YES; + } else if (firstOctet == 255) { + // 4.2.2.3. Five-Octet Length + // bodyLen = (2nd_octet << 24) | (3rd_octet << 16) | + // (4th_octet << 8) | 5th_octet + bodyLength = (lengthOctets[1] << 24) | (lengthOctets[2] << 16) | (lengthOctets[3] << 8) | lengthOctets[4]; + headerLength = 1 + 5; + } + *length = bodyLength; + + NSAssert(bodyLength > 0, @"The packet is of indeterminate length"); + + return headerLength; +} + +// 4.2. Packet Headers ++ (UInt32)parseOldFormatHeaderPacket:(NSData *)headerData bodyLength:(UInt32 *)length packetTag:(PGPPacketTag *)tag { + NSParameterAssert(headerData); + + UInt8 headerByte = 0; + [headerData getBytes:&headerByte length:1]; + // Bits 5-2 -- packet tag + UInt8 packetTag = (UInt8)(headerByte << 2); + packetTag = (packetTag >> 4); + *tag = packetTag; + // Bits 1-0 -- length-type + UInt8 bodyLengthType = (UInt8)(headerByte << 6); + bodyLengthType = bodyLengthType >> 6; + + UInt32 headerLength = 1; + UInt32 bodyLength = 0; + switch (bodyLengthType) { + case 0: { + NSRange range = (NSRange){1, 1}; + [headerData getBytes:&bodyLength range:range]; + headerLength = (UInt32)(1 + range.length); + } break; + case 1: { + UInt16 bLen = 0; + NSRange range = (NSRange){1, 2}; + [headerData getBytes:&bLen range:range]; + // value of a two-octet scalar is ((n[0] << 8) + n[1]). + bodyLength = CFSwapInt16BigToHost(bLen); + headerLength = (UInt32)(1 + range.length); + } break; + case 2: { + NSRange range = (NSRange){1, 4}; + [headerData getBytes:&bodyLength range:range]; + bodyLength = CFSwapInt32BigToHost(bodyLength); + headerLength = (UInt32)(1 + range.length); + } break; + case 3: { + PGPLogWarning(@"(Old) The packet is of indeterminate length - partially supported"); + bodyLength = PGPUnknownLength; + headerLength = 1; + } break; + + default: + break; + } + + NSAssert(bodyLength > 0, @"Invalid packet length"); + *length = bodyLength; + + return headerLength; +} + ++ (NSData *)buildPacketOfType:(PGPPacketTag)tag withBody:(PGP_NOESCAPE NSData *(^)(void))body { + return [self buildPacketOfType:tag isOld:NO withBody:body]; +} + ++ (NSData *)buildPacketOfType:(PGPPacketTag)tag isOld:(BOOL)isOld withBody:(PGP_NOESCAPE NSData *(^)(void))body { + // 4.2.2. New Format Packet Lengths + let data = [NSMutableData data]; + let bodyData = body(); + + UInt8 packetTag = 0; + + // Bit 7 -- Always one + packetTag |= PGPHeaderPacketTagAllwaysSet; + + // Bit 6 -- New packet format if set + if (!isOld) { + packetTag |= PGPHeaderPacketTagNewFormat; + } + + if (isOld) { + // Bits 5-2 -- packet tag + packetTag |= (tag << 4) >> 2; + + // Bits 1-0 -- length-type + UInt64 bodyLength = bodyData.length; + if (bodyLength < 0xFF) { + // 0 - The packet has a one-octet length. The header is 2 octets long. + packetTag |= 0; + } else if (bodyLength <= 0xFFFF) { + // 1 - The packet has a two-octet length. The header is 3 octets long. + packetTag |= 1; + } else if (bodyLength <= 0xFFFFFFFF) { + // 2 - The packet has a four-octet length. The header is 5 octets long. + packetTag |= 2; + } else { + // 3 - The packet is of indeterminate length. + // In general, an implementation SHOULD NOT use indeterminate-length packets except where the end of the data will be clear from the context + packetTag |= 3; + NSAssert(NO, @"In general, an implementation SHOULD NOT use indeterminate-length packets"); + } + } else { + // Bits 5-0 -- packet tag + packetTag |= tag; + } + + // write ptag + [data appendBytes:&packetTag length:1]; + + // write header + if (isOld) { + [data appendData:[PGPPacket buildOldFormatLengthDataForData:bodyData]]; + } else { + [data appendData:[PGPPacket buildNewFormatLengthDataForData:bodyData]]; + } + + // write packet body + [data appendData:bodyData]; + + return data; +} + ++ (NSData *)buildNewFormatLengthDataForData:(NSData *)bodyData { + let data = [NSMutableData data]; + // write length octets + UInt64 bodyLength = bodyData.length; + if (bodyLength < 192) { + // 1 octet + [data appendBytes:&bodyLength length:1]; + } else if (bodyLength >= 192 && bodyLength <= 8383) { + // 2 octet + UInt8 buf[2] = {0, 0}; + UInt16 twoOctets = (UInt16)bodyLength; + buf[0] = (UInt8)((twoOctets - 192) >> 8) + 192; + buf[1] = (UInt8)(twoOctets - 192); + [data appendBytes:buf length:2]; + } else { + // 5 octet + UInt64 fiveOctets = bodyLength; + + UInt8 buf[5] = {0xFF, 0, 0, 0, 0}; + buf[1] = (UInt8)(fiveOctets >> 24); + buf[2] = (UInt8)(fiveOctets >> 16); + buf[3] = (UInt8)(fiveOctets >> 8); + buf[4] = (UInt8)(fiveOctets); + [data appendBytes:buf length:5]; + } + return data; +} + ++ (NSData *)buildOldFormatLengthDataForData:(NSData *)bodyData { + let data = [NSMutableData data]; + UInt64 bodyLength = bodyData.length; + if (bodyLength < 0xFF) { + // 0 - The packet has a one-octet length. The header is 2 octets long. + let bodyLengthBE = bodyLength; + [data appendBytes:&bodyLengthBE length:1]; + } else if (bodyLength <= 0xFFFF) { + // 1 - The packet has a two-octet length. The header is 3 octets long. + let bodyLengthBE = CFSwapInt16HostToBig((UInt16)bodyLength); + [data appendBytes:&bodyLengthBE length:2]; + } else if (bodyLength <= 0xFFFFFFFF) { + // 2 - The packet has a four-octet length. The header is 5 octets long. + let bodyLengthBE = CFSwapInt64HostToBig(bodyLength); + [data appendBytes:&bodyLengthBE length:4]; + } else { + // 3 - The packet is of indeterminate length. + // In general, an implementation SHOULD NOT use indeterminate-length packets except where the end of the data will be clear from the context + NSAssert(NO, @"In general, an implementation SHOULD NOT use indeterminate-length packets"); + } + return data; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(nullable NSZone *)zone { + PGPPacket *copy = [[[self class] allocWithZone:zone] init]; + copy->_tag = self.tag; + copy->_indeterminateLength = self.indeterminateLength; + return copy; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPacketProtocol.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacketProtocol.h new file mode 100644 index 00000000..3f5000cf --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPacketProtocol.h @@ -0,0 +1,16 @@ +// +// PGPPacketProtocol.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 24/08/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> +#import "PGPTypes.h" + +@protocol PGPPacketProtocol <NSObject> + +@property (nonatomic, readonly) PGPPacketTag tag; + +@end diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.h new file mode 100644 index 00000000..3e3575b2 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.h @@ -0,0 +1,27 @@ +// +// PGPPublicKeyEncryptedSessionKeyPacket.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 06/06/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPacket.h" +#import "PGPExportableProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@class PGPKeyID, PGPPublicKeyPacket, PGPSecretKeyPacket; + +@interface PGPPublicKeyEncryptedSessionKeyPacket : PGPPacket <NSCopying, PGPExportable> +@property (nonatomic) UInt8 version; +@property (nonatomic) PGPKeyID *keyID; +@property (nonatomic) PGPPublicKeyAlgorithm publicKeyAlgorithm; +@property (nonatomic, getter=isEncrypted) BOOL encrypted; + +- (BOOL)encrypt:(PGPPublicKeyPacket *)publicKeyPacket sessionKeyData:(NSData *)sessionKeyData sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm error:(NSError *__autoreleasing *)error; +- (nullable NSData *)decryptSessionKeyData:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm *)sessionKeyAlgorithm error:(NSError *__autoreleasing *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPPublicKeyEncryptedSessionKeyPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.m similarity index 58% rename from PGPPublicKeyEncryptedSessionKeyPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.m index f4a40b9a..9dcb172f 100644 --- a/PGPPublicKeyEncryptedSessionKeyPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyEncryptedSessionKeyPacket.m @@ -3,30 +3,33 @@ // ObjectivePGP // // Created by Marcin Krzyzanowski on 06/06/14. -// Copyright (c) 2014 Marcin Krzyżanowski. All rencryptedMPIsPartDataights reserved. +// Copyright (c) 2014 Marcin Krzyżanowski. All rencryptedMPIPartDataights reserved. // // 5.1. Public-Key Encrypted Session Key Packets (Tag 1) #import "PGPPublicKeyEncryptedSessionKeyPacket.h" +#import "NSData+PGPUtils.h" +#import "PGPCryptoUtils.h" +#import "PGPFingerprint.h" #import "PGPKeyID.h" #import "PGPMPI.h" -#import "NSData+PGPUtils.h" #import "PGPPKCSEme.h" #import "PGPPublicKeyPacket.h" +#import "PGPRSA.h" #import "PGPSecretKeyPacket.h" -#import "PGPMPI.h" -#import "PGPPublicKeyRSA.h" -#import "PGPFingerprint.h" -#import "PGPCryptoUtils.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN @interface PGPPublicKeyEncryptedSessionKeyPacket () -@property (strong) PGPMPI *encryptedMPI_M; + +@property (nonatomic) PGPMPI *encryptedMPI_M; + @end @implementation PGPPublicKeyEncryptedSessionKeyPacket -- (instancetype)init -{ +- (instancetype)init { if (self = [super init]) { _version = 3; _encrypted = NO; @@ -35,20 +38,18 @@ return self; } -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPPublicKeyEncryptedSessionKeyPacketTag; // 1 } -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = [super parsePacketBody:packetBody error:error]; - + // - A one-octet number giving the version number of the packet type. The currently defined value for packet version is 3. [packetBody getBytes:&_version range:(NSRange){position, 1}]; NSAssert(self.version == 3, @"The currently defined value for packet version is 3"); position = position + 1; - + // - An eight-octet number that gives the Key ID of the public key self.keyID = [[PGPKeyID alloc] initWithLongKey:[packetBody subdataWithRange:(NSRange){position, 8}]]; NSAssert(self.keyID, @"Missing KeyID"); @@ -63,64 +64,43 @@ // dependent on the public-key algorithm used. // RSA 1 MPI // Elgamal 2 MPI - - NSData *encryptedMPI_MData = [packetBody subdataWithRange:(NSRange) {position, packetBody.length - position}]; - self.encryptedMPI_M = [[PGPMPI alloc] initWithMPIData:encryptedMPI_MData atPosition:0]; + + NSAssert(self.publicKeyAlgorithm == PGPPublicKeyAlgorithmRSA, @"Not supported."); + + let encryptedMPI_MData = [packetBody subdataWithRange:(NSRange){position, packetBody.length - position}]; + self.encryptedMPI_M = [[PGPMPI alloc] initWithMPIData:encryptedMPI_MData identifier:PGPMPI_M atPosition:0]; position = position + encryptedMPI_MData.length; - + self.encrypted = YES; - + return position; } -- (NSData *)exportPacket:(NSError *__autoreleasing *)error -{ - NSAssert(self.encryptedMPI_M, @"Missing encrypted mpi m"); - if (!self.encryptedMPI_M) { - return nil; - } - - NSMutableData *bodyData = [NSMutableData data]; - - [bodyData appendBytes:&_version length:1]; //1 - [bodyData appendData:[self.keyID exportKeyData]]; //8 - [bodyData appendBytes:&_publicKeyAlgorithm length:1]; //1 - [bodyData appendData:[self.encryptedMPI_M exportMPI]]; // m - - NSMutableData *data = [NSMutableData data]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - - return [data copy]; -} +- (nullable NSData *)decryptSessionKeyData:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm *)sessionKeyAlgorithm error:(NSError *__autoreleasing *)error { + NSAssert(!secretKeyPacket.isEncryptedWithPassphrase, @"Secret key can't be decrypted"); -- (NSData *) decryptSessionKeyData:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm *)sessionKeyAlgorithm error:(NSError * __autoreleasing *)error -{ - NSAssert(!secretKeyPacket.isEncryptedWithPassword, @"Secret key can't be decrypted"); - - //FIXME: Key is read from the packet, so it shouldn't be passed as parameter to the method because + // FIXME: Key is read from the packet, so it shouldn't be passed as parameter to the method because // key is unknown earlier - PGPKeyID *secretKeyKeyID = [[PGPKeyID alloc] initWithFingerprint:secretKeyPacket.fingerprint]; - if (![self.keyID isEqualToKeyID:secretKeyKeyID]) { + let secretKeyKeyID = [[PGPKeyID alloc] initWithFingerprint:secretKeyPacket.fingerprint]; + if (!secretKeyKeyID || ![self.keyID isEqual:secretKeyKeyID]) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Invalid secret key used to decrypt session key, expected %@, got %@",self.keyID, secretKeyKeyID] }]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Invalid secret key used to decrypt session key, expected %@, got %@", self.keyID, secretKeyKeyID] }]; } return nil; } - + // encrypted m value - NSData *encryptedM = [self.encryptedMPI_M bodyData]; - + let encryptedM = [self.encryptedMPI_M bodyData]; + // decrypted m value - NSData *mEMEEncoded = [secretKeyPacket decryptData:encryptedM withPublicKeyAlgorithm:self.publicKeyAlgorithm]; - NSData *mData = [PGPPKCSEme decodeMessage:mEMEEncoded error:error]; + let mEMEEncoded = [PGPCryptoUtils decryptData:encryptedM usingSecretKeyPacket:secretKeyPacket]; + let mData = [PGPPKCSEme decodeMessage:mEMEEncoded error:error]; if (error && *error) { return nil; } - + NSUInteger position = 0; - PGPSymmetricAlgorithm sessionKeyAlgorithmRead; + PGPSymmetricAlgorithm sessionKeyAlgorithmRead = PGPSymmetricPlaintext; [mData getBytes:&sessionKeyAlgorithmRead range:(NSRange){position, 1}]; NSAssert(sessionKeyAlgorithmRead < PGPSymmetricMax, @"Invalid algorithm"); *sessionKeyAlgorithm = sessionKeyAlgorithmRead; @@ -129,33 +109,32 @@ NSUInteger sessionKeySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:sessionKeyAlgorithmRead]; if (sessionKeySize == NSNotFound) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Invalid session key size"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Invalid session key size" }]; } return nil; } - NSData *sessionKeyData = [mData subdataWithRange:(NSRange){position, sessionKeySize}]; + let sessionKeyData = [mData subdataWithRange:(NSRange){position, sessionKeySize}]; position = position + sessionKeySize; - + UInt16 checksum = 0; - [mData getBytes:&checksum range:(NSRange){position,2}]; + [mData getBytes:&checksum range:(NSRange){position, 2}]; checksum = CFSwapInt16BigToHost(checksum); - + // validate checksum UInt16 calculatedChecksum = [sessionKeyData pgp_Checksum]; if (calculatedChecksum != checksum) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Invalid session key, checksum mismatch"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Invalid session key, checksum mismatch" }]; } return nil; } - + return sessionKeyData; } -// encryption update self.encryptedMPIsPartData -- (BOOL) encrypt:(PGPPublicKeyPacket *)publicKeyPacket sessionKeyData:(NSData *)sessionKeyData sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm error:(NSError * __autoreleasing *)error -{ - NSMutableData *mData = [NSMutableData data]; +// encryption update self.encryptedMPIPartData +- (BOOL)encrypt:(PGPPublicKeyPacket *)publicKeyPacket sessionKeyData:(NSData *)sessionKeyData sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm error:(NSError *__autoreleasing *)error { + let mData = [NSMutableData data]; // The value "m" in the above formulas is derived from the session key // as follows. First, the session key is prefixed with a one-octet @@ -167,40 +146,65 @@ // PKCS#1 block encoding EME-PKCS1-v1_5 in Section 7.2.1 of [RFC3447] to // form the "m" value used in the formulas above. See Section 13.1 of // this document for notes on OpenPGP's use of PKCS#1. - + [mData appendBytes:&sessionKeyAlgorithm length:1]; - + [mData appendData:sessionKeyData]; // keySize - + UInt16 checksum = [sessionKeyData pgp_Checksum]; checksum = CFSwapInt16HostToBig(checksum); [mData appendBytes:&checksum length:2]; - - PGPMPI *modulusMPI = [publicKeyPacket publicMPI:@"N"]; - if (!modulusMPI) + + let modulusMPI = [publicKeyPacket publicMPI:PGPMPI_N]; + if (!modulusMPI) { return error == nil; - - BIGNUM *nBigNumRef = modulusMPI.bignumRef; - unsigned int k = (unsigned)BN_num_bytes(nBigNumRef); - - NSData *mEMEEncoded = [PGPPKCSEme encodeMessage:mData keyModulusLength:k error:error]; - NSData *encryptedData = [publicKeyPacket encryptData:mEMEEncoded withPublicKeyAlgorithm:self.publicKeyAlgorithm]; - PGPMPI *mpiEncoded = [[PGPMPI alloc] initWithData:encryptedData]; + } + + unsigned int k = (unsigned int)modulusMPI.bigNum.bytesCount; + + let mEMEEncoded = [PGPPKCSEme encodeMessage:mData keyModulusLength:k error:error]; + let encryptedData = [publicKeyPacket encryptData:mEMEEncoded withPublicKeyAlgorithm:self.publicKeyAlgorithm]; + let mpiEncoded = [[PGPMPI alloc] initWithData:encryptedData identifier:PGPMPI_M]; self.encryptedMPI_M = mpiEncoded; return error == nil; } +#pragma mark - PGPExportable + +- (nullable NSData *)export:(NSError *__autoreleasing _Nullable *)error { + NSAssert(self.encryptedMPI_M, @"Missing encrypted mpi m"); + if (!self.encryptedMPI_M) { + return nil; + } + + let bodyData = [NSMutableData data]; + + [bodyData appendBytes:&_version length:1]; // 1 + [bodyData appendData:[self.keyID export:nil]]; // 8 + [bodyData appendBytes:&_publicKeyAlgorithm length:1]; // 1 + let exportedMPI = [self.encryptedMPI_M exportMPI]; + if (!exportedMPI) { + return nil; + } + [bodyData appendData:exportedMPI]; // m + + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return bodyData; + }]; +} #pragma mark - NSCopying -- (instancetype)copyWithZone:(NSZone *)zone -{ +- (instancetype)copyWithZone:(nullable NSZone *)zone { PGPPublicKeyEncryptedSessionKeyPacket *copy = [super copyWithZone:zone]; copy->_version = self.version; - copy->_keyID = self.keyID; + copy->_keyID = [self.keyID copy]; + copy->_encrypted = self.isEncrypted; copy->_publicKeyAlgorithm = self.publicKeyAlgorithm; - copy->_encryptedMPI_M = self.encryptedMPI_M; + copy->_encryptedMPI_M = [self.encryptedMPI_M copy];; return copy; } @end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket+Private.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket+Private.h new file mode 100644 index 00000000..c8c11379 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket+Private.h @@ -0,0 +1,24 @@ +// +// PGPPublicKeyPacket+Private.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 09/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPublicKeyPacket.h" +#import <ObjectivePGP/ObjectivePGP.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPPublicKeyPacket () + +@property (nonatomic, readwrite) UInt8 version; +@property (nonatomic, readwrite) PGPPublicKeyAlgorithm publicKeyAlgorithm; +@property (nonatomic, copy, readwrite) NSDate *createDate; +@property (nonatomic, readwrite) UInt16 V3validityPeriod; +@property (nonatomic, copy, readwrite) NSArray<PGPMPI *> *publicMPIArray; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.h new file mode 100644 index 00000000..ca94f638 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.h @@ -0,0 +1,41 @@ +// +// OpenPGPPublicKey.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// +// Tag 6 + +#import "PGPFingerprint.h" +#import "PGPKeyID.h" +#import "PGPPacketFactory.h" +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPMPI; + +@interface PGPPublicKeyPacket : PGPPacket <NSCopying, PGPExportable> + +@property (nonatomic, readonly) UInt8 version; +@property (nonatomic, readonly) NSDate *createDate; +@property (nonatomic, readonly) UInt16 V3validityPeriod; // obsolete +@property (nonatomic, readonly) PGPPublicKeyAlgorithm publicKeyAlgorithm; +@property (nonatomic, copy, readonly) NSArray<PGPMPI *> *publicMPIArray; + +// generated properties +@property (nonatomic, readonly) NSUInteger keySize; +@property (nonatomic, readonly) PGPFingerprint *fingerprint; +@property (nonatomic, readonly) PGPKeyID *keyID; + +- (NSData *)exportKeyPacketOldStyle; +- (NSData *)buildKeyBodyData:(BOOL)forceV4; + +- (nullable PGPMPI *)publicMPI:(NSString *)identifier; +- (nullable NSData *)encryptData:(NSData *)data withPublicKeyAlgorithm:(PGPPublicKeyAlgorithm)publicKeyAlgorithm; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.m new file mode 100644 index 00000000..2b4d98bc --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicKeyPacket.m @@ -0,0 +1,299 @@ +// +// OpenPGPPublicKey.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPublicKeyPacket+Private.h" +#import "PGPPacket+Private.h" +#import "NSData+PGPUtils.h" +#import "PGPMPI.h" +#import "PGPRSA.h" +#import "PGPTypes.h" +#import "NSMutableData+PGPUtils.h" +#import "PGPMacros+Private.h" + +#import <CommonCrypto/CommonCrypto.h> +#import <CommonCrypto/CommonCryptor.h> +#import <CommonCrypto/CommonDigest.h> + +#import <objc/runtime.h> + +NS_ASSUME_NONNULL_BEGIN + +@implementation PGPPublicKeyPacket + +- (instancetype)init { + if ((self = [super init])) { + _version = 0x04; + _createDate = NSDate.date; + } + return self; +} + +- (PGPPacketTag)tag { + return PGPPublicKeyPacketTag; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %@", [super description], self.keyID]; +} + +- (NSUInteger)keySize { + for (PGPMPI *mpi in self.publicMPIArray) { + if ([mpi.identifier isEqualToString:PGPMPI_N]) { + return (mpi.bigNum.bitsCount + 7) / 8; // ks + } + } + return 0; +} + +- (nullable PGPMPI *)publicMPI:(NSString *)identifier { + for (PGPMPI *mpi in self.publicMPIArray) { + if ([mpi.identifier isEqualToString:identifier]) { + return mpi; + } + } + + return nil; +} + +#pragma mark - KeyID and Fingerprint + +/** + * 12.2. Key IDs and Fingerprints + * + * @return keyID + */ +- (PGPKeyID *)keyID { + return [[PGPKeyID alloc] initWithFingerprint:self.fingerprint]; +} + +/** + * 12.2. Key IDs and Fingerprints + * Calculate fingerprint + * + * @return Fingerprint data + */ +- (PGPFingerprint *)fingerprint { + return [[PGPFingerprint alloc] initWithData:[self exportKeyPacketOldStyle]]; +} + +#pragma mark - Parse data + +/** + * 5.5.2. Public-Key Packet Formats + * + * @param packetBody Packet body + */ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + NSUInteger position = [super parsePacketBody:packetBody error:error]; + + // A one-octet version number (2,3,4). + [packetBody getBytes:&_version range:(NSRange){position, 1}]; + position = position + 1; + + NSAssert(self.version >= 3, @"To old packet version"); + + // A four-octet number denoting the time that the key was created. + UInt32 timestamp = 0; + [packetBody getBytes:×tamp range:(NSRange){position, 4}]; + timestamp = CFSwapInt32BigToHost(timestamp); + self.createDate = [NSDate dateWithTimeIntervalSince1970:timestamp]; + position = position + 4; + + // V3 keys are deprecated; an implementation MUST NOT generate a V3 key, but MAY accept it. + if (self.version == 0x03) { + // A two-octet number denoting the time in days that this key is + // valid. If this number is zero, then it does not expire. + [packetBody getBytes:&_V3validityPeriod range:(NSRange){position, 2}]; + _V3validityPeriod = CFSwapInt16BigToHost(_V3validityPeriod); + position = position + 2; + } + + // A one-octet number denoting the public-key algorithm of this key. + [packetBody getBytes:&_publicKeyAlgorithm range:(NSRange){position, 1}]; + position = position + 1; + + // A series of multiprecision integers comprising the key material. + switch (self.publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + // Algorithm-Specific Fields for RSA public keys: + // MPI of RSA public modulus n; + let mpiN = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_N atPosition:position]; + position = position + mpiN.packetLength; + + // MPI of RSA public encryption exponent e. + let mpiE = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_E atPosition:position]; + position = position + mpiE.packetLength; + + self.publicMPIArray = @[mpiN, mpiE]; + } break; + case PGPPublicKeyAlgorithmDSA: + case PGPPublicKeyAlgorithmECDSA: { + // - MPI of DSA prime p; + let mpiP = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_P atPosition:position]; + position = position + mpiP.packetLength; + + // - MPI of DSA group order q (q is a prime divisor of p-1); + let mpiQ = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_Q atPosition:position]; + position = position + mpiQ.packetLength; + + // - MPI of DSA group generator g; + let mpiG = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_G atPosition:position]; + position = position + mpiG.packetLength; + + // - MPI of DSA public-key value y (= g**x mod p where x is secret). + let mpiY = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_Y atPosition:position]; + position = position + mpiY.packetLength; + + self.publicMPIArray = @[mpiP, mpiQ, mpiG, mpiY]; + } break; + case PGPPublicKeyAlgorithmElgamal: + case PGPPublicKeyAlgorithmElgamalEncryptorSign: { + // - MPI of Elgamal prime p; + let mpiP = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_P atPosition:position]; + position = position + mpiP.packetLength; + + // - MPI of Elgamal group generator g; + let mpiG = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_G atPosition:position]; + position = position + mpiG.packetLength; + + // - MPI of Elgamal public key value y (= g**x mod p where x is secret). + let mpiY = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_Y atPosition:position]; + position = position + mpiY.packetLength; + + self.publicMPIArray = @[mpiP, mpiG, mpiY]; + } break; + default: + @throw [NSException exceptionWithName:@"Unknown Algorithm" reason:@"Given algorithm is not supported" userInfo:nil]; + break; + } + + return position; +} + +/** + * Build new style public key data + * + * @return public key data starting with version octet + */ +- (NSData *)buildKeyBodyData:(BOOL)forceV4 { + let data = [NSMutableData dataWithCapacity:128]; + [data appendBytes:&_version length:1]; + + UInt32 timestamp = (UInt32)[self.createDate timeIntervalSince1970]; + UInt32 timestampBE = CFSwapInt32HostToBig(timestamp); + [data appendBytes:×tampBE length:4]; + + if (!forceV4 && self.version == 0x03) { + // implementation MUST NOT generate a V3 key, but MAY accept it. + // however it have to be generated here to calculate the very same fingerprint + UInt16 V3ValidityPeriodBE = CFSwapInt16HostToBig(_V3validityPeriod); + [data appendBytes:&V3ValidityPeriodBE length:2]; + } + + [data appendBytes:&_publicKeyAlgorithm length:1]; + + // publicMPI is always available, no need to decrypt + for (PGPMPI *mpi in self.publicMPIArray) { + let exportMPI = [mpi exportMPI]; + [data pgp_appendData:exportMPI]; + } + return data; +} + +// Old-style packet header for a key packet with two-octet length. +// Old but used by fingerprint and with signing +- (NSData *)exportKeyPacketOldStyle { + let data = [NSMutableData data]; + + let keyData = [self buildKeyBodyData:NO]; + + NSUInteger length = keyData.length; + UInt8 upper = (UInt8)(length >> 8); + UInt8 lower = length & 0xff; + UInt8 headWithLength[3] = {0x99, upper, lower}; + [data appendBytes:&headWithLength length:3]; + [data appendData:keyData]; + return data; +} + +#pragma mark - PGPExportable + +/** + * Packet data. Header with body data. + * + * @param error error + * + * @return data + */ +- (nullable NSData *)export:(NSError * __autoreleasing _Nullable *)error { + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return [self buildKeyBodyData:NO]; + }]; + + //TODO: to be removed when verified + // let data = [NSMutableData data]; + // + // let bodyData = [self buildKeyBodyData:NO]; + // if (!self.bodyData) { + // self.bodyData = bodyData; + // } + // + // let headerData = [self buildHeaderData:bodyData]; + // if (!self.headerData) { + // self.headerData = headerData; + // } + // [data appendData:headerData]; + // [data appendData:bodyData]; + // + // // it wont match, because input data is OLD world, and we export in NEW world format + // // NSAssert([headerData isEqualToData:self.headerData], @"Header not match"); + // if ([self class] == [PGPPublicKeyPacket class]) { + // NSAssert([bodyData isEqualToData:self.bodyData], @"Body doesn't match"); + // } + // + // return data; +} + +#pragma mark - Encrypt & Decrypt + +- (nullable NSData *)encryptData:(NSData *)data withPublicKeyAlgorithm:(PGPPublicKeyAlgorithm)publicKeyAlgorithm { + switch (publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + // return ecnrypted m + return [PGPRSA publicEncrypt:data withPublicKeyPacket:self]; + } break; + default: + // TODO: add algorithms + [NSException raise:@"PGPNotSupported" format:@"Algorith not supported"]; + break; + } + return nil; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(nullable NSZone *)zone { + let _Nullable copy = PGPCast([super copyWithZone:zone], PGPPublicKeyPacket); + if (!copy) { + return nil; + } + copy.version = self.version; + copy.createDate = [self.createDate copy]; + copy.V3validityPeriod = self.V3validityPeriod; + copy.publicKeyAlgorithm = self.publicKeyAlgorithm; + copy.publicMPIArray = [self.publicMPIArray copy]; + return copy; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPPublicSubKeyPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.h similarity index 100% rename from PGPPublicSubKeyPacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.h index 54e487e5..1c5cbad0 100644 --- a/PGPPublicSubKeyPacket.h +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.h @@ -7,9 +7,9 @@ // // Tag 14 -#import <Foundation/Foundation.h> -#import "PGPPublicKeyPacket.h" #import "PGPPacketFactory.h" +#import "PGPPublicKeyPacket.h" +#import <Foundation/Foundation.h> @interface PGPPublicSubKeyPacket : PGPPublicKeyPacket diff --git a/PGPPublicSubKeyPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.m similarity index 92% rename from PGPPublicSubKeyPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.m index 6fa8b727..a2c4de98 100644 --- a/PGPPublicSubKeyPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPPublicSubKeyPacket.m @@ -10,8 +10,7 @@ @implementation PGPPublicSubKeyPacket -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPPublicSubkeyPacketTag; } diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket+Private.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket+Private.h new file mode 100644 index 00000000..b0fb1d84 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket+Private.h @@ -0,0 +1,25 @@ +// +// PGPSecretKeyPacket+Private.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 09/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPublicKeyPacket+Private.h" +#import <ObjectivePGP/ObjectivePGP.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPSecretKeyPacket () + +@property (nonatomic, readwrite) PGPS2KUsage s2kUsage; +@property (nonatomic, /* copy, */ readwrite) PGPS2K *s2k; +@property (nonatomic, readwrite) PGPSymmetricAlgorithm symmetricAlgorithm; +@property (nonatomic, copy, nullable, readwrite) NSData *ivData; +@property (nonatomic, copy) NSArray<PGPMPI *> *secretMPIArray; // decrypted MPI +@property (nonatomic, nullable, copy) NSData *encryptedMPIPartData; // after decrypt -> secretMPIArray + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.h new file mode 100644 index 00000000..b3564fb6 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.h @@ -0,0 +1,36 @@ +// +// PGPSecretKeyPacket.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 07/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPublicKeyPacket.h" +#import "PGPS2K.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPSecretKeyPacket : PGPPublicKeyPacket <NSCopying, PGPExportable> + +@property (nonatomic, readonly) PGPS2KUsage s2kUsage; +@property (nonatomic, readonly) PGPS2K *s2k; +@property (nonatomic, readonly) PGPSymmetricAlgorithm symmetricAlgorithm; +@property (nonatomic, nullable, copy, readonly) NSData *ivData; +@property (nonatomic, getter=isEncryptedWithPassphrase, readonly) BOOL encryptedWithPassphrase; + +/** + * Decrypt packet + * + * @param passphrase Passphrase + * @param error error + * + * @return Decrypted key on success + */ +- (nullable PGPSecretKeyPacket *)decryptedKeyPacket:(NSString *)passphrase error:(NSError *__autoreleasing *)error; + +- (nullable PGPMPI *)secretMPI:(NSString *)identifier; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.m new file mode 100644 index 00000000..912d6660 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretKeyPacket.m @@ -0,0 +1,401 @@ +// +// PGPSecretKeyPacket.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 07/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// +// A Secret-Key packet contains all the information that is found in a +// Public-Key packet, including the public-key material, but also +// includes the secret-key material after all the public-key fields. + +#import "PGPSecretKeyPacket.h" +#import "PGPSecretKeyPacket+Private.h" +#import "PGPPacket+Private.h" +#import "PGPMPI.h" +#import "PGPS2K.h" +#import "PGPTypes.h" +#import "NSMutableData+PGPUtils.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +#import "NSData+PGPUtils.h" +#import "PGPCryptoCFB.h" +#import "PGPCryptoUtils.h" +#import "PGPRSA.h" + +@interface PGPSecretKeyPacket () + +@property (nonatomic) BOOL wasDecrypted; // is decrypted + +@end + +@implementation PGPSecretKeyPacket + +- (PGPPacketTag)tag { + return PGPSecretKeyPacketTag; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ isEncryptedWithPassphrase: %@", super.description, @(self.isEncryptedWithPassphrase)]; +} + +// Don't really know if key is passphrase protected. +// Check the S2K settings and assume if the passphrase is set. +- (BOOL)isEncryptedWithPassphrase { + if (self.wasDecrypted) { + return NO; + } + + return (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed); +} + +- (nullable PGPMPI *)secretMPI:(NSString *)identifier { + for (PGPMPI *mpi in self.secretMPIArray) { + if ([mpi.identifier isEqual:identifier]) { + return mpi; + } + } + + return nil; +} + +- (PGPFingerprint *)fingerprint { + return [super fingerprint]; +} + +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + NSUInteger position = [super parsePacketBody:packetBody error:error]; + // 5.5.3. Secret-Key Packet Formats + + NSAssert(self.version == 0x04 || self.version == 0x03, @"Only Secret Key version 3 and 4 is supported. Found version %@", @(self.version)); + + // One octet indicating string-to-key usage conventions + [packetBody getBytes:&_s2kUsage range:(NSRange){position, 1}]; + position = position + 1; + + if (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { + // moved to parseEncryptedPart:error + } else if (self.s2kUsage != PGPS2KUsageNonEncrypted) { + // this is version 3, looks just like a V4 simple hash + self.symmetricAlgorithm = (PGPSymmetricAlgorithm)self.s2kUsage; // this is tricky, but this is right. V3 algorithm is in place of s2kUsage of V4 + self.s2kUsage = PGPS2KUsageEncrypted; + + self.s2k = [[PGPS2K alloc] initWithSpecifier:PGPS2KSpecifierSimple hashAlgorithm:PGPHashMD5]; // not really parsed s2k, overwritten in parseEncryptedPart + } + + let encryptedData = [packetBody subdataWithRange:(NSRange){position, packetBody.length - position}]; + if (self.isEncryptedWithPassphrase) { + position = position + [self parseEncryptedPart:encryptedData error:error]; + } else { + position = position + [self parseUnencryptedPart:encryptedData error:error]; + } + + return position; +} + +/** + * Encrypted algorithm-specific fields for secret keys + * + * @param data Encrypted data + * @param error error + * + * @return length + */ +- (NSUInteger)parseEncryptedPart:(NSData *)data error:(NSError *__autoreleasing *)error { + NSUInteger position = 0; + + if (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { + // If string-to-key usage octet was 255 or 254, a one-octet symmetric encryption algorithm + [data getBytes:&_symmetricAlgorithm range:(NSRange){position, 1}]; + position = position + 1; + + // S2K + NSUInteger s2kParsedLength = 0; + self.s2k = [PGPS2K S2KFromData:data atPosition:position length:&s2kParsedLength]; + position = position + s2kParsedLength; + } + + if (self.s2k.specifier == PGPS2KSpecifierGnuDummy) { + self.ivData = NSData.data; + } else if (self.s2kUsage != PGPS2KUsageNonEncrypted) { + // Initial Vector (IV) of the same length as the cipher's block size + NSUInteger blockSize = [PGPCryptoUtils blockSizeOfSymmetricAlhorithm:self.symmetricAlgorithm]; + NSAssert(blockSize <= 16, @"invalid blockSize"); + self.ivData = [data subdataWithRange:(NSRange){position, blockSize}]; + position = position + blockSize; + } + + // encrypted MPIArray + // checksum or hash is encrypted together with the algorithm-specific fields (mpis) (if string-to-key usage octet is not zero). + self.encryptedMPIPartData = [data subdataWithRange:(NSRange){position, data.length - position}]; + // position = position + self.encryptedMPIPartData.length; + + return data.length; +} + +/** + * Cleartext part, parse cleartext or unencrypted data + * Store decrypted values in secretMPI array + * + * @param data packet data + * @param error error + * + * @return length + */ +- (NSUInteger)parseUnencryptedPart:(NSData *)data error:(NSError *__autoreleasing *)error { + NSUInteger position = 0; + + // check hash before read actual data + // hash is physically located at the end of dataBody + switch (self.s2kUsage) { + case PGPS2KUsageEncryptedAndHashed: { + // a 20-octet SHA-1 hash of the plaintext of the algorithm-specific portion. + NSUInteger hashSize = [PGPCryptoUtils hashSizeOfHashAlhorithm:PGPHashSHA1]; + if (hashSize == NSNotFound) { + PGPLogWarning(@"Invalid hash size"); + return 0; + } + + let clearTextData = [data subdataWithRange:(NSRange){0, data.length - hashSize}]; + let hashData = [data subdataWithRange:(NSRange){data.length - hashSize, hashSize}]; + let calculatedHashData = clearTextData.pgp_SHA1; + + if (![hashData isEqualToData:calculatedHashData]) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorPassphraseInvalid userInfo:@{ NSLocalizedDescriptionKey: @"Decrypted hash mismatch, invalid passphrase." }]; + return data.length; + } + } + + } break; + default: { + // a two-octet checksum of the plaintext of the algorithm-specific portion + NSUInteger checksumLength = 2; + let clearTextData = [data subdataWithRange:(NSRange){0, data.length - checksumLength}]; + let checksumData = [data subdataWithRange:(NSRange){data.length - checksumLength, checksumLength}]; + NSUInteger calculatedChecksum = clearTextData.pgp_Checksum; + + UInt16 checksum = 0; + [checksumData getBytes:&checksum length:checksumLength]; + checksum = CFSwapInt16BigToHost(checksum); + + if (checksum != calculatedChecksum) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey: @"Decrypted hash mismatch, check passphrase." }]; + return data.length; + } + } + } break; + } + + // now read the actual data + switch (self.publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + // multiprecision integer (MPI) of RSA secret exponent d. + let mpiD = [[PGPMPI alloc] initWithMPIData:data identifier:PGPMPI_D atPosition:position]; + position = position + mpiD.packetLength; + + // MPI of RSA secret prime value p. + let mpiP = [[PGPMPI alloc] initWithMPIData:data identifier:PGPMPI_P atPosition:position]; + position = position + mpiP.packetLength; + + // MPI of RSA secret prime value q (p < q). + let mpiQ = [[PGPMPI alloc] initWithMPIData:data identifier:PGPMPI_Q atPosition:position]; + position = position + mpiQ.packetLength; + + // MPI of u, the multiplicative inverse of p, mod q. + let mpiU = [[PGPMPI alloc] initWithMPIData:data identifier:PGPMPI_U atPosition:position]; + position = position + mpiU.packetLength; + + self.secretMPIArray = @[mpiD, mpiP, mpiQ, mpiU]; + } break; + case PGPPublicKeyAlgorithmDSA: { + // MPI of DSA secret exponent x. + let mpiX = [[PGPMPI alloc] initWithMPIData:data identifier:PGPMPI_X atPosition:position]; + position = position + mpiX.packetLength; + + self.secretMPIArray = @[mpiX]; + } break; + case PGPPublicKeyAlgorithmElgamal: + case PGPPublicKeyAlgorithmElgamalEncryptorSign: { + // MPI of Elgamal secret exponent x. + let mpiX = [[PGPMPI alloc] initWithMPIData:data identifier:PGPMPI_X atPosition:position]; + position = position + mpiX.packetLength; + + self.secretMPIArray = @[mpiX]; + } break; + default: + break; + } + + return data.length; +} + +#pragma mark - Decrypt + +/** + * Decrypt parsed encrypted packet + * Decrypt packet and store decrypted data on instance + * TODO: V3 support - partially supported, need testing. + * NOTE: Decrypted packet data should be released/forget after use + */ +- (nullable PGPSecretKeyPacket *)decryptedKeyPacket:(NSString *)passphrase error:(NSError *__autoreleasing *)error { + PGPAssertClass(passphrase, NSString); + NSParameterAssert(error); + + if (!self.isEncryptedWithPassphrase) { + PGPLogDebug(@"No need to decrypt key."); + return self; + } + + if (!self.ivData) { + PGPLogError(@"IV is missing..."); + if (error) { *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"IV is missing" } ]; }; + return nil; + } + + PGPSecretKeyPacket *encryptedKey = self.copy; + let encryptionSymmetricAlgorithm = encryptedKey.symmetricAlgorithm; + + // Session key for passphrase + // producing a key to be used with a symmetric block cipher from a string of octets + let sessionKeyData = [encryptedKey.s2k produceSessionKeyWithPassphrase:passphrase symmetricAlgorithm:encryptionSymmetricAlgorithm]; + + // Decrypted MPIArray + let decryptedData = [PGPCryptoCFB decryptData:encryptedKey.encryptedMPIPartData sessionKeyData:sessionKeyData symmetricAlgorithm:encryptionSymmetricAlgorithm iv:encryptedKey.ivData]; + + // now read mpis + if (decryptedData) { + [encryptedKey parseUnencryptedPart:decryptedData error:error]; + if (*error) { + return nil; + } + } + encryptedKey.wasDecrypted = YES; + return encryptedKey; +} + +#pragma mark - Private + +/** + * Build public key data for fingerprint + * + * @return public key data starting with version octet + */ +- (NSData *)buildSecretKeyDataAndForceV4:(BOOL)forceV4 { + NSAssert(forceV4 == YES, @"Only V4 is supported"); + + let data = [NSMutableData data]; + [data appendBytes:&self->_s2kUsage length:1]; + + if (self.s2kUsage == PGPS2KUsageEncrypted || self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { + // If string-to-key usage octet was 255 or 254, a one-octet symmetric encryption algorithm + [data appendBytes:&self->_symmetricAlgorithm length:1]; + + // If string-to-key usage octet was 255 or 254, a string-to-key specifier. + NSError *exportError = nil; + let exportS2K = [self.s2k export:&exportError]; + [data pgp_appendData:exportS2K]; + NSAssert(!exportError, @"export failed"); + } + + if (self.s2kUsage != PGPS2KUsageNonEncrypted) { + NSAssert(self.ivData, @"Require IV"); + // If secret data is encrypted (string-to-key usage octet not zero), an Initial Vector (IV) of the same length as the cipher's block size. + // Initial Vector (IV) of the same length as the cipher's block size + [data appendData:self.ivData]; + } + + if (self.s2kUsage == PGPS2KUsageNonEncrypted) { + for (PGPMPI *mpi in self.secretMPIArray) { + let exportMPI = [mpi exportMPI]; + [data pgp_appendData:exportMPI]; + } + + // append hash + UInt16 checksum = CFSwapInt16HostToBig(data.pgp_Checksum); + [data appendBytes:&checksum length:2]; + } else if (self.encryptedMPIPartData) { + // encrypted MPIArray with encrypted hash + // hash is part of encryptedMPIPartData + [data pgp_appendData:self.encryptedMPIPartData]; + } else { + PGPLogWarning(@"Cannot build secret key data. Missing secret MPIs...."); + } + + // If the string-to-key usage octet is zero or 255, then a two-octet checksum of the plaintext of the algorithm-specific portion (sum of all octets, mod 65536). + // This checksum or hash is encrypted together with the algorithm-specific fields + // ---> is part of self.encryptedMPIPartData + // if (self.s2kUsage == PGPS2KUsageNonEncrypted || self.s2kUsage == PGPS2KUsageEncrypted) { + // // Checksum + // UInt16 checksum = CFSwapInt16HostToBig([data pgp_Checksum]); + // [data appendBytes:&checksum length:2]; + //} else if (self.s2kUsage == PGPS2KUsageEncryptedAndHashed) { + // // If the string-to-key usage octet was 254, then a 20-octet SHA-1 hash of the plaintext of the algorithm-specific portion. + // [data appendData:[data pgp_SHA1]]; + //} + + // } else if (self.s2kUsage != PGPS2KUsageNonEncrypted) { + // // this is version 3, looks just like a V4 simple hash + // self.symmetricAlgorithm = (PGPSymmetricAlgorithm)self.s2kUsage; // this is tricky, but this is right. V3 algorithm is in place of s2kUsage of V4 + // self.s2kUsage = PGPS2KUsageEncrypted; + // + // self.s2k = [[PGPS2K alloc] init]; // not really parsed s2k + // self.s2k.specifier = PGPS2KSpecifierSimple; + // self.s2k.algorithm = PGPHashMD5; + + return data; +} + +#pragma mark - PGPExportable + +- (nullable NSData *)export:(NSError *__autoreleasing _Nullable *)error { + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + let secretKeyPacketData = [NSMutableData data]; + [secretKeyPacketData appendData:[self buildKeyBodyData:YES]]; + [secretKeyPacketData appendData:[self buildSecretKeyDataAndForceV4:YES]]; + return secretKeyPacketData; + }]; + + //TODO: to be removed when verified + // let data = [NSMutableData data]; + // let publicKeyData = [super buildKeyBodyData:YES]; + // + // let secretKeyPacketData = [NSMutableData data]; + // [secretKeyPacketData appendData:publicKeyData]; + // [secretKeyPacketData appendData:[self buildSecretKeyDataAndForceV4:YES]]; + // if (!self.bodyData) { + // self.bodyData = secretKeyPacketData; + // } + // + // let headerData = [self buildHeaderData:secretKeyPacketData]; + // if (!self.headerData) { + // self.headerData = headerData; + // } + // [data appendData:headerData]; + // [data appendData:secretKeyPacketData]; + // + // // header not always match because export new format while input can be old format + // NSAssert(!self.bodyData || [secretKeyPacketData isEqualToData:self.bodyData], @"Secret key doesn't match"); + // return data; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone { + PGPSecretKeyPacket *copy = [super copyWithZone:zone]; + copy->_s2kUsage = self.s2kUsage; + copy->_s2k = [self.s2k copy]; + copy->_symmetricAlgorithm = self.symmetricAlgorithm; + copy->_ivData = [self.ivData copy]; + copy->_secretMPIArray = [self.secretMPIArray copy]; + copy->_encryptedMPIPartData = [self.encryptedMPIPartData copy]; + copy->_wasDecrypted = self.wasDecrypted; + return copy; +} + +@end diff --git a/PGPSecretSubKeyPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretSubKeyPacket.h similarity index 100% rename from PGPSecretSubKeyPacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPSecretSubKeyPacket.h diff --git a/PGPSecretSubKeyPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretSubKeyPacket.m similarity index 91% rename from PGPSecretSubKeyPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPSecretSubKeyPacket.m index 03bddb14..5497b97c 100644 --- a/PGPSecretSubKeyPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSecretSubKeyPacket.m @@ -8,18 +8,15 @@ // A Secret-Subkey packet (tag 7) is the subkey analog of the Secret // Key packet and has exactly the same format. - #import "PGPSecretSubKeyPacket.h" @implementation PGPSecretSubKeyPacket -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPSecretSubkeyPacketTag; } -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { return [super parsePacketBody:packetBody error:error]; } diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket+Private.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket+Private.h new file mode 100644 index 00000000..4fba0388 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket+Private.h @@ -0,0 +1,29 @@ +// +// PGPSignaturePacket+Private.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <ObjectivePGP/ObjectivePGP.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPSignaturePacket () + +@property (nonatomic, copy, readwrite) NSArray<PGPSignatureSubpacket *> *hashedSubpackets; +@property (nonatomic, copy, readwrite) NSArray<PGPSignatureSubpacket *> *unhashedSubpackets; + +PGP_EMPTY_INIT_UNAVAILABLE + ++ (PGPSignaturePacket *)signaturePacket:(PGPSignatureType)type hashAlgorithm:(PGPHashAlgorithm)hashAlgorithm; + +- (nullable NSData *)buildDataToSignForType:(PGPSignatureType)type inputData:(nullable NSData *)inputData key:(nullable PGPKey *)key subKey:(nullable PGPKey *)subKey keyPacket:(nullable PGPPublicKeyPacket *)signingKeyPacket userID:(nullable NSString *)userID error:(NSError *__autoreleasing _Nullable *)error; + +- (nullable PGPMPI *)signatureMPI:(NSString *)identifier; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.h new file mode 100644 index 00000000..8147af32 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.h @@ -0,0 +1,76 @@ +// +// PGPSignature.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// +// Tag 2 + +#import "PGPKeyID.h" +#import "PGPMPI.h" +#import "PGPPacketFactory.h" +#import "PGPSignatureSubpacket.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPPartialKey, PGPUser, PGPUserIDPacket, PGPPublicKeyPacket, PGPKey; + +@interface PGPSignaturePacket : PGPPacket <NSCopying> + +@property (nonatomic) UInt8 version; +@property (nonatomic) PGPSignatureType type; +@property (nonatomic) PGPPublicKeyAlgorithm publicKeyAlgorithm; +@property (nonatomic) PGPHashAlgorithm hashAlgoritm; +@property (nonatomic, copy, readonly) NSArray<PGPSignatureSubpacket *> *hashedSubpackets; +@property (nonatomic, copy, readonly) NSArray<PGPSignatureSubpacket *> *unhashedSubpackets; +/// Two-octet field holding the left 16 bits of the signed hash value. +/// Read from the key or set byt the call to `-[PGPSignaturePacket signData:usingKey:passphrase:userID:error]` +@property (nonatomic, nullable) NSData *signedHashValueData; +@property (nonatomic, copy) NSArray<PGPMPI *> *signatureMPIArray; + +@property (nonatomic, readonly) BOOL canBeUsedToSign; // computed +@property (nonatomic, readonly) BOOL canBeUsedToEncrypt; // computed + +@property (nonatomic, nullable, readonly) PGPKeyID *issuerKeyID; +@property (nonatomic, copy, readonly) NSArray<PGPSignatureSubpacket *> *subpackets; +@property (nonatomic, nullable, readonly) NSDate *expirationDate; // computed +@property (nonatomic, readonly, readonly, getter=isExpired) BOOL expired; // computed +@property (nonatomic, nullable, readonly) NSDate *creationDate; // computed +@property (nonatomic, readonly, readonly, getter=isPrimaryUserID) BOOL primaryUserID; // computed + +/** + * Create signature packet for signing. This is convienience constructor. + * + * @param type example: PGPSignatureBinaryDocument + * @param hashAlgorithm hash algorithm to be used for signature + * + * @return Packet instance ready to call signData:secretKey + */ ++ (PGPSignaturePacket *)signaturePacket:(PGPSignatureType)type hashAlgorithm:(PGPHashAlgorithm)hashAlgorithm; + +- (NSArray<PGPSignatureSubpacket *> *)subpacketsOfType:(PGPSignatureSubpacketType)type; +- (NSData *)calculateSignedHashForDataToSign:(NSData *)dataToSign; + +/** + * Build signature data (signature packet with subpackets). + * + * @param inputData Data to sign. + * @param key A key used to create signature. + * @param subKey Optional. if signature subkey can't be found automatically. + * @param passphrase Optional. Key passphrase do decrypt. + * @param userID Optional. + * @param error error + * + * @return YES on success. + */ +- (BOOL)signData:(nullable NSData *)inputData withKey:(PGPKey *)key subKey:(nullable PGPKey *)subKey passphrase:(nullable NSString *)passphrase userID:(nullable NSString *)userID error:(NSError *__autoreleasing *)error; + +- (BOOL)verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey error:(NSError *__autoreleasing *)error; +- (BOOL)verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey userID:(nullable NSString *)userID error:(NSError *__autoreleasing *)error; +- (BOOL)verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey signingKeyPacket:(PGPPublicKeyPacket *)signingKeyPacket userID:(nullable NSString *)userID error:(NSError *__autoreleasing *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.m new file mode 100644 index 00000000..0212e0bf --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignaturePacket.m @@ -0,0 +1,851 @@ +// +// PGPSignature.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPSignaturePacket.h" +#import "PGPSignaturePacket+Private.h" +#import "NSData+PGPUtils.h" +#import "PGPKey.h" +#import "PGPLiteralPacket.h" +#import "PGPMPI.h" +#import "PGPPKCSEmsa.h" +#import "PGPPartialKey.h" +#import "PGPRSA.h" +#import "PGPDSA.h" +#import "PGPSecretKeyPacket.h" +#import "PGPSignatureSubpacket.h" +#import "PGPSignatureSubpacket+Private.h" +#import "PGPSignatureSubpacketHeader.h" +#import "PGPUser.h" +#import "PGPUserIDPacket.h" +#import "NSMutableData+PGPUtils.h" + +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +#import <openssl/bn.h> +#import <openssl/dsa.h> +#import <openssl/err.h> +#import <openssl/rsa.h> +#import <openssl/ssl.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPSignaturePacket () + +- (instancetype)init; + +@end + +@implementation PGPSignaturePacket + +- (instancetype)init { + if (self = [super init]) { + _version = 0x4; + _hashedSubpackets = [NSArray<PGPSignatureSubpacket *> array]; + _unhashedSubpackets = [NSArray<PGPSignatureSubpacket *> array]; + _signatureMPIArray = [NSArray<PGPMPI *> array]; + } + return self; +} + ++ (PGPSignaturePacket *)signaturePacket:(PGPSignatureType)type hashAlgorithm:(PGPHashAlgorithm)hashAlgorithm { + let signaturePacket = [[PGPSignaturePacket alloc] init]; + signaturePacket.type = type; + signaturePacket.hashAlgoritm = hashAlgorithm; + return signaturePacket; +} + +- (PGPPacketTag)tag { + return PGPSignaturePacketTag; +} + +#pragma mark - Helper properties + +- (nullable PGPKeyID *)issuerKeyID { + let subpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeIssuerKeyID] firstObject]; + return subpacket.value; +} + +- (NSArray<PGPSignatureSubpacket *> *)subpackets { + return [self.hashedSubpackets arrayByAddingObjectsFromArray:self.unhashedSubpackets ?: @[]]; +} + +- (NSArray<PGPSignatureSubpacket *> *)subpacketsOfType:(PGPSignatureSubpacketType)type { + let filteredSubpackets = [NSMutableArray<PGPSignatureSubpacket *> array]; + for (PGPSignatureSubpacket *subPacket in self.subpackets) { + if ((subPacket.type & 0x7F) == type) { + [filteredSubpackets addObject:subPacket]; + } + } + return filteredSubpackets; +} + +- (nullable NSDate *)expirationDate { + PGPSignatureSubpacket *creationDateSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeSignatureCreationTime] firstObject]; + PGPSignatureSubpacket *validityPeriodSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeSignatureExpirationTime] firstObject]; + if (!validityPeriodSubpacket) { + validityPeriodSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeKeyExpirationTime] firstObject]; + } + + let creationDate = PGPCast(creationDateSubpacket.value, NSDate); + let validityPeriod = PGPCast(validityPeriodSubpacket.value, NSNumber); + if (!validityPeriod || validityPeriod.unsignedIntegerValue == 0) { + return nil; + } + + return [creationDate dateByAddingTimeInterval:validityPeriod.unsignedIntegerValue]; +} + +- (BOOL)isExpired { + // is no expiration date then signature never expires + let expirationDate = self.expirationDate; + if (!expirationDate) { + return NO; + } + + if ([expirationDate compare:NSDate.date] == NSOrderedAscending) { + return YES; + } + return NO; +} + +- (nullable NSDate *)creationDate { + PGPSignatureSubpacket *creationDateSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeSignatureCreationTime] lastObject]; + return creationDateSubpacket.value; +} + +- (BOOL)isPrimaryUserID { + PGPSignatureSubpacket *primaryUserIDSubpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypePrimaryUserID] firstObject]; + return [(NSNumber *)primaryUserIDSubpacket.value boolValue]; +} + +- (BOOL)canBeUsedToSign { + BOOL result = self.publicKeyAlgorithm == PGPPublicKeyAlgorithmDSA || self.publicKeyAlgorithm == PGPPublicKeyAlgorithmRSA || self.publicKeyAlgorithm == PGPPublicKeyAlgorithmRSASignOnly; + + if (result) { + PGPSignatureSubpacket *subpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeKeyFlags] firstObject]; + NSArray *flags = subpacket.value; + if ([flags containsObject:@(PGPSignatureFlagAllowSignData)]) { + return YES; + } + } + return NO; +} + +- (BOOL)canBeUsedToEncrypt { + BOOL result = NO; + PGPSignatureSubpacket *subpacket = [[self subpacketsOfType:PGPSignatureSubpacketTypeKeyFlags] firstObject]; + NSArray *flags = subpacket.value; + if ([flags containsObject:@(PGPSignatureFlagAllowEncryptStorage)] || [flags containsObject:@(PGPSignatureFlagAllowEncryptCommunications)]) { + result = YES; + } + + // I'm not convinced if DSA is allowed here self.publicKeyAlgorithm != PGPPublicKeyAlgorithmDSA + result = result && self.publicKeyAlgorithm != PGPPublicKeyAlgorithmRSASignOnly && self.publicKeyAlgorithm != PGPPublicKeyAlgorithmElgamalEncryptorSign; + + return result; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@, sign: %@, encrypt: %@", super.description, @(self.canBeUsedToSign), @(self.canBeUsedToEncrypt)]; +} + +- (nullable PGPMPI *)signatureMPI:(NSString *)identifier { + for (PGPMPI *mpi in self.signatureMPIArray) { + if ([mpi.identifier isEqualToString:identifier]) { + return mpi; + } + } + + return nil; +} + +#pragma mark - Build packet + +- (nullable NSData *)export:(NSError *__autoreleasing *)error { + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return [self buildFullSignatureBodyData:error]; + }]; +} + +- (NSData *)buildSignedPart:(NSArray *)hashedSubpackets { + let data = [NSMutableData data]; + + // One-octet version number (4). + UInt8 exportVersion = 0x04; + [data appendBytes:&exportVersion length:1]; + + // One-octet signature type. + [data appendBytes:&_type length:1]; + + // One-octet public-key algorithm. + [data appendBytes:&_publicKeyAlgorithm length:1]; + + // One-octet hash algorithm. + [data appendBytes:&_hashAlgoritm length:1]; + + // hashed Subpackets + [data appendData:[self buildSubpacketsCollectionData:hashedSubpackets]]; + + return data; +} + +- (NSData *)buildFullSignatureBodyData:(NSError *__autoreleasing *)error { + let data = [NSMutableData data]; + + // hashed Subpackets + let signedPartData = [self buildSignedPart:self.hashedSubpackets]; + [data appendData:signedPartData]; + + // unhashed Subpackets + [data appendData:[self buildSubpacketsCollectionData:self.unhashedSubpackets]]; + + // signed hash value + NSAssert(self.signedHashValueData, @"Missing signed hash"); + [data appendData:self.signedHashValueData]; + + // signed PGPMPI_M + NSAssert(self.signatureMPIArray.count > 0, @"Missing MPIArray"); + for (PGPMPI *mpi in self.signatureMPIArray) { + let exportMPI = [mpi exportMPI]; + [data pgp_appendData:exportMPI]; + } + + return data; +} + +- (NSData *)calculateSignedHashForDataToSign:(NSData *)dataToSign { + // The concatenation of the data being signed and the signature data + // from the version number through the hashed subpacket data (inclusive) + // is hashed. + // toHash = toSignData + signedPartData + trailerData; + let finalToHashData = [NSMutableData dataWithData:dataToSign]; + + let signedPartData = [self buildSignedPart:self.hashedSubpackets]; + [finalToHashData appendData:signedPartData]; + + let _Nullable trailerData = [self calculateTrailerFor:signedPartData]; + [finalToHashData appendData:trailerData]; + + // Calculate hash value + return [finalToHashData pgp_HashedWithAlgorithm:self.hashAlgoritm]; +} + +#pragma mark - Verify + +- (BOOL)verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey error:(NSError *__autoreleasing *)error { + return [self verifyData:inputData withKey:publicKey signingKeyPacket:(PGPPublicKeyPacket *)[publicKey.publicKey signingKeyPacketWithKeyID:self.issuerKeyID] userID:nil error:error]; +} + +- (BOOL)verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey userID:(nullable NSString *)userID error:(NSError *__autoreleasing *)error { + return [self verifyData:inputData withKey:publicKey signingKeyPacket:(PGPPublicKeyPacket *)[publicKey.publicKey signingKeyPacketWithKeyID:self.issuerKeyID] userID:userID error:error]; +} + +// Opposite to sign, with readed data (not produced) +- (BOOL)verifyData:(NSData *)inputData withKey:(PGPKey *)publicKey signingKeyPacket:(PGPPublicKeyPacket *)signingKeyPacket userID:(nullable NSString *)userID error:(NSError *__autoreleasing *)error { + // no signing packet was found, this we have no valid signature + PGPAssertClass(signingKeyPacket, PGPPublicKeyPacket); + + // FIXME: publicKey is actually secret key sometimes? + + if (self.type == PGPSignatureBinaryDocument && inputData.length == 0) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Invalid signature packet type" }]; + } + return NO; + } + + // 5.2.4. Computing Signatures + + // build toSignData, toSign + let toSignData = [self buildDataToSignForType:self.type inputData:inputData key:publicKey subKey:nil keyPacket:signingKeyPacket userID:userID error:error]; + if (!toSignData) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Invalid signature." }]; + } + return NO; + } + + /// Calculate hash to compare + // signedPartData + let signedPartData = [self buildSignedPart:self.hashedSubpackets]; + // calculate trailer + let trailerData = [self calculateTrailerFor:signedPartData]; + + // toHash = toSignData + signedPartData + trailerData; + let toHashData = [NSMutableData dataWithData:toSignData]; + [toHashData appendData:signedPartData]; + [toHashData appendData:trailerData]; + + // FIXME: propably will fail on V3 signature, need investigate how to handle V3 scenario here + // check signed hash value, should match + if (self.version == 0x04) { + // Calculate hash value + let calculatedHashValueData = [toHashData pgp_HashedWithAlgorithm:self.hashAlgoritm]; + + if (![self.signedHashValueData isEqualToData:[calculatedHashValueData subdataWithRange:(NSRange){0, 2}]]) { + return NO; + } + } + + switch (signingKeyPacket.publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSASignOnly: + case PGPPublicKeyAlgorithmRSAEncryptOnly: { + // convert mpi data to binary signature_bn_bin + let signatureMPI = self.signatureMPIArray[0]; + + // encoded m value + NSData *encryptedEmData = [signatureMPI bodyData]; + // decrypted encoded m value + NSData *decryptedEmData = [PGPRSA publicDecrypt:encryptedEmData withPublicKeyPacket:signingKeyPacket]; + + // calculate EM and compare with decrypted EM. PKCS-emsa Encoded M. + NSData *emData = [PGPPKCSEmsa encode:self.hashAlgoritm message:toHashData encodedMessageLength:signingKeyPacket.keySize error:error]; + if (![emData isEqualToData:decryptedEmData]) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"em hash dont match" }]; + } + return NO; + } + } break; + case PGPPublicKeyAlgorithmDSA: + case PGPPublicKeyAlgorithmECDSA: { + return [PGPDSA verify:toHashData signature:self withPublicKeyPacket:signingKeyPacket]; + } break; + default: + [NSException raise:@"PGPNotSupported" format:@"Algorith not supported"]; + break; + } + + return YES; +} + +#pragma mark - Sign + +// 5.2.4. Computing Signatures +// http://tools.ietf.org/html/rfc4880#section-5.2.4 +// @see https://github.com/singpolyma/openpgp-spec/blob/master/key-signatures + +/// Sign the signature with the given key. +/// Set signatureMPIArray and updates signed hash. +/// +/// Update sign related values. This method mutate the signature. +- (BOOL)signData:(nullable NSData *)inputData withKey:(PGPKey *)key subKey:(nullable PGPKey *)subKey passphrase:(nullable NSString *)passphrase userID:(nullable NSString *)userID error:(NSError *__autoreleasing *)error { + PGPAssertClass(key, PGPKey); + + if (!key.secretKey) { + PGPLogDebug(@"Invalid key."); + return NO; + } + + PGPAssertClass(key.secretKey.primaryKeyPacket, PGPSecretKeyPacket); // Signing key packet not found + + var signingKeyPacket = key.signingSecretKey; + if (!signingKeyPacket) { + // As of PGP Desktop. The signing signature may be missing. + PGPLogDebug(@"Missing signature for the secret key %@", key.secretKey.keyID); + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"No signing signature found" }]; + } + return NO; + } + + // TODO: check it this is right ? setup public key algorithm from secret key packet + self.publicKeyAlgorithm = signingKeyPacket.publicKeyAlgorithm; + + if (signingKeyPacket.isEncryptedWithPassphrase && passphrase && passphrase.length > 0) { + NSError *decryptError; + // Copy secret key instance, then decrypt on copy, not on the original (do not leave unencrypted instance around) + signingKeyPacket = [signingKeyPacket decryptedKeyPacket:PGPNN(passphrase) error:&decryptError]; + + // When error can be passed back to caller, we want to avoid assertion, since there is no way to + // know if packet can be decrypted and it is a typical user error to provide the wrong passhrase. + if(signingKeyPacket == nil && error != nil) { + *error = decryptError; + return NO; + } + + NSAssert(signingKeyPacket && !decryptError, @"decrypt error %@", decryptError); + } + + // signed part data + if (self.hashedSubpackets.count == 0) { + // add hashed subpacket - REQUIRED + let creationTimeSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeSignatureCreationTime andValue:NSDate.date]; + self.hashedSubpackets = @[creationTimeSubpacket]; + PGPLogWarning(@"Signature without subpackets. Define subpackets! Adding minimal set of subpackets."); + } + + let signedPartData = [self buildSignedPart:self.hashedSubpackets]; + // calculate trailer + let _Nullable trailerData = [self calculateTrailerFor:signedPartData]; + + // build toSignData, toSign + let toSignData = [self buildDataToSignForType:self.type inputData:inputData key:key subKey:subKey keyPacket:signingKeyPacket userID:userID error:error]; + // toHash = toSignData + signedPartData + trailerData; + let toHashData = [NSMutableData dataWithData:toSignData]; + [toHashData appendData:signedPartData]; + [toHashData appendData:trailerData]; + + // == Computing Signatures == + // Encrypt hash data Packet signature MPIArray + switch (self.publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + // Encrypted m value (PKCS emsa encrypted) + NSData *em = [PGPPKCSEmsa encode:self.hashAlgoritm message:toHashData encodedMessageLength:signingKeyPacket.keySize error:nil]; + NSData *encryptedEmData = nil; + encryptedEmData = [PGPRSA privateEncrypt:em withSecretKeyPacket:signingKeyPacket]; + if (!encryptedEmData) { + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Sign Encryption failed" }]; + } + return NO; + } + + // store signature data as MPI + self.signatureMPIArray = @[[[PGPMPI alloc] initWithData:encryptedEmData identifier:PGPMPI_M]]; + } break; + case PGPPublicKeyAlgorithmDSA: + case PGPPublicKeyAlgorithmECDSA: { + self.signatureMPIArray = [PGPDSA sign:toHashData key:key]; + } break; + default: + [NSException raise:@"PGPNotSupported" format:@"Algorith not supported"]; + break; + } + + if (self.unhashedSubpackets.count == 0) { + // add unhashed PGPSignatureSubpacketTypeIssuer subpacket - REQUIRED + let keyid = [[PGPKeyID alloc] initWithFingerprint:signingKeyPacket.fingerprint]; + PGPSignatureSubpacket *issuerSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeIssuerKeyID andValue:keyid]; + self.unhashedSubpackets = @[issuerSubpacket]; + PGPLogWarning(@"Signature without subpackets. Define subpackets! Adding minimal set of subpackets."); + } + + // Checksum + // Two-octet field holding the left 16 bits of the signed hash value. + // Calculate hash value + let hashValueData = [[self calculateSignedHashForDataToSign:toSignData] subdataWithRange:(NSRange){0, 2}]; + self.signedHashValueData = hashValueData; + return YES; +} + +- (nullable NSData *)buildDataToSignForType:(PGPSignatureType)type inputData:(nullable NSData *)inputData key:(nullable PGPKey *)key subKey:(nullable PGPKey *)subKey keyPacket:(nullable PGPPublicKeyPacket *)signingKeyPacket userID:(nullable NSString *)userID error:(NSError *__autoreleasing _Nullable *)error { + let toSignData = [NSMutableData data]; + switch (type) { + case PGPSignatureBinaryDocument: + case PGPSignatureCanonicalTextDocument: { + if (!inputData) { + PGPLogError(@"Invalid paramaters."); + if (error) { *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing input data" }]; } + return nil; + } + [toSignData appendData:inputData]; + } break; + case PGPSignatureSubkeyBinding: // 0x18 + case PGPSignaturePrimaryKeyBinding: { // 0x19 + if (!signingKeyPacket) { + PGPLogError(@"Invalid paramaters"); + if (error) { *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing key packet." }]; } + return nil; + } + + let signingKeyData = [signingKeyPacket exportKeyPacketOldStyle]; + [toSignData appendData:signingKeyData]; + + // A subkey binding signature (type 0x18) or primary key binding signature (type 0x19) then hashes + // the subkey using the same format as the main key (also using 0x99 as the first octet). + let signingSubKeyData = [(PGPPublicKeyPacket *)subKey.publicKey.primaryKeyPacket exportKeyPacketOldStyle]; + [toSignData appendData:signingSubKeyData]; + } + break; + case PGPSignatureGenericCertificationUserIDandPublicKey: // 0x10 + case PGPSignaturePersonalCertificationUserIDandPublicKey: // 0x11 + case PGPSignatureCasualCertificationUserIDandPublicKey: // 0x12 + case PGPSignaturePositiveCertificationUserIDandPublicKey: // 0x13 + case PGPSignatureCertificationRevocation: // 0x28 + { + if (!signingKeyPacket) { + PGPLogError(@"Invalid paramaters"); + if (error) { *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Missing key packet." }]; } + return nil; + } + // A certification signature (type 0x10 through 0x13) + + // When a signature is made over a key, the hash data starts with the + // octet 0x99, followed by a two-octet length of the key, and then body + // of the key packet. (Note that this is an old-style packet header for + // a key packet with two-octet length.) + + let signingKeyData = [signingKeyPacket exportKeyPacketOldStyle]; + [toSignData appendData:signingKeyData]; + + if (key.secretKey) { + let secretPartialKey = key.secretKey; + NSAssert(secretPartialKey.users.count > 0, @"Need at least one user for the key."); + + BOOL userIsValid = NO; + for (PGPUser *user in secretPartialKey.users) { + if ([user.userID isEqualToString:userID]) { + userIsValid = YES; + } + } + + if (!userIsValid) { + if (error) { *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: @"Invalid ." }]; } + PGPLogError(@"Invalid user"); + return nil; + } + } + + if (userID.length > 0) { + let userIDData = [userID dataUsingEncoding:NSUTF8StringEncoding]; + if (self.version == 4) { + // constant tag (1) + UInt8 userIDConstant = 0xB4; + [toSignData appendBytes:&userIDConstant length:1]; + + // length (4) + UInt32 userIDLength = (UInt32)userIDData.length; + userIDLength = CFSwapInt32HostToBig(userIDLength); + [toSignData appendBytes:&userIDLength length:4]; + } + // data + [toSignData appendData:userIDData]; + } + // TODO user attributes alternative + // UInt8 userAttributeConstant = 0xD1; + //[data appendBytes:&userAttributeConstant length:sizeof(userAttributeConstant)]; + + } break; + default: + [toSignData pgp_appendData:inputData]; + break; + } + return toSignData; +} + +- (nullable NSData *)calculateTrailerFor:(NSData *)signedPartData { + NSAssert(self.version == 0x4, @"Not supported signature version"); + if (self.version != 0x4) { + return nil; + } + + let trailerData = [NSMutableData data]; + UInt8 prefix[2] = {self.version, 0xFF}; + [trailerData appendBytes:&prefix length:2]; + + UInt32 signatureLength = (UInt32)signedPartData.length; // + 6; // ??? (note that this number does not include these final six octets) + signatureLength = CFSwapInt32HostToBig(signatureLength); + [trailerData appendBytes:&signatureLength length:4]; + + return trailerData; +} + +#pragma mark - Parse + +/** + * 5.2. Signature Packet (Tag 2) + * + * @param packetBody Packet body + */ + +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + __unused NSUInteger position = [super parsePacketBody:packetBody error:error]; + NSUInteger startPosition = position; + + UInt8 parsedVersion = 0; + // One-octet version number. + [packetBody getBytes:&parsedVersion range:(NSRange){position, 1}]; + position = position + 1; + + switch (parsedVersion) { + case 0x04: + position = [self parseV4PacketBody:packetBody error:error]; + break; + case 0x03: + position = [self parseV3PacketBody:packetBody error:error]; + break; + default: + NSAssert(true, @"Unsupported signature packet version"); + if (error) { + *error = [NSError errorWithDomain:PGPErrorDomain code:PGPErrorGeneral userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Signature version %@ is supported at the moment", @(parsedVersion)] }]; + } + return startPosition + packetBody.length; + break; + } + return position; +} + +// FIXME: V3 signatures fail somewehere (I don't know where yet) because everything is designed +// for V4 and uses V4 specific data to (for example) validate signature +- (NSUInteger)parseV3PacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + NSUInteger position = [super parsePacketBody:packetBody error:error]; + + // V3 + // One-octet version number (3). + UInt8 parsedVersion = 0; + [packetBody getBytes:&parsedVersion range:(NSRange){position, 1}]; + position = position + 1; + + // One-octet length of following hashed material. MUST be 5. + UInt8 parsedLength = 0; + [packetBody getBytes:&parsedLength range:(NSRange){position, 1}]; + position = position + 1; + NSAssert(parsedLength == 5, @"Invalid signature data"); + + // One-octet signature type. + [packetBody getBytes:&_type range:(NSRange){position, 1}]; + position = position + 1; + + // Four-octet creation time + UInt32 parsedCreationTimestamp = 0; + [packetBody getBytes:&parsedCreationTimestamp range:(NSRange){position, 4}]; + parsedCreationTimestamp = CFSwapInt32BigToHost(parsedCreationTimestamp); + position = position + 4; + + // Eight-octet Key ID of signer + PGPKeyID *parsedkeyID = [[PGPKeyID alloc] initWithLongKey:[packetBody subdataWithRange:(NSRange){position, 8}]]; + position = position + 8; + + // One-octet public-key algorithm. + [packetBody getBytes:&_publicKeyAlgorithm range:(NSRange){position, 1}]; + position = position + 1; + + // One-octet hash algorithm. + [packetBody getBytes:&_hashAlgoritm range:(NSRange){position, 1}]; + position = position + 1; + + // Two-octet field holding the left 16 bits of the signed hash value. + self.signedHashValueData = [packetBody subdataWithRange:(NSRange){position, 2}]; + position = position + 2; + + // 5.2.2. One or more multiprecision integers comprising the signature. This portion is algorithm specific + // Signature + switch (_publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + // multiprecision integer (MPI) of RSA signature value m**d mod n. + // MPI of RSA public modulus n; + PGPMPI *mpiN = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_N atPosition:position]; + position = position + mpiN.packetLength; + + self.signatureMPIArray = @[mpiN]; + } break; + case PGPPublicKeyAlgorithmDSA: + case PGPPublicKeyAlgorithmECDSA: { + // MPI of DSA value r. + PGPMPI *mpiR = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_R atPosition:position]; + position = position + mpiR.packetLength; + + // MPI of DSA value s. + PGPMPI *mpiS = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_S atPosition:position]; + position = position + mpiS.packetLength; + + self.signatureMPIArray = @[mpiR, mpiS]; + } break; + case PGPPublicKeyAlgorithmElgamal: { + // MPI of Elgamal (Diffie-Hellman) value g**k mod p. + PGPMPI *mpiG = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_G atPosition:position]; + position = position + mpiG.packetLength; + + // MPI of Elgamal (Diffie-Hellman) value m * y**k mod p. + PGPMPI *mpiY = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_Y atPosition:position]; + position = position + mpiY.packetLength; + + self.signatureMPIArray = @[mpiG, mpiY]; + } break; + default: + break; + } + + // convert V3 values to V4 subpackets + PGPSignatureSubpacket *keyIDSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeIssuerKeyID andValue:parsedkeyID]; + self.unhashedSubpackets = [self.unhashedSubpackets arrayByAddingObject:keyIDSubpacket]; + + let creationDateTime = [NSDate dateWithTimeIntervalSince1970:parsedCreationTimestamp]; + PGPSignatureSubpacket *creationTimeSubpacket = [[PGPSignatureSubpacket alloc] initWithType:PGPSignatureSubpacketTypeSignatureCreationTime andValue:creationDateTime]; + self.hashedSubpackets = [self.hashedSubpackets arrayByAddingObject:creationTimeSubpacket]; + + return position; +} + +- (NSUInteger)parseV4PacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + NSUInteger position = [super parsePacketBody:packetBody error:error]; + + // A V4 signature hashes the packet body + // starting from its first field, the version number, through the end + // of the hashed subpacket data. Thus, the fields hashed are the + // signature version, the signature type, the public-key algorithm, the + // hash algorithm, the hashed subpacket length, and the hashed + // subpacket body. + + UInt8 parsedVersion = 0; + // V4 + // One-octet version number (4). + [packetBody getBytes:&parsedVersion range:(NSRange){position, 1}]; + position = position + 1; + + // One-octet signature type. + [packetBody getBytes:&_type range:(NSRange){position, 1}]; + position = position + 1; + + // One-octet public-key algorithm. + [packetBody getBytes:&_publicKeyAlgorithm range:(NSRange){position, 1}]; + position = position + 1; + + // One-octet hash algorithm. + [packetBody getBytes:&_hashAlgoritm range:(NSRange){position, 1}]; + position = position + 1; + + // Two-octet scalar octet count for following hashed subpacket data. + UInt16 hashedOctetCount = 0; + [packetBody getBytes:&hashedOctetCount range:(NSRange){position, 2}]; + hashedOctetCount = CFSwapInt16BigToHost(hashedOctetCount); + position = position + 2; + + // Hashed subpacket data set (zero or more subpackets) + NSData *hashedSubpacketsData = nil; + if (hashedOctetCount > 0) { + hashedSubpacketsData = [packetBody subdataWithRange:(NSRange){position, hashedOctetCount}]; + position = position + hashedOctetCount; + + NSMutableArray *hashedSubpackets = [NSMutableArray arrayWithCapacity:hashedOctetCount]; + + NSUInteger positionSubpacket = 0; + while (positionSubpacket < hashedSubpacketsData.length) { + let subpacket = [self getSubpacketStartingAtPosition:positionSubpacket fromData:hashedSubpacketsData]; + [hashedSubpackets addObject:subpacket]; + positionSubpacket = positionSubpacket + subpacket.length; + } + + self.hashedSubpackets = [hashedSubpackets copy]; + } + + // Two-octet scalar octet count for the following unhashed subpacket + UInt16 unhashedOctetCount = 0; + [packetBody getBytes:&unhashedOctetCount range:(NSRange){position, 2}]; + unhashedOctetCount = CFSwapInt16BigToHost(unhashedOctetCount); + position = position + 2; + + // Unhashed subpacket data set (zero or more subpackets) + NSData *unhashedSubpacketsData = nil; + if (unhashedOctetCount > 0) { + unhashedSubpacketsData = [packetBody subdataWithRange:(NSRange){position, unhashedOctetCount}]; + position = position + unhashedOctetCount; + + NSMutableArray *unhashedSubpackets = [NSMutableArray arrayWithCapacity:unhashedOctetCount]; + + // Loop subpackets + NSUInteger positionSubpacket = 0; + while (positionSubpacket < unhashedSubpacketsData.length) { + let subpacket = [self getSubpacketStartingAtPosition:positionSubpacket fromData:unhashedSubpacketsData]; + [unhashedSubpackets addObject:subpacket]; + positionSubpacket = positionSubpacket + subpacket.length; + } + + self.unhashedSubpackets = [unhashedSubpackets copy]; + } + + // Two-octet field holding the left 16 bits of the signed hash value. + self.signedHashValueData = [packetBody subdataWithRange:(NSRange){position, 2}]; + + position = position + 2; + + // 5.2.2. One or more multiprecision integers comprising the signature. This portion is algorithm specific + // Signature + switch (_publicKeyAlgorithm) { + case PGPPublicKeyAlgorithmRSA: + case PGPPublicKeyAlgorithmRSAEncryptOnly: + case PGPPublicKeyAlgorithmRSASignOnly: { + // multiprecision integer (MPI) of RSA signature value m**d mod n. + // MPI of RSA public modulus n; + PGPMPI *mpiN = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_N atPosition:position]; + position = position + mpiN.packetLength; + + self.signatureMPIArray = @[mpiN]; + } break; + case PGPPublicKeyAlgorithmDSA: + case PGPPublicKeyAlgorithmECDSA: { + // MPI of DSA value r. + PGPMPI *mpiR = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_R atPosition:position]; + position = position + mpiR.packetLength; + + // MPI of DSA value s. + PGPMPI *mpiS = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_S atPosition:position]; + position = position + mpiS.packetLength; + + self.signatureMPIArray = @[mpiR, mpiS]; + } break; + case PGPPublicKeyAlgorithmElgamal: { + // MPI of Elgamal (Diffie-Hellman) value g**k mod p. + PGPMPI *mpiG = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_G atPosition:position]; + position = position + mpiG.packetLength; + + // MPI of Elgamal (Diffie-Hellman) value m * y**k mod p. + PGPMPI *mpiY = [[PGPMPI alloc] initWithMPIData:packetBody identifier:PGPMPI_Y atPosition:position]; + position = position + mpiY.packetLength; + + self.signatureMPIArray = @[mpiG, mpiY]; + } break; + default: + break; + } + + return position; +} + +#pragma mark - Private + +// I don't like this part, really ugly +// This is because subpacket length is unknow and header need to be found first +// then subpacket can be parsed +- (PGPSignatureSubpacket *)getSubpacketStartingAtPosition:(NSUInteger)subpacketsPosition fromData:(NSData *)subpacketsData { + let headerRange = (NSRange){subpacketsPosition, MIN((NSUInteger)6, subpacketsData.length - subpacketsPosition)}; // up to 5+1 octets + let guessHeaderData = [subpacketsData subdataWithRange:headerRange]; // this is "may be" header to be parsed + let subpacketHeader = [PGPSignatureSubpacket subpacketHeaderFromData:guessHeaderData]; + + let subPacketBodyRange = (NSRange){subpacketsPosition + subpacketHeader.headerLength, subpacketHeader.bodyLength}; + let subPacketBody = [subpacketsData subdataWithRange:subPacketBodyRange]; + let subpacket = [[PGPSignatureSubpacket alloc] initWithHeader:subpacketHeader body:subPacketBody]; + + return subpacket; +} + +/// count + subpackets(count) +- (NSData *)buildSubpacketsCollectionData:(NSArray *)subpacketsCollection { + let data = [NSMutableData data]; + if (subpacketsCollection.count == 0) { + // 0x00 0x00 + UInt16 zeroZero = 0; + [data appendBytes:&zeroZero length:2]; + return data; + } + + let subpackets = [NSMutableData data]; + // Hashed subpacket data set (zero or more subpackets) + for (PGPSignatureSubpacket *subpacket in subpacketsCollection) { + NSError *error = nil; + let subpacketData = [subpacket export:&error]; + [subpackets pgp_appendData:subpacketData]; + } + // Two-octet scalar octet count for following hashed subpacket data. + UInt16 countBE = CFSwapInt16HostToBig((UInt16)subpackets.length); + [data appendBytes:&countBE length:2]; + // subackets data + [data appendData:subpackets]; + return data; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket+Private.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket+Private.h new file mode 100644 index 00000000..b84e019e --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket+Private.h @@ -0,0 +1,15 @@ +// +// PGPSignatureSubpacket+Private.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +@interface PGPSignatureSubpacket () + +@property (nonatomic, readwrite) id value; + +@end diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.h new file mode 100644 index 00000000..1c76a18a --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.h @@ -0,0 +1,35 @@ +// +// PGPSignatureSubPacket.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPTypes.h" +#import "PGPMacros.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class PGPSignatureSubpacketHeader; + +@interface PGPSignatureSubpacket : NSObject + +@property (nonatomic, readonly) PGPSignatureSubpacketType type; +@property (nonatomic, readonly) id value; +@property (nonatomic, readonly) NSUInteger length; + +PGP_EMPTY_INIT_UNAVAILABLE; + +- (instancetype)initWithType:(PGPSignatureSubpacketType)type andValue:(id)value NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithHeader:(PGPSignatureSubpacketHeader *)header body:(NSData *)subPacketBodyData; + ++ (PGPSignatureSubpacketHeader *)subpacketHeaderFromData:(NSData *)headerData; + +- (void)parseSubpacketBody:(NSData *)packetBody; +- (nullable NSData *)export:(NSError *__autoreleasing *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPSignatureSubpacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.m similarity index 51% rename from PGPSignatureSubpacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.m index 6d1bb3ff..4482e4e5 100644 --- a/PGPSignatureSubpacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacket.m @@ -7,41 +7,45 @@ // #import "PGPSignatureSubpacket.h" +#import "PGPSignatureSubpacket+Private.h" +#import "PGPSignatureSubpacketCreationTime.h" +#import "PGPSignatureSubpacketHeader.h" +#import "PGPCompressedPacket.h" #import "PGPKeyID.h" #import "PGPPacket.h" -#import "PGPCompressedPacket.h" -#import "NSValue+PGPUtils.h" +#import "PGPPacket+Private.h" +#import "NSMutableData+PGPUtils.h" -@implementation PGPSignatureSubpacketHeader -@end +#import "PGPLogging.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN @interface PGPSignatureSubpacket () -@property (strong, readwrite) id value; + +@property (nonatomic, readwrite) NSUInteger length; @end @implementation PGPSignatureSubpacket -- (instancetype) initWithHeader:(PGPSignatureSubpacketHeader *)header body:(NSData *)subPacketBodyData bodyRange:(NSRange)bodyRange -{ - if (self = [self init]) { - _type = header.type; - _bodyRange = bodyRange; - [self parseSubpacketBody:subPacketBodyData]; +- (instancetype)initWithType:(PGPSignatureSubpacketType)type andValue:(id)value { + if ((self = [super init])) { + _type = type; + _value = value; } return self; } -+ (PGPSignatureSubpacket *) subpacketWithType:(PGPSignatureSubpacketType)type andValue:(id)value -{ - PGPSignatureSubpacket *subpacket = [[PGPSignatureSubpacket alloc] init]; - subpacket.type = type; - subpacket.value = value; - return subpacket; +- (instancetype)initWithHeader:(PGPSignatureSubpacketHeader *)header body:(NSData *)subPacketBodyData { + if (self = [self initWithType:header.type andValue:NSNull.null]) { + _length = header.headerLength + header.bodyLength; + [self parseSubpacketBody:subPacketBodyData]; + } + return self; } -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ %d %@", [super description], self.type, self.value]; +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %@ %@", [super description], @(self.type), self.value]; } /** @@ -49,86 +53,71 @@ * * @param packetBody A single subpacket body data. */ -- (void) parseSubpacketBody:(NSData *)packetBody -{ - // NSLog(@"parseSubpacket %@, body %@",@(self.type), packetBody); - switch (self.type) { +- (void)parseSubpacketBody:(NSData *)packetBodyData { + PGPLogDebug(@"parseSubpacketBody %@, body %@",@(self.type), packetBodyData); + + switch (self.type & 0x7F) { case PGPSignatureSubpacketTypeSignatureCreationTime: // NSDate { - // 5.2.3.4. Signature Creation Time + // 5.2.3.4. Signature Creation Time // Signature Creation Time MUST be present in the hashed area. - - UInt32 signatureCreationTimestamp = 0; - [packetBody getBytes:&signatureCreationTimestamp length:4]; - signatureCreationTimestamp = CFSwapInt32BigToHost(signatureCreationTimestamp); - self.value = [NSDate dateWithTimeIntervalSince1970:signatureCreationTimestamp]; - } - break; + self.value = [PGPSignatureSubpacketCreationTime packetWithData:packetBodyData].value; + } break; case PGPSignatureSubpacketTypeSignatureExpirationTime: // NSNumber - case PGPSignatureSubpacketTypeKeyExpirationTime: - { + case PGPSignatureSubpacketTypeKeyExpirationTime: { // 5.2.3.10. Signature Expiration Time // 5.2.3.6. Key Expiration Time // The validity period of the signature UInt32 validityPeriodTime = 0; - [packetBody getBytes:&validityPeriodTime length:4]; + [packetBodyData getBytes:&validityPeriodTime length:4]; validityPeriodTime = CFSwapInt32BigToHost(validityPeriodTime); self.value = @(validityPeriodTime); - - } - break; - case PGPSignatureSubpacketTypeTrustSignature: - { + } break; + case PGPSignatureSubpacketTypeTrustSignature: { // (1 octet "level" (depth), 1 octet of trust amount) // TODO trust subpacket - } - break; + } break; case PGPSignatureSubpacketTypeIssuerKeyID: // PGPKeyID { // 5.2.3.5. Issuer - PGPKeyID *keyID = [[PGPKeyID alloc] initWithLongKey:packetBody]; + PGPKeyID *keyID = [[PGPKeyID alloc] initWithLongKey:packetBodyData]; self.value = keyID; //[packetBody subdataWithRange:(NSRange){0,8}]; - } - break; - case PGPSignatureSubpacketTypeExportableCertification: // NSNumber BOOL + } break; + case PGPSignatureSubpacketTypeExportableCertification: // NSNumber BOOL { // 5.2.3.11. Exportable Certification UInt8 exportableValue = 0; - [packetBody getBytes:&exportableValue length:1]; + [packetBodyData getBytes:&exportableValue length:1]; self.value = @(exportableValue); - } - break; - case PGPSignatureSubpacketTypePrimaryUserID: // NSNumber BOOL + } break; + case PGPSignatureSubpacketTypePrimaryUserID: // NSNumber BOOL { // 5.2.3.19. Primary User ID UInt8 primaryUserIDValue = 0; - [packetBody getBytes:&primaryUserIDValue length:1]; + [packetBodyData getBytes:&primaryUserIDValue length:1]; self.value = @(primaryUserIDValue); - } - break; - case PGPSignatureSubpacketTypeSignerUserID: // NSString - // side note: This subpacket is not appropriate to use to refer to a User Attribute packet. - case PGPSignatureSubpacketTypePreferredKeyServer: // NSString - case PGPSignatureSubpacketTypePolicyURI: // NSString + } break; + case PGPSignatureSubpacketTypeSignerUserID: // NSString + // side note: This subpacket is not appropriate to use to refer to a User Attribute packet. + case PGPSignatureSubpacketTypePreferredKeyServer: // NSString + case PGPSignatureSubpacketTypePolicyURI: // NSString { - self.value = [[NSString alloc] initWithData:packetBody encoding:NSUTF8StringEncoding]; - } - break; - case PGPSignatureSubpacketTypeReasonForRevocation: // NSNumber + self.value = [[NSString alloc] initWithData:packetBodyData encoding:NSUTF8StringEncoding]; + } break; + case PGPSignatureSubpacketTypeReasonForRevocation: // NSNumber { UInt8 revocationCode = 0; - [packetBody getBytes:&revocationCode length:1]; + [packetBodyData getBytes:&revocationCode length:1]; self.value = @(revocationCode); - } - break; + } break; case PGPSignatureSubpacketTypeKeyFlags: // NSArray of NSNumber { // 5.2.3.21. Key Flags // (N octets of flags) ??? // This implementation supports max 8 octets (64bit) UInt64 flagByte = 0; - [packetBody getBytes:&flagByte length:MIN(8,packetBody.length)]; + [packetBodyData getBytes:&flagByte length:MIN((NSUInteger)8, packetBodyData.length)]; NSMutableArray *flagsArray = [NSMutableArray array]; if (flagByte & PGPSignatureFlagAllowCertifyOtherKeys) { @@ -154,272 +143,250 @@ } self.value = [flagsArray copy]; - } - break; - case PGPSignatureSubpacketTypePreferredSymetricAlgorithm: // NSArray of NSValue @encode(PGPSymmetricAlgorithm) + } break; + case PGPSignatureSubpacketTypePreferredSymetricAlgorithm: // NSArray of NSNumber(PGPSymmetricAlgorithm) { // 5.2.3.7. Preferred Symmetric Algorithms NSMutableArray *algorithmsArray = [NSMutableArray array]; - for (NSUInteger i = 0; i < packetBody.length; i++) { - PGPSymmetricAlgorithm algorithm = 0; - [packetBody getBytes:&algorithm range:(NSRange){i,1}]; - - NSValue *val = [NSValue valueWithBytes:&algorithm objCType:@encode(PGPSymmetricAlgorithm)]; - [algorithmsArray addObject:val]; + for (NSUInteger i = 0; i < packetBodyData.length; i++) { + PGPSymmetricAlgorithm algorithm = PGPSymmetricPlaintext; + [packetBodyData getBytes:&algorithm range:(NSRange){i, 1}]; + [algorithmsArray addObject:@(algorithm)]; } self.value = [algorithmsArray copy]; - } - break; - case PGPSignatureSubpacketTypePreferredHashAlgorithm: // NSArray of NSValue @encode(PGPHashAlgorithm) + } break; + case PGPSignatureSubpacketTypePreferredHashAlgorithm: // NSArray of NSNumber(PGPHashAlgorithm) { // 5.2.3.8. Preferred Hash Algorithms - NSMutableArray *algorithmsArray = [NSMutableArray array]; + let algorithmsArray = [NSMutableArray<NSNumber *> array]; - for (NSUInteger i = 0; i < packetBody.length; i++) { - PGPHashAlgorithm algorithm = 0; - [packetBody getBytes:&algorithm range:(NSRange){i,1}]; - - NSValue *val = [NSValue valueWithBytes:&algorithm objCType:@encode(PGPHashAlgorithm)]; - [algorithmsArray addObject:val]; + for (NSUInteger i = 0; i < packetBodyData.length; i++) { + PGPHashAlgorithm algorithm = PGPHashUnknown; + [packetBodyData getBytes:&algorithm range:(NSRange){i, 1}]; + [algorithmsArray addObject:@(algorithm)]; } - self.value = [algorithmsArray copy]; - } - break; - case PGPSignatureSubpacketTypePreferredCompressionAlgorithm: // NSArray of NSValue @encode(PGPCompressionAlgorithm) + self.value = algorithmsArray; + } break; + case PGPSignatureSubpacketTypePreferredCompressionAlgorithm: // NSArray of NSNumber(PGPCompressionAlgorithm) { // 5.2.3.9. Preferred Compression Algorithms // If this subpacket is not included, ZIP is preferred. NSMutableArray *algorithmsArray = [NSMutableArray array]; - for (UInt8 i = 0; i < packetBody.length; i++) { - PGPCompressionAlgorithm algorithm = 0; - [packetBody getBytes:&algorithm range:(NSRange){i,1}]; - - NSValue *val = [NSValue valueWithBytes:&algorithm objCType:@encode(PGPCompressionAlgorithm)]; - [algorithmsArray addObject:val]; + for (UInt8 i = 0; i < packetBodyData.length; i++) { + PGPCompressionAlgorithm algorithm = PGPCompressionUncompressed; + [packetBodyData getBytes:&algorithm range:(NSRange){i, 1}]; + [algorithmsArray addObject:@(algorithm)]; } self.value = [algorithmsArray copy]; - } - break; - case PGPSignatureSubpacketTypeKeyServerPreference: // NSArray of NSNumber PGPKeyServerPreferenceFlags + } break; + case PGPSignatureSubpacketTypeKeyServerPreference: // NSArray of NSNumber(PGPKeyServerPreferenceFlags) { // 5.2.3.17. Key Server Preferences - PGPKeyServerPreferenceFlags flag = 0; - [packetBody getBytes:&flag length:MIN(8,packetBody.length)]; + PGPKeyServerPreferenceFlags flag = PGPKeyServerPreferenceUnknown; + [packetBodyData getBytes:&flag length:MIN((NSUInteger)8, packetBodyData.length)]; NSMutableArray *flagsArray = [NSMutableArray array]; if (flag & PGPKeyServerPreferenceNoModify) { [flagsArray addObject:@(PGPKeyServerPreferenceNoModify)]; } self.value = [flagsArray copy]; - } - break; - case PGPSignatureSubpacketTypeFeatures: // NSArray of NSNumber PGPFeature + } break; + case PGPSignatureSubpacketTypeFeatures: // NSArray of NSNumber(PGPFeature) { // 5.2.3.24. Features NSMutableArray *featuresArray = [NSMutableArray array]; - for (NSUInteger i = 0; i < packetBody.length; i++) { - PGPFeature feature = 0; - [packetBody getBytes:&feature range:(NSRange){i,1}]; + for (NSUInteger i = 0; i < packetBodyData.length; i++) { + PGPFeature feature = PGPFeatureModificationUnknown; + [packetBodyData getBytes:&feature range:(NSRange){i, 1}]; [featuresArray addObject:@(feature)]; } self.value = [featuresArray copy]; - } - break; + } break; default: -#ifdef DEBUG - // NSLog(@"Unsuported subpacket type %d", self.type); -#endif + if (self.type & 0x80) { + PGPLogError(@"Unsupported critical subpacket type %d", self.type); + } else { + PGPLogDebug(@"Unsupported subpacket type %d", self.type); + } break; } } -- (NSData *) exportSubpacket:(NSError *__autoreleasing *)error -{ +- (nullable NSData *)export:(NSError *__autoreleasing *)error { NSMutableData *data = [NSMutableData data]; // subpacket type PGPSignatureSubpacketType type = self.type; [data appendBytes:&type length:1]; - switch (self.type) { + switch (self.type & 0x7F) { case PGPSignatureSubpacketTypeSignatureCreationTime: // NSDate { - NSDate *date = (NSDate *)self.value; - UInt32 signatureCreationTimestamp = CFSwapInt32HostToBig((UInt32)[date timeIntervalSince1970]); + let date = PGPCast(self.value, NSDate); + let signatureCreationTimestamp = CFSwapInt32HostToBig((UInt32)[date timeIntervalSince1970]); [data appendBytes:&signatureCreationTimestamp length:4]; - } - break; + } break; case PGPSignatureSubpacketTypeSignatureExpirationTime: // NSNumber - case PGPSignatureSubpacketTypeKeyExpirationTime: - { - NSNumber *validityPeriod = (NSNumber *)self.value; - UInt32 validityPeriodInt = CFSwapInt32HostToBig((UInt32)validityPeriod.unsignedIntegerValue); + case PGPSignatureSubpacketTypeKeyExpirationTime: { + let validityPeriod = PGPCast(self.value, NSNumber); + let validityPeriodInt = CFSwapInt32HostToBig((UInt32)validityPeriod.unsignedIntegerValue); [data appendBytes:&validityPeriodInt length:4]; - } - break; + } break; case PGPSignatureSubpacketTypeIssuerKeyID: // PGPKeyID { - PGPKeyID *keyID = self.value; - [data appendData:[keyID exportKeyData]]; - } - break; - case PGPSignatureSubpacketTypeExportableCertification: // NSNumber BOOL - case PGPSignatureSubpacketTypePrimaryUserID: // NSNumber BOOL + let _Nullable keyID = PGPCast(self.value, PGPKeyID); + [data pgp_appendData:[keyID export:nil]]; + } break; + case PGPSignatureSubpacketTypeExportableCertification: // NSNumber BOOL + case PGPSignatureSubpacketTypePrimaryUserID: // NSNumber BOOL { - NSNumber *boolNumber = self.value; - BOOL boolValue = [boolNumber boolValue]; + var boolValue = PGPCast(self.value, NSNumber).boolValue; [data appendBytes:&boolValue length:1]; - } - break; - case PGPSignatureSubpacketTypeSignerUserID: // NSString - case PGPSignatureSubpacketTypePreferredKeyServer: // NSString - case PGPSignatureSubpacketTypePolicyURI: // NSString - { - NSString *stringValue = self.value; - [data appendData:[stringValue dataUsingEncoding:NSUTF8StringEncoding]]; - } - break; - case PGPSignatureSubpacketTypeReasonForRevocation: + } break; + case PGPSignatureSubpacketTypeSignerUserID: // NSString + case PGPSignatureSubpacketTypePreferredKeyServer: // NSString + case PGPSignatureSubpacketTypePolicyURI: // NSString { + let stringValue = PGPCast(self.value, NSString); + let _Nullable stringData = [stringValue dataUsingEncoding:NSUTF8StringEncoding]; + [data pgp_appendData:stringData]; + } break; + case PGPSignatureSubpacketTypeReasonForRevocation: { // 5.2.3.23. Reason for Revocation - NSNumber *revocationCode = self.value; - UInt8 revocationCodeByte = [revocationCode unsignedIntValue]; + let revocationCode = PGPCast(self.value, NSNumber); + UInt8 revocationCodeByte = [revocationCode unsignedCharValue]; [data appendBytes:&revocationCodeByte length:1]; - } - break; + } break; case PGPSignatureSubpacketTypeKeyFlags: // NSArray of NSNumber PGPSignatureFlags { - //TODO: actually it can be more than one byte (documented) + // TODO: actually it can be more than one byte (documented) // so I should calculate how many bytes do I need here - NSArray *flagsArray = self.value; - PGPSignatureFlags flagByte = 0; + let flagsArray = PGPCast(self.value, NSArray); + if (!flagsArray) { + break; + } + PGPSignatureFlags flagByte = PGPSignatureFlagUnknown; for (NSNumber *flagByteNumber in flagsArray) { flagByte = flagByte | ((UInt8)[flagByteNumber unsignedIntValue]); } [data appendBytes:&flagByte length:sizeof(PGPSignatureFlags)]; - } - break; - case PGPSignatureSubpacketTypePreferredSymetricAlgorithm: // NSArray of NSValue @encode(PGPSymmetricAlgorithm) + } break; + case PGPSignatureSubpacketTypePreferredSymetricAlgorithm: // NSArray of NSNumber(PGPSymmetricAlgorithm) { - NSArray *algorithmsArray = self.value; - for (NSValue *val in algorithmsArray) { - if (![val pgp_objCTypeIsEqualTo:@encode(PGPSymmetricAlgorithm)]) { - continue; - } - - PGPSymmetricAlgorithm symmetricAlgorithm = 0; - [val getValue:&symmetricAlgorithm]; - + let algorithmsArray = PGPCast(self.value, NSArray); + if (!algorithmsArray) { + break; + } + for (NSNumber *val in algorithmsArray) { + PGPSymmetricAlgorithm symmetricAlgorithm = (UInt8)val.unsignedIntValue; [data appendBytes:&symmetricAlgorithm length:sizeof(PGPSymmetricAlgorithm)]; } - } - break; - case PGPSignatureSubpacketTypePreferredHashAlgorithm: // NSArray of of NSValue @encode(PGPHashAlgorithm) + } break; + case PGPSignatureSubpacketTypePreferredHashAlgorithm: // NSArray of NSNumber(PGPHashAlgorithm) { - NSArray *algorithmsArray = self.value; - for (NSValue *val in algorithmsArray) { - if (![val pgp_objCTypeIsEqualTo:@encode(PGPHashAlgorithm)]) { - continue; - } - - PGPHashAlgorithm hashAlgorithm = 0; - [val getValue:&hashAlgorithm]; + let algorithmsArray = PGPCast(self.value, NSArray); + if (!algorithmsArray) { + break; + } + + for (NSNumber *val in algorithmsArray) { + PGPHashAlgorithm hashAlgorithm = (UInt8)val.unsignedIntValue; [data appendBytes:&hashAlgorithm length:sizeof(PGPHashAlgorithm)]; } - } - break; - case PGPSignatureSubpacketTypePreferredCompressionAlgorithm: // NSArray of NSValue @encode(PGPCompressionAlgorithm) + } break; + case PGPSignatureSubpacketTypePreferredCompressionAlgorithm: // NSArray of NSNumber(PGPCompressionAlgorithm) { - NSArray *algorithmsArray = self.value; - for (NSValue *val in algorithmsArray) { - if (![val pgp_objCTypeIsEqualTo:@encode(PGPCompressionAlgorithm)]) { - continue; - } - - PGPCompressionAlgorithm hashAlgorithm = 0; - [val getValue:&hashAlgorithm]; + let algorithmsArray = PGPCast(self.value, NSArray); + if (!algorithmsArray) { + break; + } + for (NSNumber *val in algorithmsArray) { + PGPCompressionAlgorithm hashAlgorithm = (UInt8)val.unsignedIntValue; [data appendBytes:&hashAlgorithm length:sizeof(PGPCompressionAlgorithm)]; } - } - break; + } break; case PGPSignatureSubpacketTypeKeyServerPreference: // NSArray of NSNumber PGPKeyServerPreferenceFlags { - //TODO: actually it can be more than one byte (documented) + // TODO: actually it can be more than one byte (documented) // so I should calculate how many bytes do I need here - PGPKeyServerPreferenceFlags allFlags = 0; - NSArray *flagsArray = (NSArray *)self.value; + PGPKeyServerPreferenceFlags allFlags = PGPKeyServerPreferenceUnknown; + let flagsArray = PGPCast(self.value, NSArray); + if (!flagsArray) { + break; + } for (NSNumber *flagNumber in flagsArray) { PGPKeyServerPreferenceFlags flag = (PGPKeyServerPreferenceFlags)flagNumber.unsignedIntValue; allFlags = allFlags | flag; } [data appendBytes:&allFlags length:sizeof(PGPKeyServerPreferenceFlags)]; - } - break; + } break; case PGPSignatureSubpacketTypeFeatures: // NSArray of NSNumber PGPFeature { - //TODO: actually it can be more than one byte (documented) + // TODO: actually it can be more than one byte (documented) // so I should calculate how many bytes do I need here - NSArray *flagsArray = self.value; - PGPFeature flagByte = 0; + let flagsArray = PGPCast(self.value, NSArray); + if (!flagsArray) { + break; + } + PGPFeature flagByte = PGPFeatureModificationUnknown; for (NSNumber *flagByteNumber in flagsArray) { flagByte = flagByte | ((UInt8)[flagByteNumber unsignedIntValue]); } [data appendBytes:&flagByte length:sizeof(PGPSignatureFlags)]; - } - break; + } break; default: -#ifdef DEBUG - // NSLog(@"Unsuported subpacket type %d", self.type); -#endif + if (self.type & 0x80) { + PGPLogError(@"Unsupported critical subpacket type %d", self.type); + } else { + PGPLogDebug(@"Unsupported subpacket type %d", self.type); + } break; } - //subpacket = length + tag + body + // subpacket = length + tag(type) + body NSMutableData *subpacketData = [NSMutableData data]; // the subpacket length (1, 2, or 5 octets), NSData *subpacketLengthData = [PGPPacket buildNewFormatLengthDataForData:data]; [subpacketData appendData:subpacketLengthData]; // data with tag [subpacketData appendData:data]; - // NSLog(@"exportSubpacket %@, header %@",@(self.type), [subpacketData subdataWithRange:(NSRange){0, subpacketLengthData.length + 1}]); - // NSLog(@"exportSubpacket %@, body %@",@(self.type), [data subdataWithRange:(NSRange){1,data.length - 1}]); - return [subpacketData copy]; } -+ (PGPSignatureSubpacketHeader *) subpacketHeaderFromData:(NSData *)headerData -{ ++ (PGPSignatureSubpacketHeader *)subpacketHeaderFromData:(NSData *)headerData { NSUInteger position = 0; - UInt8 *lengthOctets = (UInt8 *)[headerData subdataWithRange:NSMakeRange(position, MIN(5,headerData.length))].bytes; + const UInt8 *lengthOctets = [headerData subdataWithRange:NSMakeRange(position, MIN((NSUInteger)5, headerData.length))].bytes; UInt32 headerLength = 0; UInt32 subpacketLength = 0; + //TODO: Use -[PGPPacket parseNewFormatHeaderPacket:]. headerLength is different size !? + // Its format is similar to the "new" format packet header lengths, but cannot have Partial Body Lengths. if (lengthOctets[0] < 192) { // subpacketLen = 1st_octet; subpacketLength = lengthOctets[0]; - headerLength = 1 ; + headerLength = 1; } else if (lengthOctets[0] >= 192 && lengthOctets[0] < 255) { // subpacketLen = ((1st_octet - 192) << 8) + (2nd_octet) + 192 - subpacketLength = ((lengthOctets[0] - 192) << 8) + (lengthOctets[1]) + 192; + subpacketLength = ((lengthOctets[0] - 192) << 8) + (lengthOctets[1]) + 192; headerLength = 2; } else if (lengthOctets[0] == 255) { // subpacketLen = (2nd_octet << 24) | (3rd_octet << 16) | // (4th_octet << 8) | 5th_octet - subpacketLength = (lengthOctets[1] << 24) | (lengthOctets[2] << 16) | (lengthOctets[3] << 8) | lengthOctets[4]; + subpacketLength = (lengthOctets[1] << 24) | (lengthOctets[2] << 16) | (lengthOctets[3] << 8) | lengthOctets[4]; headerLength = 5; } position = position + headerLength; - //TODO: Bit 7 of the subpacket type is the "critical" bit. - PGPSignatureSubpacketType subpacketType = 0; + // TODO: Bit 7 of the subpacket type is the "critical" bit. + PGPSignatureSubpacketType subpacketType = PGPSignatureSubpacketTypeUnknown; [headerData getBytes:&subpacketType range:(NSRange){position, 1}]; headerLength = headerLength + 1; @@ -441,5 +408,6 @@ return subpacketHeader; } - @end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.h new file mode 100644 index 00000000..c240dde6 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.h @@ -0,0 +1,31 @@ +// +// PGPSignatureSubpacketCreationTime.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// +// 5.2.3.4. Signature Creation Time +// Signature Creation Time MUST be present in the hashed area. + +#import "PGPTypes.h" +#import "PGPMacros.h" +#import "PGPExportableProtocol.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPSignatureSubpacketCreationTime : NSObject <PGPExportable> + +@property (nonatomic, copy, readonly) NSDate *value; +@property (class, nonatomic, readonly) PGPSignatureSubpacketType type; + +PGP_EMPTY_INIT_UNAVAILABLE + +- (instancetype)initWithDate:(NSDate *)date NS_DESIGNATED_INITIALIZER; + ++ (instancetype)packetWithData:(NSData *)packetBodyData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.m new file mode 100644 index 00000000..8602e260 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketCreationTime.m @@ -0,0 +1,59 @@ +// +// PGPSignatureSubpacketCreationTime.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPSignatureSubpacketCreationTime.h" +#import "NSData+PGPUtils.h" +#import "PGPPacket.h" +#import "PGPPacket+Private.h" +#import "PGPMacros+Private.h" + +NS_ASSUME_NONNULL_BEGIN + +static const NSUInteger PGPSignatureSubpacketLength = 4; + +@implementation PGPSignatureSubpacketCreationTime + +- (instancetype)initWithDate:(NSDate *)date { + if ((self = [super init])) { + _value = [date copy]; + } + return self; +} + ++ (PGPSignatureSubpacketType)type { + return PGPSignatureSubpacketTypeSignatureCreationTime; +} + ++ (instancetype)packetWithData:(NSData *)packetBodyData { + UInt32 signatureCreationTimestamp = 0; + [packetBodyData getBytes:&signatureCreationTimestamp length:PGPSignatureSubpacketLength]; + signatureCreationTimestamp = CFSwapInt32BigToHost(signatureCreationTimestamp); + let date = [NSDate dateWithTimeIntervalSince1970:signatureCreationTimestamp]; + return [[PGPSignatureSubpacketCreationTime alloc] initWithDate:date]; +} + +#pragma mark - PGPExportable + +- (nullable NSData *)export:(NSError *__autoreleasing _Nullable *)error { + let timestamp = CFSwapInt32HostToBig((UInt32)[self.value timeIntervalSince1970]); + let valueData = [NSData dataWithBytes:×tamp length:PGPSignatureSubpacketLength]; + + let type = self.class.type; + let typedData = [NSMutableData dataWithBytes:&type length:1]; + [typedData appendData:valueData]; + + + let output = [NSMutableData data]; + [output appendData:[PGPPacket buildNewFormatLengthDataForData:typedData]]; + [output appendData:typedData]; + return output; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.h new file mode 100644 index 00000000..8bbc3aab --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.h @@ -0,0 +1,22 @@ +// +// PGPSignatureSubpacketHeader.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPSignatureSubpacketHeader : NSObject + +@property (nonatomic) PGPSignatureSubpacketType type; +@property (nonatomic) NSUInteger headerLength; +@property (nonatomic) NSUInteger bodyLength; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.m new file mode 100644 index 00000000..7320d7f8 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSignatureSubpacketHeader.m @@ -0,0 +1,13 @@ +// +// PGPSignatureSubpacketHeader.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/07/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPSignatureSubpacketHeader.h" + +@implementation PGPSignatureSubpacketHeader + +@end diff --git a/PGPSymmetricallyEncryptedDataPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.h similarity index 85% rename from PGPSymmetricallyEncryptedDataPacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.h index f5e08c8d..05faa6d2 100644 --- a/PGPSymmetricallyEncryptedDataPacket.h +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.h @@ -9,6 +9,6 @@ #import "PGPPacket.h" @interface PGPSymmetricallyEncryptedDataPacket : PGPPacket -@property (strong) NSData *encryptedData; +@property (nonatomic) NSData *encryptedData; @end diff --git a/PGPSymmetricallyEncryptedDataPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.m similarity index 72% rename from PGPSymmetricallyEncryptedDataPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.m index c8edc380..2c8548aa 100644 --- a/PGPSymmetricallyEncryptedDataPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedDataPacket.m @@ -8,38 +8,35 @@ // Parse only #import "PGPSymmetricallyEncryptedDataPacket.h" -#import "PGPPublicKeyPacket.h" -#import "PGPCryptoUtils.h" #import "PGPCryptoCFB.h" +#import "PGPCryptoUtils.h" +#import "PGPPublicKeyPacket.h" #import <CommonCrypto/CommonCrypto.h> -#import <CommonCrypto/CommonDigest.h> #import <CommonCrypto/CommonCryptor.h> +#import <CommonCrypto/CommonDigest.h> -#include <openssl/cast.h> -#include <openssl/idea.h> -#include <openssl/aes.h> -#include <openssl/sha.h> -#include <openssl/des.h> -#include <openssl/camellia.h> -#include <openssl/blowfish.h> +#import <openssl/aes.h> +#import <openssl/blowfish.h> +#import <openssl/camellia.h> +#import <openssl/cast.h> +#import <openssl/des.h> +#import <openssl/idea.h> +#import <openssl/sha.h> @implementation PGPSymmetricallyEncryptedDataPacket -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = [super parsePacketBody:packetBody error:error]; self.encryptedData = [packetBody copy]; - + return position; } -- (NSData *)exportPacket:(NSError *__autoreleasing *)error -{ +- (NSData *)export:(NSError *__autoreleasing *)error { NSAssert(self.encryptedData, @"Need encrypted data, use PGPSymmetricallyEncryptedIntegrityProtectedDataPacket instead"); - if (!self.encryptedData) - return nil; + if (!self.encryptedData) return nil; return self.encryptedData; } diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h new file mode 100644 index 00000000..06a3687e --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h @@ -0,0 +1,25 @@ +// +// PGPSymmetricallyEncryptedDataPacket.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/06/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPPacket.h" +#import "PGPSymmetricallyEncryptedDataPacket.h" + +NS_ASSUME_NONNULL_BEGIN + +@class PGPSecretKeyPacket, PGPPublicKeyPacket; + +@interface PGPSymmetricallyEncryptedIntegrityProtectedDataPacket : PGPSymmetricallyEncryptedDataPacket + +@property (nonatomic) NSUInteger version; + +- (BOOL)encrypt:(NSData *)literalPacketData symmetricAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData error:(NSError *__autoreleasing *)error; +- (NSArray<PGPPacket *> *)decryptWithSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData isIntegrityProtected:(BOOL *)isIntegrityProtected error:(NSError *__autoreleasing _Nullable *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m similarity index 54% rename from PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m index 98d91ccf..f25fe04d 100644 --- a/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.m @@ -7,47 +7,47 @@ // #import "PGPSymmetricallyEncryptedIntegrityProtectedDataPacket.h" -#import "PGPSecretKeyPacket.h" -#import "PGPKey.h" -#import "PGPPublicKeyRSA.h" +#import "NSData+PGPUtils.h" +#import "PGPCompressedPacket.h" #import "PGPCryptoCFB.h" #import "PGPCryptoUtils.h" -#import "NSData+PGPUtils.h" -#import "PGPModificationDetectionCodePacket.h" #import "PGPLiteralPacket.h" -#import "PGPCompressedPacket.h" -#import "PGPOnePassSignaturePacket.h" #import "PGPModificationDetectionCodePacket.h" +#import "PGPOnePassSignaturePacket.h" +#import "PGPPartialKey.h" +#import "PGPRSA.h" +#import "PGPSecretKeyPacket.h" +#import "PGPMacros+Private.h" +#import "PGPFoundation.h" #import <CommonCrypto/CommonCrypto.h> -#import <CommonCrypto/CommonDigest.h> #import <CommonCrypto/CommonCryptor.h> +#import <CommonCrypto/CommonDigest.h> + +#import <openssl/aes.h> +#import <openssl/blowfish.h> +#import <openssl/camellia.h> +#import <openssl/cast.h> +#import <openssl/des.h> +#import <openssl/idea.h> +#import <openssl/sha.h> -#include <openssl/cast.h> -#include <openssl/idea.h> -#include <openssl/aes.h> -#include <openssl/sha.h> -#include <openssl/des.h> -#include <openssl/camellia.h> -#include <openssl/blowfish.h> +NS_ASSUME_NONNULL_BEGIN @implementation PGPSymmetricallyEncryptedIntegrityProtectedDataPacket -- (instancetype)init -{ +- (instancetype)init { if (self = [super init]) { _version = 1; } return self; } -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPSymmetricallyEncryptedIntegrityProtectedDataPacketTag; // 18 } -- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = 0; // The content of an encrypted data packet is more OpenPGP packets @@ -62,168 +62,172 @@ return position; } -- (NSData *)exportPacket:(NSError *__autoreleasing *)error -{ +- (nullable NSData *)export:(NSError *__autoreleasing _Nullable *)error { NSAssert(self.encryptedData, @"No encrypted data?"); NSAssert(self.version == 1, @"Require version == 1"); - - if (!self.encryptedData) - { + + if (!self.encryptedData) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"No encrypted data? try encrypt first"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"No encrypted data? try encrypt first" }]; } return nil; } - - NSMutableData *bodyData = [NSMutableData data]; + + let bodyData = [NSMutableData data]; // A one-octet version number. [bodyData appendBytes:&_version length:1]; // Encrypted data [bodyData appendData:self.encryptedData]; - - NSMutableData *data = [NSMutableData data]; - NSData *headerData = [self buildHeaderData:bodyData]; - [data appendData: headerData]; - [data appendData: bodyData]; - return [data copy]; + + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return bodyData; + }]; } -- (NSArray *) readPacketsFromData:(NSData *)keyringData offset:(NSUInteger)offset mdcLength:(NSUInteger*)mdcLength -{ - NSMutableArray *accumulatedPackets = [NSMutableArray array]; - NSUInteger nextPacketOffset; - if (mdcLength) *mdcLength = 0; +- (NSArray<PGPPacket *> *)readPacketsFromData:(NSData *)keyringData offset:(NSUInteger)offset mdcLength:(nullable NSUInteger *)mdcLength { + let accumulatedPackets = [NSMutableArray<PGPPacket *> array]; + NSUInteger nextPacketOffset = 0; + if (mdcLength) { *mdcLength = 0; } while (offset < keyringData.length) { - - PGPPacket *packet = [PGPPacketFactory packetWithData:keyringData offset:offset nextPacketOffset:&nextPacketOffset]; + let _Nullable packet = [PGPPacketFactory packetWithData:keyringData offset:offset nextPacketOffset:&nextPacketOffset]; if (packet) { [accumulatedPackets addObject:packet]; - if (packet.tag != PGPModificationDetectionCodePacketTag) - { - if (mdcLength) *mdcLength += nextPacketOffset; + if (packet.tag != PGPModificationDetectionCodePacketTag) { + if (mdcLength) { + *mdcLength += nextPacketOffset; + } } } + // A compressed Packet contains more packets - if ([packet isKindOfClass:[PGPCompressedPacket class]]) - { - [accumulatedPackets addObjectsFromArray:[self readPacketsFromData:((PGPCompressedPacket*)packet).decompressedData offset:0 mdcLength:NULL]]; + let _Nullable compressedPacket = PGPCast(packet, PGPCompressedPacket); + if (compressedPacket) { + let packets = [self readPacketsFromData:compressedPacket.decompressedData offset:0 mdcLength:nil]; + if (packets) { + [accumulatedPackets addObjectsFromArray:packets]; + } } - offset += nextPacketOffset; - if (packet.indeterminateLength && [accumulatedPackets[0] isKindOfClass:[PGPCompressedPacket class]]) - { - // substract size of PGPModificationDetectionCodePacket in this very special case - TODO: fix this + + if (packet.indeterminateLength && accumulatedPackets.count > 0 && PGPCast(accumulatedPackets.firstObject, PGPCompressedPacket)) { + //FIXME: substract size of PGPModificationDetectionCodePacket in this very special case - TODO: fix this offset -= 22; - if (mdcLength) *mdcLength -= 22; + if (mdcLength) { + *mdcLength -= 22; + } } + + // corrupted data. Move by one byte in hope we find some packet there, or EOF. + if (nextPacketOffset == 0) { + offset++; + } + offset += nextPacketOffset; } - return [accumulatedPackets copy]; + return accumulatedPackets; } // return array of packets -- (NSArray *) decryptWithSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData isIntegrityProtected:(BOOL *)isIntegrityProtected error:(NSError * __autoreleasing *)error -{ +- (NSArray<PGPPacket *> *)decryptWithSecretKeyPacket:(PGPSecretKeyPacket *)secretKeyPacket sessionKeyAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData isIntegrityProtected:(BOOL *)isIntegrityProtected error:(NSError *__autoreleasing _Nullable *)error { NSAssert(self.encryptedData, @"Missing encrypted data to decrypt"); NSAssert(secretKeyPacket, @"Missing secret key"); - NSAssert(!secretKeyPacket.isEncryptedWithPassword, @"Decrypt secret key first"); - + // initialize if Packet isIntegrityProtected - if (isIntegrityProtected) *isIntegrityProtected = NO; - + if (isIntegrityProtected) { + *isIntegrityProtected = NO; + } + if (!self.encryptedData) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Missing encrypted data"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Missing encrypted data" }]; } - return nil; + return @[]; } - - if (secretKeyPacket.isEncryptedWithPassword) { + + if (secretKeyPacket.isEncryptedWithPassphrase) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Encrypted secret key used to decryption. Decrypt key first"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Encrypted secret key used to decryption. Decrypt key first" }]; } - return nil; + return @[]; } NSUInteger blockSize = [PGPCryptoUtils blockSizeOfSymmetricAlhorithm:sessionKeyAlgorithm]; // The Initial Vector (IV) is specified as all zeros. - NSMutableData *ivData = [NSMutableData dataWithLength:blockSize]; + let ivData = [NSMutableData dataWithLength:blockSize]; NSUInteger position = 0; // preamble + data + mdc - NSData *decryptedData = [PGPCryptoCFB decryptData:self.encryptedData sessionKeyData:sessionKeyData symmetricAlgorithm:sessionKeyAlgorithm iv:ivData]; + let decryptedData = [PGPCryptoCFB decryptData:self.encryptedData sessionKeyData:sessionKeyData symmetricAlgorithm:sessionKeyAlgorithm iv:ivData]; // full prefix blockSize + 2 - NSData *prefixRandomFullData = [decryptedData subdataWithRange:(NSRange){position, blockSize + 2}]; + let prefixRandomFullData = [decryptedData subdataWithRange:(NSRange){position, blockSize + 2}]; position = position + blockSize + 2; - + // check if suffix match - // Here null. WHY???? - if (![[prefixRandomFullData subdataWithRange:(NSRange){blockSize + 2 - 4, 2}] isEqualToData:[prefixRandomFullData subdataWithRange:(NSRange){blockSize + 2 - 2, 2}]]) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Random suffix mismatch"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Random suffix mismatch" }]; } - return nil; + return @[]; } - - - NSUInteger mdcLength; - NSArray *packets = [self readPacketsFromData:decryptedData offset:position mdcLength:&mdcLength]; - - PGPPacket* lastPacket = (PGPPacket*)[packets lastObject]; - if (!lastPacket || lastPacket.tag != PGPModificationDetectionCodePacketTag) - { + + NSUInteger mdcLength = 0; + let packets = [self readPacketsFromData:decryptedData offset:position mdcLength:&mdcLength]; + + let _Nullable lastPacket = PGPCast(packets.lastObject, PGPPacket); + if (!lastPacket || lastPacket.tag != PGPModificationDetectionCodePacketTag) { // Not Integrity Protected, isIntegrityProtected will be reported to NO (see initialization) return packets; } // indicate accordingly if packet was found (might still be invalid) - if (isIntegrityProtected) *isIntegrityProtected = YES; - - PGPModificationDetectionCodePacket *mdcPacket = (PGPModificationDetectionCodePacket *)lastPacket; - - NSMutableData *toMDCData = [[NSMutableData alloc] init]; + if (isIntegrityProtected) { + *isIntegrityProtected = YES; + } + + let _Nullable mdcPacket = PGPCast(lastPacket, PGPModificationDetectionCodePacket); + + let toMDCData = [[NSMutableData alloc] init]; // preamble [toMDCData appendData:prefixRandomFullData]; // validation: calculate MDC hash to check if literal data is modified [toMDCData appendData:[decryptedData subdataWithRange:(NSRange){position, mdcLength}]]; - + // and then also includes two octets of values 0xD3, 0x14 (sha length) UInt8 mdc_suffix[2] = {0xD3, 0x14}; [toMDCData appendBytes:&mdc_suffix length:2]; - - NSData *mdcHash = [toMDCData pgp_SHA1]; - if (![mdcHash isEqualToData:mdcPacket.hashData]) { + + let mdcHash = [toMDCData pgp_SHA1]; + if (!mdcPacket || ![mdcHash isEqualToData:mdcPacket.hashData]) { if (error) { - *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"MDC validation failed"}]; + *error = [NSError errorWithDomain:PGPErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: @"MDC validation failed" }]; } - return nil; + return @[]; } - + return [packets subarrayWithRange:(NSRange){0, packets.count - 1}]; } -- (BOOL) encrypt:(NSData *)literalPacketData symmetricAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData error:(NSError * __autoreleasing *)error -{ +- (BOOL)encrypt:(NSData *)literalPacketData symmetricAlgorithm:(PGPSymmetricAlgorithm)sessionKeyAlgorithm sessionKeyData:(NSData *)sessionKeyData error:(NSError *__autoreleasing _Nullable *)error { // OpenPGP does symmetric encryption using a variant of Cipher Feedback mode (CFB mode). NSUInteger blockSize = [PGPCryptoUtils blockSizeOfSymmetricAlhorithm:sessionKeyAlgorithm]; // The Initial Vector (IV) is specified as all zeros. - NSMutableData *ivData = [NSMutableData dataWithLength:blockSize]; - + let ivData = [NSMutableData dataWithLength:blockSize]; + // Prepare preamble // Instead of using an IV, OpenPGP prefixes a string of length equal to the block size of the cipher plus two to the data before it is encrypted. // The first block-size octets (for example, 8 octets for a 64-bit block length) are random, uint8_t buf[blockSize]; if (SecRandomCopyBytes(kSecRandomDefault, blockSize, buf) == -1) { + //TODO: error return NO; } - NSMutableData *prefixRandomData = [NSMutableData dataWithBytes:buf length:blockSize]; - + let prefixRandomData = [NSMutableData dataWithBytes:buf length:blockSize]; + // and the following two octets are copies of the last two octets of the IV. - NSMutableData *prefixRandomFullData = [NSMutableData dataWithData:prefixRandomData]; + let prefixRandomFullData = [NSMutableData dataWithData:prefixRandomData]; [prefixRandomFullData appendData:[prefixRandomData subdataWithRange:(NSRange){prefixRandomData.length - 2, 2}]]; // Prepare MDC Packet - NSMutableData *toMDCData = [[NSMutableData alloc] init]; + let toMDCData = [[NSMutableData alloc] init]; // preamble [toMDCData appendData:prefixRandomFullData]; // plaintext @@ -231,23 +235,25 @@ // and then also includes two octets of values 0xD3, 0x14 (sha length) UInt8 mdc_suffix[2] = {0xD3, 0x14}; [toMDCData appendBytes:&mdc_suffix length:2]; - - PGPModificationDetectionCodePacket *mdcPacket = [[PGPModificationDetectionCodePacket alloc] initWithData:toMDCData]; - NSData *mdcPacketData = [mdcPacket exportPacket:error]; - if (*error) { + + let mdcPacket = [[PGPModificationDetectionCodePacket alloc] initWithData:toMDCData]; + let _Nullable mdcPacketData = [mdcPacket export:error]; + if (!mdcPacketData || (error && *error)) { return NO; } - + // Finally build encrypted packet data // Encrypt at once (the same encrypt key) preamble + data + mdc - NSMutableData *toEncrypt = [NSMutableData data]; + let toEncrypt = [NSMutableData data]; [toEncrypt appendData:prefixRandomFullData]; [toEncrypt appendData:literalPacketData]; [toEncrypt appendData:mdcPacketData]; - NSData *encrypted = [PGPCryptoCFB encryptData:toEncrypt sessionKeyData:sessionKeyData symmetricAlgorithm:sessionKeyAlgorithm iv:ivData]; - + let encrypted = [PGPCryptoCFB encryptData:toEncrypt sessionKeyData:sessionKeyData symmetricAlgorithm:sessionKeyAlgorithm iv:ivData]; + self.encryptedData = encrypted; return YES; } @end + +NS_ASSUME_NONNULL_END diff --git a/PGPTrustPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.h similarity index 85% rename from PGPTrustPacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.h index db467268..78c2a014 100644 --- a/PGPTrustPacket.h +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.h @@ -7,12 +7,11 @@ // // Tag 12 -#import <Foundation/Foundation.h> #import "PGPPacketFactory.h" +#import <Foundation/Foundation.h> @interface PGPTrustPacket : PGPPacket -@property (strong, readonly) NSData *data; - +@property (nonatomic, readonly) NSData *data; @end diff --git a/PGPTrustPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.m similarity index 72% rename from PGPTrustPacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.m index c974ce0b..6e646696 100644 --- a/PGPTrustPacket.m +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPTrustPacket.m @@ -9,18 +9,16 @@ #import "PGPTrustPacket.h" @interface PGPTrustPacket () -@property (strong, readwrite) NSData *data; +@property (nonatomic, readwrite) NSData *data; @end @implementation PGPTrustPacket -- (PGPPacketTag)tag -{ +- (PGPPacketTag)tag { return PGPTrustPacketTag; } -- (NSUInteger) parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error -{ +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { NSUInteger position = [super parsePacketBody:packetBody error:error]; // 5.10. Trust Packet (Tag 12) @@ -30,10 +28,8 @@ return position; } - -- (NSData *) exportPacket:(NSError *__autoreleasing *)error -{ - //TODO: export trust packet +- (nullable NSData *)export:(NSError *__autoreleasing *)error { + // TODO: export trust packet // (1 octet "level" (depth), 1 octet of trust amount) return [self.data copy]; } diff --git a/PGPUserAttributePacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.h similarity index 72% rename from PGPUserAttributePacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.h index 3e8e6dbc..7f86d1a5 100644 --- a/PGPUserAttributePacket.h +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.h @@ -7,10 +7,11 @@ // #import "PGPPacket.h" +#import "PGPUserAttributeSubpacket.h" @interface PGPUserAttributePacket : PGPPacket // array of PGPUserAttributeSubpacket -@property (strong) NSArray *subpackets; +@property (nonatomic) NSArray<PGPUserAttributeSubpacket *> *subpackets; @end diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.m new file mode 100644 index 00000000..b8bc2d38 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributePacket.m @@ -0,0 +1,89 @@ +// +// PGPUserAttributePacket.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 24/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPUserAttributePacket.h" +#import "PGPUserAttributeSubpacket.h" +#import "PGPFoundation.h" + +@implementation PGPUserAttributePacket + +- (PGPPacketTag)tag { + return PGPUserAttributePacketTag; +} + +// FIXME: handle image subtype. Somehow it's broken, so not supported. +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + NSUInteger position = [super parsePacketBody:packetBody error:error]; + position = position + packetBody.length; + return position; + // while (position < position + packetBody.length) { + // UInt8 lengthLength = 0; + // UInt8 *lengthOctets = (UInt8 *)[packetBody subdataWithRange:(NSRange){position, 5}].bytes; + // UInt8 subpacketLength = lengthOctets[0]; + // + // if (lengthOctets[0] < 192) { + // // 4.2.2.1. One-Octet Length + // // bodyLen = 1st_octet; + // subpacketLength = lengthOctets[0]; + // lengthLength = 1; + // } else if (lengthOctets[0] >= 192 && lengthOctets[0] <= 223) { + // // 4.2.2.2. Two-Octet Lengths + // // bodyLen = ((1st_octet - 192) << 8) + (2nd_octet) + 192 + // subpacketLength = ((lengthOctets[0] - 192) << 8) + (lengthOctets[1]) + 192; + // lengthLength = 2; + // } else { + // // 4.2.2.3. Five-Octet Length + // // bodyLen = (2nd_octet << 24) | (3rd_octet << 16) | + // // (4th_octet << 8) | 5th_octet + // subpacketLength = (lengthOctets[1] << 24) | (lengthOctets[2] << 16) | (lengthOctets[3] << 8) | lengthOctets[4]; + // lengthLength = 5; + // } + // NSLog(@"PGPUserAttributePacket subpacketLength %@ (%@)",@(subpacketLength), @(lengthLength)); + // position = position + lengthLength; + // + // UInt8 subpacketType = 0; + // [packetBody getBytes:&subpacketType range:(NSRange){position, 1}]; + // position = position + 1; + // + //// PGPUserAttributeSubpacket *subpacket = [[PGPUserAttributeSubpacket alloc] init]; + //// subpacket.type = subpacketType; + //// subpacket.valueData = [packetBody subdataWithRange:(NSRange){position, subpacketLength}]; + //// position = position + subpacketLength; + //// + //// self.subpackets = [self.subpackets arrayByAddingObject:subpacket]; + // } + + return position; +} + +- (NSData *)export:(NSError *__autoreleasing *)error { + // TODO: export + return nil; +} + +#pragma mark - isEqual + +- (BOOL)isEqual:(id)other { + if (self == other) { return YES; } + if ([super isEqual:other] && [other isKindOfClass:self.class]) { + return [self isEqualToAttributePacket:other]; + } + return NO; +} + +- (BOOL)isEqualToAttributePacket:(PGPUserAttributePacket *)packet { + return PGPEqualObjects(self.subpackets,packet.subpackets); +} + +- (NSUInteger)hash { + NSUInteger result = 1; + result = 31 * result + self.subpackets.hash; + return result; +} + +@end diff --git a/PGPUserAttributeSubpacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributeSubpacket.h similarity index 82% rename from PGPUserAttributeSubpacket.h rename to enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributeSubpacket.h index 46f94673..515b87d3 100644 --- a/PGPUserAttributeSubpacket.h +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributeSubpacket.h @@ -8,12 +8,11 @@ #import <Foundation/Foundation.h> - @interface PGPUserAttributeSubpacket : NSObject // Subpacket types 100 through 110 are reserved for private or experimental use. -@property (assign) UInt8 type; +@property (nonatomic) UInt8 type; // Value -@property (strong) NSData *valueData; +@property (nonatomic) NSData *valueData; @end diff --git a/PGPUserAttributeSubpacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributeSubpacket.m similarity index 100% rename from PGPUserAttributeSubpacket.m rename to enzevalos_iphone/ObjectivePGP/Packets/PGPUserAttributeSubpacket.m diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.h b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.h new file mode 100644 index 00000000..da5b6335 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.h @@ -0,0 +1,26 @@ +// +// PGPUserID.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 05/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// +// Tag 13 + +#import "PGPMacros.h" +#import "PGPPacket.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPUserIDPacket : PGPPacket + +@property (nonatomic, copy, readonly) NSString *userID; + +PGP_EMPTY_INIT_UNAVAILABLE + +- (instancetype)initWithUserID:(NSString *)userID NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.m b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.m new file mode 100644 index 00000000..1f9e67b8 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Packets/PGPUserIDPacket.m @@ -0,0 +1,55 @@ +// +// PGPUserID.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 05/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPUserIDPacket.h" +#import "PGPPacket+Private.h" +#import "PGPMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface PGPUserIDPacket () + +@property (nonatomic, copy, readwrite) NSString *userID; + +@end + +@implementation PGPUserIDPacket + +- (instancetype)initWithUserID:(NSString *)userID { + if ((self = [super init])) { + _userID = [userID copy]; + } + return self; +} + +- (PGPPacketTag)tag { + return PGPUserIDPacketTag; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %@", [super description], self.userID]; +} + +- (NSUInteger)parsePacketBody:(NSData *)packetBody error:(NSError *__autoreleasing *)error { + NSUInteger position = [super parsePacketBody:packetBody error:error]; + + self.userID = [[NSString alloc] initWithData:packetBody encoding:NSUTF8StringEncoding]; + position = position + packetBody.length; + + return position; +} + +- (nullable NSData *)export:(NSError *__autoreleasing *)error { + return [PGPPacket buildPacketOfType:self.tag withBody:^NSData * { + return [self.userID dataUsingEncoding:NSUTF8StringEncoding]; + }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.h b/enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.h new file mode 100644 index 00000000..fafba1a7 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.h @@ -0,0 +1,33 @@ +// +// NSData+PGPUtils.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "PGPTypes.h" +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface NSData (PGPUtils) + +- (UInt16)pgp_Checksum; +- (UInt32)pgp_CRC24; +- (NSData *)pgp_MD5; +- (NSData *)pgp_SHA1; +- (NSData *)pgp_SHA224; +- (NSData *)pgp_SHA256; +- (NSData *)pgp_SHA384; +- (NSData *)pgp_SHA512; +- (NSData *)pgp_RIPEMD160; + ++ (NSData *)dataWithValue:(NSValue *)value; + +- (NSData *)pgp_HashedWithAlgorithm:(PGPHashAlgorithm)hashAlgorithm; +- (NSData *)pgp_encryptBlockWithSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm sessionKeyData:(NSData *)sessionKeyData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.m b/enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.m new file mode 100644 index 00000000..718dbcb2 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSData+PGPUtils.m @@ -0,0 +1,198 @@ +// +// NSData+PGPUtils.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 04/05/14. +// Copyright (c) 2014 Marcin Krzyżanowski. All rights reserved. +// + +#import "NSData+PGPUtils.h" +#import "PGPCryptoHash.h" +#import "PGPCryptoUtils.h" +#import "PGPMacros+Private.h" + +#import <CommonCrypto/CommonCrypto.h> + +#import <openssl/aes.h> +#import <openssl/blowfish.h> +#import <openssl/camellia.h> +#import <openssl/cast.h> +#import <openssl/des.h> +#import <openssl/idea.h> +#import <openssl/ripemd.h> +#import <openssl/sha.h> + +NS_ASSUME_NONNULL_BEGIN + +@implementation NSData (PGPUtils) + +/** + * Calculates a 16bit sum of a string by adding each character * codes modulus 65535 + * + * @return checksum + */ +- (UInt16)pgp_Checksum { + UInt32 s = 0; + const UInt8 *bytes = self.bytes; + for (NSUInteger i = 0; i < self.length; i++) { + s = (s + (UInt8)bytes[i]); + } + s = s % 65536; + return (UInt16)s; +} + +#define CRC24_POLY 0x1864cfbL +#define CRC24_INIT 0xB704CEL + +- (UInt32)pgp_CRC24 { + UInt32 crc = CRC24_INIT; + NSUInteger len = self.length; + const UInt8 *octets = self.bytes; + int i; + while (len--) { + crc ^= (*octets++) << 16; + for (i = 0; i < 8; i++) { + crc <<= 1; + if (crc & 0x1000000) crc ^= CRC24_POLY; + } + } + return crc & 0xFFFFFFL; +} + +- (NSData *)pgp_MD5 { + return PGPmd5(^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +- (NSData *)pgp_SHA1 { + return PGPsha1(^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +- (NSData *)pgp_SHA224 { + return PGPsha224(^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +- (NSData *)pgp_SHA256 { + return PGPsha256(^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +- (NSData *)pgp_SHA384 { + return PGPsha384(^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +- (NSData *)pgp_SHA512 { + return PGPsha512(^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +- (NSData *)pgp_RIPEMD160 { + return PGPripemd160(^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +- (NSData *)pgp_HashedWithAlgorithm:(PGPHashAlgorithm)hashAlgorithm { + return PGPCalculateHash(hashAlgorithm, ^(void (^update)(const void *, int)) { + update(self.bytes, (int)self.length); + }); +} + +#pragma mark - NSValue + ++ (NSData *)dataWithValue:(NSValue *)value { + NSUInteger size = 0; + let encoding = [value objCType]; + NSGetSizeAndAlignment(encoding, &size, nil); + + let ptr = calloc(size,1); + [value getValue:ptr]; + let data = [NSData dataWithBytes:ptr length:size]; + free(ptr); + + return data; +} + +#pragma mark - Encryption + +- (NSData *)pgp_encryptBlockWithSymmetricAlgorithm:(PGPSymmetricAlgorithm)symmetricAlgorithm sessionKeyData:(NSData *)sessionKeyData { + NSAssert(sessionKeyData, @"Missing key data"); + + if (!sessionKeyData) { + return nil; + } + + NSUInteger keySize = [PGPCryptoUtils keySizeOfSymmetricAlgorithm:symmetricAlgorithm]; + + NSData *ret = nil; + + switch (symmetricAlgorithm) { + case PGPSymmetricCAST5: { + CAST_KEY *encrypt_key = calloc(1, sizeof(CAST_KEY)); + CAST_set_key(encrypt_key, (unsigned int)keySize, sessionKeyData.bytes); + UInt8 *outBuf = calloc(self.length, sizeof(UInt8)); + CAST_ecb_encrypt(self.bytes, outBuf, encrypt_key, CAST_ENCRYPT); + ret = [NSData dataWithBytes:&outBuf length:self.length]; + + free(outBuf); + free(encrypt_key); + } break; + case PGPSymmetricAES256: + case PGPSymmetricAES128: + case PGPSymmetricAES192: { + AES_KEY *encrypt_key = calloc(1, sizeof(AES_KEY)); + AES_set_encrypt_key(sessionKeyData.bytes, (int)(keySize * 8), encrypt_key); + + UInt8 *outBuf = calloc(self.length, sizeof(UInt8)); + AES_encrypt(self.bytes, outBuf, encrypt_key); + ret = [NSData dataWithBytes:&outBuf length:self.length]; + + free(outBuf); + free(encrypt_key); + } break; + case PGPSymmetricIDEA: { + IDEA_KEY_SCHEDULE *encrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE)); + idea_set_encrypt_key(sessionKeyData.bytes, encrypt_key); + + UInt8 *outBuf = calloc(self.length, sizeof(UInt8)); + idea_ecb_encrypt(self.bytes, outBuf, encrypt_key); + ret = [NSData dataWithBytes:&outBuf length:self.length]; + + free(outBuf); + free(encrypt_key); + } break; + case PGPSymmetricTripleDES: { + // Very unsure if this is working, need some tests later + const void *key = sessionKeyData.bytes; + + DES_key_schedule *keys3 = calloc(3, sizeof(DES_key_schedule)); + for (int n = 0; n < 3; ++n) { + DES_set_key((DES_cblock *)(void *)(key + n * 8), &keys3[n]); + } + + DES_cblock *outBuf = calloc(self.length, sizeof(DES_cblock)); + DES_ecb3_encrypt((void *)(unsigned long)(const void *)(self.bytes), outBuf, &keys3[0], &keys3[1], &keys3[2], DES_ENCRYPT); + ret = [NSData dataWithBytes:&outBuf length:self.length]; + + free(outBuf); + free(keys3); + } break; + default: + [NSException raise:@"PGPNotSupported" format:@"Encryption unsupported, cant encrypt data"]; + break; + } + return ret; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.h b/enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.h new file mode 100644 index 00000000..cf03ceb9 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.h @@ -0,0 +1,18 @@ +// +// NSData+zlib.h +// +// rfc1950 (zlib format) + +#import <Foundation/Foundation.h> + +extern NSString *const ZlibErrorDomain; + +@interface NSData (compression) + +- (NSData *)zlibCompressed:(NSError *__autoreleasing *)error; +- (NSData *)zlibDecompressed:(NSError *__autoreleasing *)error compressionType:(int)compressionType; + +- (NSData *)bzip2Decompressed:(NSError *__autoreleasing *)error; +- (NSData *)bzip2Compressed:(NSError *__autoreleasing *)error; + +@end diff --git a/NSData+compression.m b/enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.m old mode 100755 new mode 100644 similarity index 60% rename from NSData+compression.m rename to enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.m index 90886dfa..51f8600d --- a/NSData+compression.m +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSData+compression.m @@ -5,49 +5,45 @@ #import "NSData+compression.h" #import "PGPCompressedPacket.h" -#import <zlib.h> #import <bzlib.h> -#import "BZipCompression.h" +#import <zlib.h> @implementation NSData (compression) -- (NSData *)zlibCompressed:(NSError * __autoreleasing *)error -{ - if ([self length] == 0) - { - return [NSData data]; - } - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - if (Z_OK != deflateInit(&strm, Z_DEFAULT_COMPRESSION)) //FIXME -13 for PGP 2.x - { +- (NSData *)zlibCompressed:(NSError *__autoreleasing *)error { + if ([self length] == 0) { + return [NSData data]; + } + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + if (Z_OK != deflateInit(&strm, Z_DEFAULT_COMPRESSION)) // FIXME -13 for PGP 2.x + { if (error) { NSString *errorMsg = [NSString stringWithCString:strm.msg encoding:NSASCIIStringEncoding]; *error = [NSError errorWithDomain:@"ZLIB" code:0 userInfo:@{NSLocalizedDescriptionKey: errorMsg}]; } return nil; - } - - NSMutableData *compressed = [NSMutableData dataWithLength: deflateBound(&strm, [self length])]; - strm.next_out = [compressed mutableBytes]; - strm.avail_out = (uInt)compressed.length; - strm.next_in = (void *)[self bytes]; - strm.avail_in = (uInt)[self length]; - - while (deflate(&strm, Z_FINISH) != Z_STREAM_END) - { - // deflate should return Z_STREAM_END on the first call - [compressed setLength: [compressed length] * 1.5]; - strm.next_out = [compressed mutableBytes] + strm.total_out; - strm.avail_out = (uInt)(compressed.length - strm.total_out); - } - - [compressed setLength: strm.total_out]; - - int status = deflateEnd(&strm); + } + + NSMutableData *compressed = [NSMutableData dataWithLength:deflateBound(&strm, [self length])]; + strm.next_out = [compressed mutableBytes]; + strm.avail_out = (uInt)compressed.length; + strm.next_in = (void *)[self bytes]; + strm.avail_in = (uInt)[self length]; + + while (deflate(&strm, Z_FINISH) != Z_STREAM_END) { + // deflate should return Z_STREAM_END on the first call + [compressed setLength:(NSUInteger)(compressed.length * 1.5f)]; + strm.next_out = [compressed mutableBytes] + strm.total_out; + strm.avail_out = (uInt)(compressed.length - strm.total_out); + } + + [compressed setLength:strm.total_out]; + + int status = deflateEnd(&strm); if (status != Z_OK) { if (error) { NSString *errorMsg = [NSString stringWithCString:strm.msg encoding:NSASCIIStringEncoding]; @@ -55,52 +51,48 @@ } return nil; } - - return compressed; + + return compressed; } -- (NSData *)zlibDecompressed:(NSError * __autoreleasing *)error compressionType:(int)compressionType -{ - if ([self length] == 0) - { - return [NSData data]; - } - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - if (Z_OK != (compressionType == PGPCompressionZIP ? inflateInit2( &strm, -15) : inflateInit(&strm))) - { +- (NSData *)zlibDecompressed:(NSError *__autoreleasing *)error compressionType:(int)compressionType { + if ([self length] == 0) { + return [NSData data]; + } + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + if (Z_OK != (compressionType == PGPCompressionZIP ? inflateInit2(&strm, -15) : inflateInit(&strm))) { if (error) { NSString *errorMsg = [NSString stringWithCString:strm.msg encoding:NSASCIIStringEncoding]; *error = [NSError errorWithDomain:@"ZLIB" code:0 userInfo:@{NSLocalizedDescriptionKey: errorMsg}]; } return nil; - } - - NSMutableData *decompressed = [NSMutableData dataWithLength: [self length]*2.5]; - strm.next_out = [decompressed mutableBytes]; - strm.avail_out = (uInt)[decompressed length]; - strm.next_in = (void *)[self bytes]; - strm.avail_in = (uInt)[self length]; - // From the gnupg sources this might be needed - of course not like this, as we need to extend the input buffer length for this - //if (compressionType == PGPCompressionZIP) - //{ - // *(strm.next_in + (uInt)[self length]) = 0xFF; - //} - - while (inflate(&strm, Z_FINISH) != Z_STREAM_END) - { - // inflate should return Z_STREAM_END on the first call - [decompressed setLength: [decompressed length] * 1.5]; - strm.next_out = [decompressed mutableBytes] + strm.total_out; - strm.avail_out = (uInt)([decompressed length] - strm.total_out); - } - - [decompressed setLength: strm.total_out]; - - int status = inflateEnd(&strm); + } + + NSMutableData *decompressed = [NSMutableData dataWithLength:(NSUInteger)(self.length * 2.5f)]; + strm.next_out = [decompressed mutableBytes]; + strm.avail_out = (uInt)[decompressed length]; + strm.next_in = (void *)[self bytes]; + strm.avail_in = (uInt)[self length]; + // From the gnupg sources this might be needed - of course not like this, as we need to extend the input buffer length for this + // if (compressionType == PGPCompressionZIP) + //{ + // *(strm.next_in + (uInt)[self length]) = 0xFF; + //} + + while (inflate(&strm, Z_FINISH) != Z_STREAM_END) { + // inflate should return Z_STREAM_END on the first call + [decompressed setLength:(NSUInteger)(decompressed.length * 1.5f)]; + strm.next_out = [decompressed mutableBytes] + strm.total_out; + strm.avail_out = (uInt)([decompressed length] - strm.total_out); + } + + [decompressed setLength:strm.total_out]; + + int status = inflateEnd(&strm); if (status != Z_OK) { if (error) { NSString *errorMsg = [NSString stringWithCString:strm.msg encoding:NSASCIIStringEncoding]; @@ -108,22 +100,21 @@ } return nil; } - - return decompressed; + + return decompressed; } -- (NSData *)bzip2Decompressed:(NSError * __autoreleasing *)error -{ +- (NSData *)bzip2Decompressed:(NSError *__autoreleasing *)error { int bzret = 0; - bz_stream stream = {0x00}; + bz_stream stream = {.avail_in = 0x00}; stream.next_in = (void *)[self bytes]; stream.avail_in = (uInt)self.length; - + const int buffer_size = 10000; NSMutableData *buffer = [NSMutableData dataWithLength:buffer_size]; stream.next_out = [buffer mutableBytes]; stream.avail_out = buffer_size; - + bzret = BZ2_bzDecompressInit(&stream, 0, NO); if (bzret != BZ_OK) { if (error) { @@ -131,7 +122,7 @@ } return nil; } - + NSMutableData *decompressedData = [NSMutableData data]; do { bzret = BZ2_bzDecompress(&stream); @@ -141,20 +132,19 @@ } return nil; } - + [decompressedData appendBytes:[buffer bytes] length:(buffer_size - stream.avail_out)]; stream.next_out = [buffer mutableBytes]; stream.avail_out = buffer_size; } while (bzret != BZ_STREAM_END); - + BZ2_bzDecompressEnd(&stream); return decompressedData; } -- (NSData *)bzip2Compressed:(NSError * __autoreleasing *)error -{ +- (NSData *)bzip2Compressed:(NSError *__autoreleasing *)error { int bzret = 0; - bz_stream stream = {0x00}; + bz_stream stream = {.avail_in = 0x00}; stream.next_in = (void *)[self bytes]; stream.avail_in = (uInt)self.length; unsigned int compression = 9; // should be a value between 1 and 9 inclusive @@ -163,8 +153,7 @@ NSMutableData *buffer = [NSMutableData dataWithLength:buffer_size]; stream.next_out = [buffer mutableBytes]; stream.avail_out = buffer_size; - - + bzret = BZ2_bzCompressInit(&stream, compression, 0, 0); if (bzret != BZ_OK) { if (error) { @@ -172,9 +161,9 @@ } return nil; } - + NSMutableData *compressedData = [NSMutableData data]; - + do { bzret = BZ2_bzCompress(&stream, (stream.avail_in) ? BZ_RUN : BZ_FINISH); if (bzret < BZ_OK) { @@ -186,14 +175,11 @@ [compressedData appendBytes:[buffer bytes] length:(buffer_size - stream.avail_out)]; stream.next_out = [buffer mutableBytes]; stream.avail_out = buffer_size; - + } while (bzret != BZ_STREAM_END); - + BZ2_bzCompressEnd(&stream); return compressedData; - } - - @end diff --git a/enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.h b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.h new file mode 100644 index 00000000..05d583ef --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.h @@ -0,0 +1,19 @@ +// +// NSMutableArray+PGPUtils.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/09/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface NSMutableArray <ObjectType> (PGPUtils) + +- (void)pgp_addObject:(nullable ObjectType)anObject; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.m b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.m new file mode 100644 index 00000000..e28aed4e --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableArray+PGPUtils.m @@ -0,0 +1,23 @@ +// +// NSMutableArray+PGPUtils.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/09/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "NSMutableArray+PGPUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation NSMutableArray (PGPUtils) + +- (void)pgp_addObject:(nullable id)anObject { + if (anObject) { + [self addObject:anObject]; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.h b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.h new file mode 100644 index 00000000..bba1fec6 --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.h @@ -0,0 +1,19 @@ +// +// NSMutableData+PGPUtils.h +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/09/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface NSMutableData (PGPUtils) + +- (void)pgp_appendData:(nullable NSData *)other; + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.m b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.m new file mode 100644 index 00000000..1fccc8df --- /dev/null +++ b/enzevalos_iphone/ObjectivePGP/Utils/NSMutableData+PGPUtils.m @@ -0,0 +1,23 @@ +// +// NSMutableData+PGPUtils.m +// ObjectivePGP +// +// Created by Marcin Krzyzanowski on 10/09/2017. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +#import "NSMutableData+PGPUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation NSMutableData (PGPUtils) + +- (void)pgp_appendData:(nullable NSData *)other { + if (other) { + [self appendData:other]; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/enzevalos_iphone/PGPEncryption.swift b/enzevalos_iphone/PGPEncryption.swift deleted file mode 100644 index 45503f1e..00000000 --- a/enzevalos_iphone/PGPEncryption.swift +++ /dev/null @@ -1,676 +0,0 @@ -// -// PGPEncryption.swift -// enzevalos_iphone -// -// Created by jakobsbode on 18.01.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -class PGPEncryption : Encryption { - - internal let encryptionHandler: EncryptionHandler - internal let keyManager: PGPKeyManagement - var password = "525062478368502727504972217063013649" - //internal let keyIDs : [] - - var encryptionType: EncryptionType { - get { - return EncryptionType.PGP - } - } - - required init(encHandler: EncryptionHandler) { - self.encryptionHandler = encHandler - self.keyManager = PGPKeyManagement(encryptionHandler: self.encryptionHandler) - } - - func newPassword() -> String{ - // Autocrypt: 36 nums (0...9) see: https://autocrypt.readthedocs.io/en/latest/level1.html#setup-code - var pw = "" - for _ in 0..<36{ - let rand = arc4random_uniform(10) - print (rand) - pw.append("\(rand)") - } - //TODO safe key in Keychain! - return "525062478368502727504972217063013649" - //return pw - } - - private func importKeys(dir: String?, adr: String?) -> KeyWrapper?{ - let objectivePGP = self.getPGPKeyManagement().pgp - var keyID: String? - - if let keydir = dir{ - if let keys = objectivePGP.importKeys(fromFile: keydir , allowDuplicates: false){ - for k in keys { - let newKey = k as! PGPKey - do{ - let ak = try newKey.export() - keyID = self.addKey(ak, forMailAddress: adr) - } catch _ {} - } - } - - // remove keyring after creation! - let fileManager = FileManager.default - let url = URL.init(fileURLWithPath: keydir) - do{ - try fileManager.removeItem(at: url) - } - catch _ {} - if keyID != nil{ - return self.getKey(keyID!) - } - } - return nil - } - - func generateKey(adr: String) -> KeyWrapper?{ - - let unnetpgp = UNNetPGP.init(userId: adr) - - unnetpgp?.password = password - unnetpgp?.armored = true - unnetpgp?.generateKey(2048) - - // import private key - let key = importKeys(dir: unnetpgp?.secretKeyRingPath, adr: nil) - - // import public key - _ = importKeys(dir: unnetpgp?.publicKeyRingPath, adr: adr) - return key - } - - - - func getPGPKeyManagement() -> PGPKeyManagement { - return keyManager - } - - func isUsed(_ mail: PersistentMail) -> Bool { - if let plain = mail.body { - return isUsed(plain, key: nil) - } - return false - } - - //key is unused - func isUsed(_ text: String, key: KeyWrapper?) -> Bool { - if let usedForSignature = self.isUsedForSignature(text, key: key), usedForSignature { - return true - } - return self.isUsedForEncryption(text, key: key)! - } - - //check whether this encryption is used in this mail for encryption. nil is returned, if there is no answer to be made at the moment. - func isUsedForEncryption(_ mail: PersistentMail) -> Bool? { - if let plain = mail.body { - return isUsedForEncryption(plain, key: nil) - } - return false - } - - //check whether this encryption is used in this text for encryption. the key is not known to be used. nil is returned, if there is no answer to be made at the moment. - //key unused - func isUsedForEncryption(_ text: String, key: KeyWrapper?) -> Bool?{ - return getCipher(text: text) != "" //text.hasPrefix("-----BEGIN PGP MESSAGE-----") && (text.hasSuffix("-----END PGP MESSAGE-----\n") || text.hasSuffix("-----END PGP MESSAGE-----")) - } - - //check whether this encryption is used in this mail for signing. nil is returned, if there is no answer to be made at the moment. - func isUsedForSignature(_ mail: PersistentMail) -> Bool?{ - //TODO api-check - //baut auf der Annahme auf, dass der signierte Teil nach dem entschlüsseln noch vorhanden ist. - if let plain = mail.decryptedBody { - return isUsedForSignature(plain, key: nil) - } - else if let plain = mail.body { - return isUsedForSignature(plain, key: nil) - } - return false - } - - //check whether this encryption is used in this text for signing. nil is returned, if there is no answer to be made at the moment. - //key unused - func isUsedForSignature(_ text: String, key: KeyWrapper?) -> Bool? { - if !isUsedForEncryption(text, key: nil)! { - return text.hasPrefix("-----BEGIN PGP SIGNED MESSAGE-----") && (text.hasSuffix("-----END PGP SIGNATURE-----\n") || text.hasSuffix("-----END PGP SIGNATURE-----")) - } - return nil - } - - func decryptedMime(_ data: Data, from: String) -> DecryptedData?{ - var sigState: SignatureState = SignatureState.NoSignature - var encState: EncryptionState = EncryptionState.NoEncryption - var handeledData: Data? - var signkey: String? - - if true { - //has to be var because it is given as pointer to obj-c-code - var error: NSErrorPointer = NSErrorPointer.none - var temp = keyManager.pgp.decryptDataFirstPart(data, passphrase: password, integrityProtected: nil, error: error) - var maybeUsedKeys: [String] = [] - //has to be var because it is given as pointer to obj-c-code - var signed = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1) - signed[0] = false - //has to be var because it is given as pointer to obj-c-code - var valid = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1) - valid[0] = false - handeledData = temp.plaintextData - if handeledData != nil{ - encState = EncryptionState.ValidedEncryptedWithCurrentKey - } - else { - self.keyManager.useAllPrivateKeys() - temp = keyManager.pgp.decryptDataFirstPart(data, passphrase: password, integrityProtected: nil, error: error) - handeledData = temp.plaintextData //TODO Does this works? - self.keyManager.useOnlyActualPrivateKey() - if handeledData != nil { - encState = EncryptionState.ValidEncryptedWithOldKey - } - } - if error.debugDescription == "MDC validation failed" { - encState = EncryptionState.UnableToDecrypt - } - if let unwrappedData = handeledData { - handeledData = unwrappedData - if let allKeyIDs = self.keyManager.getKeyIDsForMailAddress(from), let theirKeyID = temp.incompleteKeyID{ - maybeUsedKeys = self.getLibaryKeyIDOverlap(theirKeyID, ourKeyIDs: allKeyIDs) - } - for maybeUsedKey in maybeUsedKeys { - if let key = self.keyManager.getKey(maybeUsedKey) { - //FIXME - - let done : ObjCBool - done = (self.keyManager.pgp.decryptDataSecondPart(temp, verifyWithPublicKey: key.key, signed: signed, valid: valid, error: error)[0]) - if let errorHappening = (error?.debugDescription.contains("Missing")), errorHappening { - sigState = SignatureState.InvalidSignature - break - } - - if !done.boolValue { - sigState = SignatureState.NoSignature - break - } - if valid.pointee.boolValue{ - sigState = SignatureState.ValidSignature - signkey = key.keyID - break - } - else{ - sigState = SignatureState.InvalidSignature - break - } - } - } - return DecryptedData.init(decryptedBody: handeledData, sigState: sigState, encState: encState, key: signkey, encType: EncryptionType.PGP) - } - } - encState = EncryptionState.UnableToDecrypt - - return DecryptedData.init(decryptedBody: handeledData, sigState: sigState, encState: encState, key: signkey, encType: EncryptionType.PGP) - - } - - - - - //TODO - //decrypt the mails body. the decryted body will be saved in the mail object. - func decrypt(_ mail: PersistentMail)-> String?{ - if self.isUsed(mail) { - //let bodyData = mail.body!.data(using: String.Encoding.utf8)! - let bodyData = getCipher(text: mail.body!).data(using: String.Encoding.utf8)! - var data = try? keyManager.pgp.decryptData(bodyData, passphrase: password) - if data == nil { - self.keyManager.useAllPrivateKeys() - //TODO add oldKeyUsed attribute in Mail object - data = try? keyManager.pgp.decryptData(mail.body!.data(using: String.Encoding.utf8)!, passphrase: password) - self.keyManager.useOnlyActualPrivateKey() - if data != nil { - mail.decryptedWithOldPrivateKey = true - } - } - if let unwrappedData = data { - mail.decryptedBody = String(data: unwrappedData, encoding: String.Encoding.utf8) - return String(data: unwrappedData, encoding: String.Encoding.utf8) - } - } - /*if self.isUsed(mail) { - //sortInPlace auf keyRecords, um Reihnfolge für signature keys zu bekommen. - var signed = false - var valid = false - var integrityProtected = false - let verificationKey = keyManager.getKey(keyManager.) - var data = try? keyManager.pgp.decryptData(mail.body!.dataUsingEncoding(NSUTF8StringEncoding)!, passphrase: nil, verifyWithPublicKey: ) - if data == nil { - self.keyManager.useAllPrivateKeys() - //TODO add oldKeyUsed attribute in Mail object - data = try? keyManager.pgp.decryptData(mail.body!.dataUsingEncoding(NSUTF8StringEncoding)!, passphrase: nil) - self.keyManager.useOnlyActualPrivateKey() - if data != nil { - mail.oldKeyUsed = true - } - } - if let unwrappedData = data { - mail.decryptedBody = String(data: unwrappedData, encoding: NSUTF8StringEncoding) - } - }*/ - return nil - } - - func decryptAndSignatureCheck(_ mail: PersistentMail) { - if self.isUsed(mail) { - //let bodyData = mail.body!.data(using: String.Encoding.utf8)! - let bodyData = getCipher(text: mail.body!).data(using: String.Encoding.utf8)! - var data: Data? - //has to be var because it is given as pointer to obj-c-code - var error: NSErrorPointer = NSErrorPointer.none - var temp = keyManager.pgp.decryptDataFirstPart(bodyData, passphrase: password, integrityProtected: nil, error: error) - var maybeUsedKeys: [String] = [] - //has to be var because it is given as pointer to obj-c-code - var signed = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1) - signed[0] = false - //has to be var because it is given as pointer to obj-c-code - var valid = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1) - valid[0] = false - data = temp.plaintextData - if data == nil { - self.keyManager.useAllPrivateKeys() - temp = keyManager.pgp.decryptDataFirstPart(bodyData, passphrase: password, integrityProtected: nil, error: error) - data = temp.plaintextData - self.keyManager.useOnlyActualPrivateKey() - if data != nil { - mail.decryptedWithOldPrivateKey = true - } - } - if error.debugDescription == "MDC validation failed" { - mail.trouble = true - } - if let unwrappedData = data { - mail.decryptedBody = String(data: unwrappedData, encoding: String.Encoding.utf8) - if let allKeyIDs = self.keyManager.getKeyIDsForMailAddress(mail.from.mailAddress), let theirKeyID = temp.incompleteKeyID { - maybeUsedKeys = self.getLibaryKeyIDOverlap(theirKeyID, ourKeyIDs: allKeyIDs) - } - for maybeUsedKey in maybeUsedKeys { - if let key = self.keyManager.getKey(maybeUsedKey) { - //FIXME - let done : ObjCBool - done = (self.keyManager.pgp.decryptDataSecondPart(temp, verifyWithPublicKey: key.key, signed: signed, valid: valid, error: error)[0]) - if let errorHappening = (error?.debugDescription.contains("Missing")), errorHappening { - mail.trouble = true - mail.isCorrectlySigned = false - break - } - - if !done.boolValue { - mail.isSigned = false - mail.isCorrectlySigned = false - break - } - mail.isSigned = signed.pointee.boolValue - mail.isCorrectlySigned = valid.pointee.boolValue - if mail.isSigned && mail.isCorrectlySigned { - mail.keyID = key.keyID - break - } - } - } - if mail.isSigned && !mail.isCorrectlySigned && maybeUsedKeys != [] { - mail.trouble = true - } - return - } - } - mail.unableToDecrypt = true - } - - //decrypt the text with the given key and return it. - func decrypt(_ text: String, keyID: String) -> String?{ - if let privKeys = keyManager.getAllPrivateKeyIDs() { - if !privKeys.contains(keyID) { - return nil - } - } - if let key = keyManager.getKey(keyID) { - let pgp = ObjectivePGP.init() - pgp.keys.append(key.key) - if let decr = try? pgp.decryptData(text.data(using: String.Encoding.utf8)!, passphrase: password) { - return String(data: decr, encoding: String.Encoding.utf8) - } - } - return nil - } - - //TODO - //check whether the mail is correctly signed with this encryption. nil is returned, if there is no answer to be made at the moment. - func isCorrectlySigned(_ mail: PersistentMail) -> Bool?{ - return false - } - - //TODO - //check whether the text is correctly signed with this encryption. - func isCorrectlySigned(_ text: String, key: KeyWrapper) -> Bool?{ - return false - } - - //TODO - //encrypt mail for contact - func encrypt(_ mail: PersistentMail){ - - } - - //encrypt text with key - func encrypt(_ text: String, keyIDs: [String]) -> Data? { - var encData : Data? = nil - var keys : [PGPKey] = [] - for id in keyIDs { - if let key = keyManager.getKey(id) { - keys.append(key.key) - } - else { - print("PGPEncryption.encrypt: No key found for keyID "+id) - return nil - } - } - if let data = text.data(using: String.Encoding.utf8) { - encData = try? keyManager.pgp.encryptData(data, usingPublicKeys: keys, armored: true) - } - else { - print("PGPEncryption.encrypt: text has to be in UTF8Encoding") - } - return encData - } - - func encrypt(_ text: String, mailaddresses: [String]) -> Data? { - var keyIDs : [String] = [] - for addr in mailaddresses { - if let ids = keyManager.getKeyIDsForMailAddress(addr) { - if ids != [] { - keyIDs.append(ids.last!) - } - else { - print("PGPEncryption.encrypt: no keyID for mailaddress "+addr+" found") - return nil - } - } - else { - print("PGPEncryption.encrypt: no keyID for mailaddress "+addr+" found") - return nil - } - } - - return encrypt(text, keyIDs: keyIDs) - } - - //TODO - //sign mail - func sign(_ mail: PersistentMail){ - - } - - //TODO - //sign text - func sign(_ text: String, key: KeyWrapper) -> String{ - return "" - } - - //TODO - //sign and encrypt mail for contact - func signAndEncrypt(_ mail: PersistentMail, forContact: KeyRecord){ - - } - - func signAndEncrypt(_ text: String, keyIDs: [String]) -> Data? { - var encData : Data? = nil - var keys : [PGPKey] = [] - for id in keyIDs { - if let key = keyManager.getKey(id) { - keys.append(key.key) - } - else { - print("PGPEncryption.encrypt: No key found for keyID "+id) - return nil - } - } - if let data = text.data(using: String.Encoding.utf8) { - if let myKeyID = keyManager.getPrivateKeyID() { - if let myKey = keyManager.getKey(myKeyID) { - encData = try? keyManager.pgp.encryptData(data, usingPublicKeys: keys, signWithSecretKey: myKey.key, passphrase: password, armored: true) - } - else { - return nil - } - } - else { - return nil - } - } - else { - print("PGPEncryption.encrypt: text has to be in UTF8Encoding") - } - return encData - } - - func signAndEncrypt(_ text: String, mailaddresses: [String]) -> Data? { - var keyIDs : [String] = [] - for addr in mailaddresses { - if let ids = keyManager.getKeyIDsForMailAddress(addr) { - if ids != [] { - keyIDs.append(ids.last!) - } - else { - print("PGPEncryption.encrypt: no keyID for mailaddress "+addr+" found") - return nil - } - } - else { - print("PGPEncryption.encrypt: no keyID for mailaddress "+addr+" found") - return nil - } - } - - return signAndEncrypt(text, keyIDs: keyIDs) - } - - //chooses first key in data. others will be ignored - func addKey(_ keyData: Data, forMailAddress: String?) -> String? { - var addrs : [String] = [] - if let addr = forMailAddress { - addrs = [addr] - } - return self.addKey(keyData, forMailAddresses: addrs) - } - - //chooses first key in data. others will be ignored - func addKey(_ keyData: Data, forMailAddresses: [String]?) -> String?{ - return self.addKey(keyData, forMailAddresses: forMailAddresses, discoveryMailUID: nil) - } - - //chooses first key in data. others will be ignored - func addKey(_ keyData: Data, forMailAddresses: [String]?, discoveryMailUID: UInt64?) -> String? { - if let tmpKey = self.keyManager.pgp.keys(from: keyData) { - var addrs : [String] = [] - if let addr = forMailAddresses { - addrs = addr - } - let key = PGPKeyWrapper.init(key: tmpKey[0], mailAddresses: addrs, discoveryMailUID: discoveryMailUID, keyManager: self.keyManager) - return key.keyID - } - return nil - } - - //chooses first key in data. others will be ignored - func addKey(_ keyData: Data, discoveryMail: PersistentMail?) -> String? { - var discoveryMailUID: UInt64? = nil - var forMailAddresses: [String]? = nil - if let mail = discoveryMail { - discoveryMailUID = mail.uid - forMailAddresses = [mail.from.mailAddress] - } - return self.addKey(keyData, forMailAddresses: forMailAddresses, discoveryMailUID: discoveryMailUID) - } - - //TODO maybe remove here. used in keyWrapper - //forMailAddress has to be set (not nil) - /*func addKey(key: PGPKeyWrapper, forMailAddress: String?, callBack: ((success: Bool) -> Void)?){ - /*if forMailAddress == nil { - if let cb = callBack { - cb(success: false) - } - return - } - self.keyManager.addKey(key, forMailAddresses: [forMailAddress!], callBack: nil)*/ - //überprüfen, ob key in dictionary der email zugeordnet - - if let cb = callBack { - cb(success: false) - } - return - }*/ - - fileprivate func getMaxIndex(_ fingerprint: String) -> Int64 { - var index : Int64 = 0 - if let indexData = encryptionHandler.getPersistentData(fingerprint+"-index", encryptionType: self.encryptionType){ - (indexData as NSData).getBytes(&index, length: MemoryLayout<Int64>.size) - } - - return index - } - - func hasKey(_ enzContact: EnzevalosContact) -> Bool { - if let addrs = enzContact.addresses { - if let mailaddrs : [Mail_Address] = (addrs.allObjects as? [Mail_Address]) { - for mail in mailaddrs { - if self.hasKey(mail.address) { - return true - } - } - } - } - return false - } - - func hasKey(_ mailaddress: String) -> Bool { - if let ids = keyManager.getKeyIDsForMailAddress(mailaddress) { - return ids != [] - } - return false - } - - //TODO - func getKeyIDs(_ enzContact: EnzevalosContact) -> [String]? { - return nil - } - - func getKeyIDs(_ mailaddress: String) -> [String]?{ - return keyManager.getKeyIDsForMailAddress(mailaddress) - } - - func getActualKeyID(_ mailaddress: String) -> String? { - if let key = self.keyManager.getActualKeyIDForMailaddress(mailaddress){ - let pk = self.getKey(key) - return key - } - return nil - - } - - - func getKey(_ keyID: String) -> KeyWrapper? { - return self.keyManager.getKey(keyID) - } - - - /*func updateKey(key: PGPKeyWrapper, callBack: ((success: Bool) -> Void)?) { - - }*/ - - func removeKey(_ keyID: String){ - self.keyManager.removeKey(keyID) - } - - func removeKey(_ key: KeyWrapper) { - self.removeKey(key.keyID) - } - - //includes privatekeys too - func removeAllKeys() { - self.keyManager.removeAllKeys() - } - - func printAllKeyIDs() { - keyManager.printAllKeyIDs() - } - - func addMailAddressForKey(_ mailAddress: String, keyID: String) { - self.addMailAddressesForKey([mailAddress], keyID: keyID) - } - - func addMailAddressesForKey(_ mailAddresses: [String], keyID: String) { - self.keyManager.addMailAddressesForKey(mailAddresses, keyID: keyID) - } - - func removeMailAddressForKey(_ mailaddress: String, keyID: String){ - self.removeMailAddressesForKey([mailaddress], keyID: keyID) - } - - func removeMailAddressesForKey(_ mailaddresses: [String], keyID: String){ - self.keyManager.removeMailAddressesForKey(mailaddresses, keyID: keyID) - } - - func keyIDExists(_ keyID: String) -> Bool { - return self.keyManager.keyIDExists(keyID) - } - - //TODO - func keyOfThisEncryption(_ keyData: Data) -> Bool? { - return nil - } - - //TODO: Add for signature only - func getCipher(text: String) -> String { - var range = text.range(of: "-----BEGIN PGP MESSAGE-----") - if let lower = range?.lowerBound { - range = text.range(of: "-----END PGP MESSAGE-----") - if let upper = range?.upperBound { - let retValue = text.substring(to: upper).substring(from: lower) - return retValue - } - } - return "" - } - - - func autocryptHeader(_ adr: String) -> String? { - if let keyId = self.getActualKeyID(adr){ - let key = self.getKey(keyId) as! PGPKeyWrapper - let pgpManger = self.keyManager - var string = "adr = " + adr + "; type = 1;" - let enc = UserManager.loadUserValue(Attribute.prefEncryption) as! String - print ("Enc: \(enc)") - if enc == "yes"{ - string = string + "prefer-encrypted = mutal" - } - string = string + ";key = " - if let keyBase64 = pgpManger.pgp.exportKeyWithoutArmor(key.key){ - string = string + keyBase64 - } - return string - } - return nil - } - - - //the libary (ObjectivePGP) we use has a different definition of keyID than we have. their keyID is calculated outof the key. We take their keyID and add a index in the end to handle collisions - private func getLibaryKeyIDOverlap(_ libaryKeyID: String, ourKeyIDs: [String]) -> [String] { - var returnValue: [String] = [] - for ourKeyID in ourKeyIDs { - if ourKeyID.hasPrefix(libaryKeyID) { - returnValue.append(ourKeyID) - } - } - return returnValue - } - -} diff --git a/enzevalos_iphone/PGPKeyManagement.swift b/enzevalos_iphone/PGPKeyManagement.swift deleted file mode 100644 index 329ee54b..00000000 --- a/enzevalos_iphone/PGPKeyManagement.swift +++ /dev/null @@ -1,319 +0,0 @@ -// -// PGPKeyManagement.swift -// enzevalos_iphone -// -// Created by jakobsbode on 19.01.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -class PGPKeyManagement { - - let encryptionType: EncryptionType - let encryptionHandler: EncryptionHandler - let pgp: ObjectivePGP - private var keyIDs : [String : [String]] = [:] //[mailAddress: keyIDs] - private var addresses : [String: [String]] = [:] //[keyID : mailAddresses] - private var actualPrivateKey: String? - private var privateKeys: [String] - - init(encryptionHandler: EncryptionHandler) { - self.encryptionType = EncryptionType.PGP - self.encryptionHandler = encryptionHandler - //get or create keyIDs - var data = self.encryptionHandler.getPersistentData("keyIDs", encryptionType: self.encryptionType) - if let unwrappedData = data { - self.keyIDs = (NSKeyedUnarchiver.unarchiveObject(with: unwrappedData) as! NSDictionary) as! [String: [String]] - } - else { - data = NSKeyedArchiver.archivedData(withRootObject: keyIDs) - self.encryptionHandler.addPersistentData(data!, searchKey: "keyIDs", encryptionType: self.encryptionType) - } - data = self.encryptionHandler.getPersistentData("addresses", encryptionType: self.encryptionType) - if let unwrappedData = data { - self.addresses = (NSKeyedUnarchiver.unarchiveObject(with: unwrappedData) as! NSDictionary) as! [String: [String]] - } - else { - data = NSKeyedArchiver.archivedData(withRootObject: addresses) - self.encryptionHandler.addPersistentData(data!, searchKey: "addresses", encryptionType: self.encryptionType) - } - data = self.encryptionHandler.getPersistentData("actualPrivateKey", encryptionType: self.encryptionType) - if let unwrappedData = data { - self.actualPrivateKey = NSKeyedUnarchiver.unarchiveObject(with: unwrappedData) as? String - } - else { - self.actualPrivateKey = nil - } - data = self.encryptionHandler.getPersistentData("privateKeys", encryptionType: self.encryptionType) - if let unwrappedData = data { - self.privateKeys = NSKeyedUnarchiver.unarchiveObject(with: unwrappedData) as! [String] - } - else { - self.privateKeys = [] - let insertData = NSKeyedArchiver.archivedData(withRootObject: self.privateKeys) - encryptionHandler.addPersistentData(insertData, searchKey: "privateKeys", encryptionType: self.encryptionType) - } - self.pgp = ObjectivePGP.init() - } - - func getMaxIndex(_ fingerprint: String) -> Int64 { - var index : Int64 = 0 - if let indexData = encryptionHandler.getPersistentData(fingerprint+"-index", encryptionType: self.encryptionType){ - (indexData as NSData).getBytes(&index, length: MemoryLayout<Int64>.size) - } - - return index - } - - @discardableResult func addKey(_ key: PGPKeyWrapper, forMailAddresses: [String]) -> String{ - var index : Int64 = 0 - let searchKey = key.key.keyID.longKeyString+"-index" - var existent = false - if let indexData = encryptionHandler.getPersistentData(searchKey, encryptionType: self.encryptionType){ - existent = true - (indexData as NSData).getBytes(&index, length: MemoryLayout<Int64>.size) - } - - index += 1 - let indexData = Data(bytes: &index, count: MemoryLayout<Int64>.size)//Data(bytes: UnsafePointer<UInt8>(&index), length: MemoryLayout<Int64>.size) - if !existent { - encryptionHandler.addPersistentData(indexData, searchKey: searchKey, encryptionType: self.encryptionType) - } - else { - encryptionHandler.replacePersistentData(searchKey, replacementData: indexData, encryptionType: self.encryptionType) - } - - let keyID = key.key.keyID.longKeyString+"-"+String(index) - key.setOnceKeyID(keyID) - - let data = NSKeyedArchiver.archivedData(withRootObject: key) - //key-ID should be created once - //encryptionHandler.addPersistentData(data, searchKey: key.keyID, encryptionType: self.encryptionType) - - //check, if the key is already inserted - var alreadyInserted = false - var returnedKeyID = keyID - if index > 1 { - for otherIndex in 1...index { - let otherKeyID = key.key.keyID.longKeyString+"-"+String(otherIndex) - if key.key.isEqual(self.getKey(otherKeyID)?.key) { - alreadyInserted = true - returnedKeyID = otherKeyID - break - } - } - } - if !alreadyInserted { - encryptionHandler.addPersistentData(data, searchKey: key.keyID, encryptionType: self.encryptionType) - addMailAddressesForKey(forMailAddresses, keyID: keyID) - addPrivateKey(key) - } - - return returnedKeyID - } - - - func updateKey(_ key: PGPKeyWrapper) { - if encryptionHandler.hasPersistentData(key.keyID, encryptionType: self.encryptionType) { - let keyData = NSKeyedArchiver.archivedData(withRootObject: key) - encryptionHandler.replacePersistentData(key.keyID, replacementData: keyData, encryptionType: self.encryptionType) - return - } - } - - func findPublicKeyInBase64(_ key: PGPKeyWrapper)-> String{ - if let data = self.pgp.exportKeyWithoutArmor(key.key){ - return data - } - return "" - } - - func addMailAddressesForKey(_ mailAddresses: [String], keyID: String){ - for addr in mailAddresses{ - let mailAddress = addr.lowercased() - //insert keyID in keyIDs - if var keys = keyIDs[mailAddress]{ - if !keys.contains(keyID) { - keys.append(keyID) - keyIDs[mailAddress] = keys - } - } - else { - keyIDs[mailAddress] = [keyID] - } - //insert mailAddress in addresses - if var mAddresses = addresses[keyID]{ - if !mAddresses.contains(mailAddress) { - mAddresses.append(mailAddress) - addresses[keyID] = mAddresses - } - } - else { - addresses[keyID] = [mailAddress] - } - } - saveDictionarys() - } - - func removeMailAddressesForKey(_ mailAddresses: [String], keyID: String) { - for addr in mailAddresses{ - let mailAddress = addr.lowercased() - //remove keyID outof keyIDs - if var keys = keyIDs[mailAddress]{ - if keys.contains(keyID) { - keys.remove(at: keys.index(of: keyID)!) - keyIDs[mailAddress] = keys - } - } - //remove mailAddress outof addresses - if var mAddresses = addresses[keyID]{ - if mAddresses.contains(mailAddress) { - mAddresses.remove(at: mAddresses.index(of: mailAddress)!) - addresses[keyID] = mAddresses - } - } - } - saveDictionarys() - } - - func getKeyIDsForMailAddress(_ mailAddress: String) -> [String]?{ - return keyIDs[mailAddress.lowercased()] - } - - func getActualKeyIDForMailaddress(_ mailaddress: String) -> String? { - let key = keyIDs[mailaddress.lowercased()]?.last - return key - } - - //keyID of the current used privateKey - func getPrivateKeyID() -> String? { - return actualPrivateKey - } - - //a list of all privateKeyIDs, which are not removed - func getAllPrivateKeyIDs() -> [String]? { - if self.privateKeys.count == 0 { - return nil - } - return self.privateKeys - } - - func getKey(_ keyID: String) -> PGPKeyWrapper? { - if let data = (encryptionHandler.getPersistentData(keyID, encryptionType: self.encryptionType)) { - let keywrapper = NSKeyedUnarchiver.unarchiveObject(with: data) as? PGPKeyWrapper - return keywrapper - } - return nil - } - - func getMailAddressesForKeyID(_ keyID: String) -> [String]?{ - return addresses[keyID] - } - - func keyIDExists(_ keyID: String) -> Bool { - if let addr = addresses[keyID] { - return addr != [] - } - return false - } - - //if the actualPrivateKey is removed a old key is set as actualPrivateKey, if availiable - func removeKey(_ keyID: String) { - removePrivateKey(keyID) - - var addrs: [String] = [] - if let addrss = addresses[keyID] { - addrs = addrss - } - self.removeMailAddressesForKey(addrs, keyID: keyID) - encryptionHandler.deletePersistentData(keyID, encryptionType: self.encryptionType) - } - - private func cleanIndex(_ keyID: String) { - let index = keyID.components(separatedBy: "-")[0]+"-index" - encryptionHandler.deletePersistentData(index, encryptionType: self.encryptionType) - } - - //includes privatekeys too - func removeAllKeys() { - for keyID in privateKeys { - self.encryptionHandler.deletePersistentData(keyID, encryptionType: self.encryptionType) - } - self.privateKeys = [] - self.actualPrivateKey = nil - encryptionHandler.deletePersistentData("actualPrivateKey", encryptionType: self.encryptionType) - encryptionHandler.deletePersistentData("privateKeys", encryptionType: self.encryptionType) - let insertData = NSKeyedArchiver.archivedData(withRootObject: self.privateKeys) - encryptionHandler.addPersistentData(insertData, searchKey: "privateKeys", encryptionType: self.encryptionType) - for keyID in addresses.keys { - self.removeKey(keyID) - self.cleanIndex(keyID) - } - for keyID in privateKeys { - self.removeKey(keyID) - self.cleanIndex(keyID) - } - self.addresses = [:] - self.keyIDs = [:] - self.saveDictionarys() - } - - func printAllKeyIDs() { - print(self.addresses) - } - - func useOnlyActualPrivateKey() { - self.pgp.keys = [] - if let actual = self.actualPrivateKey { - self.pgp.keys.append(self.getKey(actual)!.key) - } - } - - //will be deactivated if new private key is added or a private key is removed - func useAllPrivateKeys() { - for key in privateKeys { - self.pgp.keys.append(self.getKey(key)!.key) - } - } - - - private func saveDictionarys(){ - var data = NSKeyedArchiver.archivedData(withRootObject: keyIDs as NSDictionary) - encryptionHandler.replacePersistentData("keyIDs", replacementData: data, encryptionType: self.encryptionType) - data = NSKeyedArchiver.archivedData(withRootObject: addresses as NSDictionary) - encryptionHandler.replacePersistentData("addresses", replacementData: data, encryptionType: self.encryptionType) - } - - private func addPrivateKey(_ key: PGPKeyWrapper) { - if key.key.type == PGPKeyType.secret { - privateKeys.append(key.keyID) - var data = NSKeyedArchiver.archivedData(withRootObject: privateKeys) - encryptionHandler.replacePersistentData("privateKeys", replacementData: data, encryptionType: self.encryptionType) - actualPrivateKey = key.keyID - data = NSKeyedArchiver.archivedData(withRootObject: actualPrivateKey!) - if encryptionHandler.hasPersistentData("actualPrivateKey", encryptionType: self.encryptionType) { - encryptionHandler.replacePersistentData("actualPrivateKey", replacementData: data, encryptionType: self.encryptionType) - } - else { - encryptionHandler.addPersistentData(data, searchKey: "actualPrivateKey", encryptionType: self.encryptionType) - } - self.useOnlyActualPrivateKey() - } - } - - private func removePrivateKey(_ keyID: String) { - if privateKeys.contains(keyID) { - privateKeys.remove(at: privateKeys.index(of: keyID)!) - actualPrivateKey = privateKeys.last - if let key = actualPrivateKey { - let data = NSKeyedArchiver.archivedData(withRootObject: key) - encryptionHandler.replacePersistentData("actualPrivateKey", replacementData: data, encryptionType: self.encryptionType) - } - else { - encryptionHandler.deletePersistentData("actualPrivateKey", encryptionType: self.encryptionType) - } - let data = NSKeyedArchiver.archivedData(withRootObject: privateKeys) - encryptionHandler.addPersistentData(data, searchKey: "privateKeys", encryptionType: self.encryptionType) - self.useOnlyActualPrivateKey() - } - } -} diff --git a/enzevalos_iphone/PGPKeyWrapper.swift b/enzevalos_iphone/PGPKeyWrapper.swift deleted file mode 100644 index 40955c80..00000000 --- a/enzevalos_iphone/PGPKeyWrapper.swift +++ /dev/null @@ -1,222 +0,0 @@ -// -// KeyWrapper.swift -// enzevalos_iphone -// -// Created by jakobsbode on 16.11.16. -// Copyright © 2016 fu-berlin. All rights reserved. -// - -import Foundation - -open class PGPKeyWrapper : NSObject, KeyWrapper { - - let key: PGPKey /*{ - set (newKey) { - oldKey = self.copy() - self.key = newKey - self.timestamp = NSDate.init() - let handler = KeyHandler.createHandler() - handler.updateKey(self) - } - get { - return self.key - } - }*/ - //TODO Referenz auf Mail, die den key geändert hat, hinzufügen - //darin befindet sich unter anderem auch, ob die ändernde Mail mit dem alten Key signiert war - //private(set) var oldKey: KeyWrapper? - - //private(set) var alternativeOldKeys: [KeyWrapper]? - - open var expireDate: Date?{ - get{ - // Expire date is not speficied for PublicKeyPacket V4. - // See: https://tools.ietf.org/html/rfc4880#section-5.5.1.1 - if let publicKey = publicKeyPacket{ - // TODO: Consider other packets? - if publicKey.v3validityPeriod <= 0{ - return nil - } - else{ - return (Calendar.current as NSCalendar).date(byAdding: .day, value: Int(publicKey.v3validityPeriod), to: publicKey.createDate, options: []) - } - } - return nil - } - } - - open var creationDate: Date{ - get{ - // TODO: Consider other packets? - if let publicKey = publicKeyPacket{ - return publicKey.createDate - } - return discoveryTime - } - } - - private var publicKeyPacket: PGPPublicKeyPacket?{ - get{ - if self.key.primaryKeyPacket.tag.rawValue == 6{ // Flag for PGPPublicKeyPacket - let primKey = self.key.primaryKeyPacket as! PGPPublicKeyPacket - return primKey - } - for k in key.allKeyPackets(){ - let keypacket = k as! PGPPacket - if keypacket.tag.rawValue == 6 { - let publicKeyPacket = keypacket as! PGPPublicKeyPacket - return publicKeyPacket - } - } - return nil - } - } - - - open var revoked: Bool{ - didSet { - self.revokeTime = Date.init() - self.keyManager.updateKey(self) - } - } - - open fileprivate(set) var revokeTime: Date? - - //choose Int8 here? - open var trustlevel: Int{ - didSet { - self.keyManager.updateKey(self) - } - } //negative misstrust; zero neutral; positive trust - - open var verified: Bool{ - didSet { - self.verifyTime = Date.init() - self.keyManager.updateKey(self) - } - } - - open fileprivate(set) var verifyTime: Date? - open let discoveryTime: Date - - //TODO - open let discoveryMailUID: UInt64? - - open let type: EncryptionType = EncryptionType.PGP - - open fileprivate(set) var keyID: String //will look like key.longKeyString+"-1" for the key with this longKeyString at index 1 - - open fileprivate(set) var fingerprint: String - - fileprivate let keyManager: PGPKeyManagement - - open var mailAddresses : [String]? { - get { - return self.keyManager.getMailAddressesForKeyID(self.keyID) - } - set(newArray) { - var added: [String] = [] - var deleted: [String] = [] - - if var arr = newArray { - if var addrs = mailAddresses { - for entry in arr { - if addrs.contains(entry){ - addrs.remove(at: addrs.index(of: entry)!) - arr.remove(at: arr.index(of: entry)!) - } - } - deleted = addrs - } - added = arr - } - else { - if let addrs = mailAddresses { - deleted = addrs - } - } - keyManager.addMailAddressesForKey(added, keyID: self.keyID) - keyManager.removeMailAddressesForKey(deleted, keyID: self.keyID) - } - } - - //TODO - //KeyIDs from previous keys, that signed the actual key - //public var predecessorsKeyID: [String]? - - open var mailAddressesInKey: [String]? { - get { - var array: [String] = [] - for user:PGPUser in key.users as NSArray as! [PGPUser]{ - array.append(user.userID) - } - if array == [] { - return nil - } - return array - } - } - - init(key: PGPKey, mailAddresses: [String], discoveryMailUID: UInt64?, keyManager: PGPKeyManagement){ - self.key = key - self.keyManager = keyManager - self.discoveryTime = Date.init() - self.discoveryMailUID = discoveryMailUID - self.keyID = "" - - if let keyPacket = (key.primaryKeyPacket as? PGPPublicKeyPacket), let fp = keyPacket.fingerprint { - self.fingerprint = fp.description() - } - else { - self.fingerprint = "Error" //TODO: find a secure way - } - revoked = false - trustlevel = 0 - verified = false - super.init() - - self.keyManager.addKey(self, forMailAddresses: mailAddresses) - } - - required public init(coder: NSCoder){ - let enc : PGPEncryption = EnzevalosEncryptionHandler.getEncryption(self.type)! as! PGPEncryption - keyManager = (enc as PGPEncryption).getPGPKeyManagement()//coder.decodeObjectForKey("keyManager") as! PGPKeyManagement - key = keyManager.pgp.keys(from: coder.decodeObject(forKey: "key") as! Data)![0] - revoked = coder.decodeBool(forKey: "revoked") - revokeTime = coder.decodeObject(forKey: "revokeTime") as! Date? - trustlevel = coder.decodeInteger(forKey: "trustlevel") - verified = coder.decodeBool(forKey: "verified") - verifyTime = coder.decodeObject(forKey: "verifyTime") as! Date? - keyID = coder.decodeObject(forKey: "keyID") as! String - fingerprint = coder.decodeObject(forKey: "fingerprint") as! String - if let dmailUID = coder.decodeObject(forKey: "discoveryMailUID"){ - self.discoveryMailUID = (dmailUID as! NSNumber).uint64Value - } - else { - self.discoveryMailUID = nil - } - discoveryTime = coder.decodeObject(forKey: "discoveryTime") as! Date - } - - open func setOnceKeyID (_ keyID: String) { - if self.keyID == "" { - self.keyID = keyID - } - } - - open func encodeWithCoder(_ coder: NSCoder){ - coder.encode((try? key.export())!, forKey: "key") - coder.encode(revoked, forKey: "revoked") - coder.encode(revokeTime, forKey: "revokeTime") - coder.encode(trustlevel, forKey: "trustlevel") - coder.encode(verified, forKey: "verified") - coder.encode(verifyTime, forKey: "verifyTime") - if let dmailUID = discoveryMailUID { - coder.encode(NSNumber.init(value: dmailUID as UInt64), forKey: "discoveryMailUID") - } - coder.encode(keyID, forKey: "keyID") - coder.encode(fingerprint, forKey: "fingerprint") - coder.encode(discoveryTime, forKey: "discoveryTime") - } - -} diff --git a/enzevalos_iphone/PGPTemporaryDecryptionObject.h b/enzevalos_iphone/PGPTemporaryDecryptionObject.h deleted file mode 100644 index 8e25ee9b..00000000 --- a/enzevalos_iphone/PGPTemporaryDecryptionObject.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// PGPTemporaryDecryptionObject.h -// enzevalos_iphone -// -// Created by jakobsbode on 16.02.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -#import "PGPOnePassSignaturePacket.h" -#import "PGPSignaturePacket.h" - -@interface PGPTemporaryDecryptionObject : NSObject - -@property (readonly, nullable) PGPOnePassSignaturePacket *onePassSignaturePacket; -@property (readonly, nullable) NSString *incompleteKeyID; -@property (readonly, nullable) PGPSignaturePacket *signaturePacket; -@property (readonly, nullable) NSData *plaintextData; - -- (nonnull instancetype)init:(nullable PGPSignaturePacket *)signaturePacket plaintextData:(nullable NSData *)plaintextData; - -@end diff --git a/enzevalos_iphone/PGPTemporaryDecryptionObject.m b/enzevalos_iphone/PGPTemporaryDecryptionObject.m deleted file mode 100644 index a8688614..00000000 --- a/enzevalos_iphone/PGPTemporaryDecryptionObject.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// PGPTemporaryDecryptionObject.m -// enzevalos_iphone -// -// Created by jakobsbode on 16.02.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - -//#import <Foundation/Foundation.h> -#import "PGPTemporaryDecryptionObject.h" - -@implementation PGPTemporaryDecryptionObject - -- (instancetype)init:(PGPSignaturePacket*)signaturePacket plaintextData:(NSData *)plaintextData -{ - self->_signaturePacket = signaturePacket; - self->_plaintextData = plaintextData; - if (signaturePacket != nil) { - self->_incompleteKeyID = signaturePacket.issuerKeyID.longKeyString; - }else { - self->_incompleteKeyID = nil; - } - - return self; -} - -@end diff --git a/enzevalos_iphone/PGPTemporaryDecryptionObject.swift b/enzevalos_iphone/PGPTemporaryDecryptionObject.swift deleted file mode 100644 index dffe1418..00000000 --- a/enzevalos_iphone/PGPTemporaryDecryptionObject.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// PGPTemporaryDecryptionObject.swift -// enzevalos_iphone -// -// Created by jakobsbode on 09.02.17. -// Copyright © 2017 fu-berlin. All rights reserved. -// - - -class PGPTemporaryDecryptionObject { - let onePassSignaturePacket: PGPOnePassSignaturePacket - let signaturePacket: PGPSignaturePacket - let plaintextData: Data? - - init(onePassSignaturePacket: PGPOnePassSignaturePacket, signaturePacket: PGPSignaturePacket, plaintextData: Data?){ - self.onePassSignaturePacket = onePassSignaturePacket - self.signaturePacket = signaturePacket - self.plaintextData = plaintextData - } - -} diff --git a/enzevalos_iphone/SwiftPGP.swift b/enzevalos_iphone/SwiftPGP.swift new file mode 100644 index 00000000..56b8f594 --- /dev/null +++ b/enzevalos_iphone/SwiftPGP.swift @@ -0,0 +1,179 @@ +// +// SwiftPGP.swift +// ObjectivePGP +// +// Created by Oliver Wiese on 25.09.17. +// Copyright © 2017 Marcin Krzyżanowski. All rights reserved. +// + +import Foundation +import Security +import KeychainAccess + +class SwiftPGP: Encryption{ + + let cryptoScheme = CryptoScheme.PGP + + private var keychain: Keychain{ + get{ + return Keychain(service: "Enzevalos/PGP") + } + + } + + private func storeKey(key: PGPKey) -> String{ + let id = key.keyID.longKeyString + let data = try! key.export() + let testData = try? keychain.getData(id) + if let tmp = testData, tmp == nil { + keychain[data: id] = data + } + return id + } + + private func loadKey(id: String) -> PGPKey?{ + do{ + if let data = try keychain.getData(id){ + let pgp = ObjectivePGP() + let keys = pgp.keys(from: data) + if let key = keys.first{ + return key + } + } + } catch{ + return nil + } + return nil + } + + func generateKey(adr: String) -> String{ + let gen = PGPKeyGenerator() + let key = gen.generate(for: adr, passphrase: nil) + return storeKey(key: key) + } + + func importKeys(key: String, isSecretKey: Bool, autocrypt: Bool) -> [String]{ + let pgp = ObjectivePGP() + var ids = [String]() + // TODO: Autocrypt! + if let data = key.data(using: .utf8){ + let keys = pgp.importKeys(from: data) //.base64EncodedData() + for k in keys{ + if k.isSecret && isSecretKey || !k.isSecret && !isSecretKey{ + ids.append(storeKey(key: k)) + } + } + } + return ids + } + func exportKey(id: String, isSecretkey isSecretKey: Bool, autocrypt: Bool) -> String?{ + let pgp = ObjectivePGP() + if var key = loadKey(id: id){ + if key.isSecret && !isSecretKey{ + let pk = try! key.export(PGPPartialKeyType.public, error: ()) + let keys = pgp.keys(from: pk) + if (keys.count > 0){ + key = keys.first! + } + else{ + return nil + } + } + if autocrypt{ + if let data = pgp.export(key, armored: false){ + return data.base64EncodedString() + } + } + else{ + if let data = pgp.export(key, armored: true){ + return data.base64EncodedString() + } + } + } + return nil + } + + + func encrypt(plaintext: String, ids: [String], myId: String) -> CryptoObject{ + let pgp = ObjectivePGP() + var keys = [PGPKey]() + let signKey = loadKey(id: myId) + for id in ids{ + if let key = loadKey(id: id){ + keys.append(key) + } + } + if let data = plaintext.data(using: String.Encoding.utf8){ + do{ + let chipher = try pgp.encryptData(data, using: keys, signWith: signKey, passphrase: nil, armored: true) + return CryptoObject(chiphertext: chipher, plaintext: plaintext, sigState: SignatureState.ValidSignature, encState: EncryptionState.ValidedEncryptedWithCurrentKey, signKey: myId, encType: CryptoScheme.PGP) + } catch { + print("Encryption error!") //TODO: Error handling! + } + } + return CryptoObject(chiphertext: nil, plaintext: nil, sigState: SignatureState.InvalidSignature, encState: EncryptionState.UnableToDecrypt, signKey: nil, encType: cryptoScheme) + + } + func decrypt(data: Data,decryptionId: String, verifyIds: [String]) -> CryptoObject{ + let pgp = ObjectivePGP() + + //has to be var because it is given as pointer to obj-c-code + var signed = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1) + signed[0] = false + //has to be var because it is given as pointer to obj-c-code + var valid = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1) + valid[0] = false + + var plaindata: Data? = nil + var sigState = SignatureState.NoSignature + var encState = EncryptionState.UnableToDecrypt //TODO: More decryption keys? + var sigKey: String? = nil + + if let decKey = loadKey(id: decryptionId){ + pgp.importKeys(Set([decKey])) + } + else{ + return CryptoObject(chiphertext: data, plaintext: nil, sigState: SignatureState.NoSignature, encState: EncryptionState.UnableToDecrypt, signKey: nil, encType: CryptoScheme.PGP) + } + + + for id in verifyIds{ + let key = loadKey(id: id) + do{ + plaindata = try pgp.decryptData(data, passphrase: nil, verifyWith: key, signed: signed, valid: valid, integrityProtected: nil) + encState = EncryptionState.ValidedEncryptedWithCurrentKey + if !signed.pointee.boolValue{ + break + } + else if signed.pointee.boolValue && valid.pointee.boolValue{ + sigState = SignatureState.ValidSignature + sigKey = id + break + } + else{ + sigState = SignatureState.InvalidSignature + } + }catch{ + encState = EncryptionState.UnableToDecrypt + sigState = SignatureState.InvalidSignature + break + } + } + + if encState == EncryptionState.UnableToDecrypt{ + do{ + plaindata = try pgp.decryptData(data, passphrase: nil) + encState = EncryptionState.ValidedEncryptedWithCurrentKey + sigState = SignatureState.InvalidSignature + }catch{ + encState = EncryptionState.UnableToDecrypt + } + } + + var plaintext: String? = nil + if plaindata != nil{ + plaintext = plaindata?.base64EncodedString() + } + return CryptoObject(chiphertext: data, plaintext: plaintext , sigState: sigState, encState: encState, signKey: sigKey, encType: CryptoScheme.PGP) + } +} diff --git a/enzevalos_iphone/enzevalos_iphone-Bridging-Header.h b/enzevalos_iphone/enzevalos_iphone-Bridging-Header.h index 3e625eaf..e3b773a0 100644 --- a/enzevalos_iphone/enzevalos_iphone-Bridging-Header.h +++ b/enzevalos_iphone/enzevalos_iphone-Bridging-Header.h @@ -7,13 +7,7 @@ // #import <MailCore/MailCore.h> -//#import <BZipCompression/BZipCompression.h> #import <Onboard/OnboardingViewController.h> #import <Onboard/OnboardingContentViewController.h> -#import "ObjectivePGP.h" -#import "PGPOnePassSignaturePacket.h" -#import "PGPSignaturePacket.h" -#import "PGPKeyID.h" -#import "PGPPublicKeyPacket.h" -#import "UNNetPGP.h" -#import "PGPSecretKeyPacket.h" +#import "ObjectivePGP/ObjectivePGP.h" + -- GitLab