diff --git a/.gitignore b/.gitignore index aaea0fe..e1c91f2 100644 --- a/.gitignore +++ b/.gitignore @@ -58,7 +58,6 @@ go/bin/ go/dist/ go/pkg/ go/src/* -!go/src/gopenpgpwrapper # fastlane # diff --git a/.travis.yml b/.travis.yml index 2707609..1538035 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ before_script: travis_wait 45 carthage bootstrap --platform iOS fi - | - if [ ! $(git diff --name-only "$TRAVIS_COMMIT_RANGE" | grep -E "gopenpgp_build.sh|gopenpgpwrapper.go") ] && [ -d "go/dist/Gopenpgpwrapper.framework" ]; then + if [ ! $(git diff --name-only "$TRAVIS_COMMIT_RANGE" | grep -E "gopenpgp_build.sh|gopenpgpwrapper.go") ] && [ -d "go/dist/Crypto.framework" ]; then echo "Use cached go dependencies." ls -ld go/dist/*framework else diff --git a/go/src/gopenpgpwrapper/gopenpgpwrapper.go b/go/src/gopenpgpwrapper/gopenpgpwrapper.go deleted file mode 100644 index cf96b08..0000000 --- a/go/src/gopenpgpwrapper/gopenpgpwrapper.go +++ /dev/null @@ -1,88 +0,0 @@ -package gopenpgpwrapper - -import ( - "bytes" - "io" - "io/ioutil" - - "github.com/ProtonMail/gopenpgp/crypto" - "github.com/ProtonMail/gopenpgp/armor" -) - -type Key struct { - kr crypto.KeyRing -} - -func (k *Key) GetKeyID() string { - if len(k.kr.GetEntities()) > 0 { - return k.kr.GetEntities()[0].PrimaryKey.KeyIdShortString() - } else { - return "" - } -} - -func (k *Key) Encrypt(plaintext []byte, armor bool) []byte { - var b bytes.Buffer - var w io.WriteCloser - if armor { - wr, err := k.kr.EncryptArmored(&b, nil) - if err != nil { - return nil - } - w = wr - } else { - wr, err := k.kr.Encrypt(&b, nil, "", false) - if err != nil { - return nil - } - - w = wr - } - - if _, err := w.Write(plaintext); err != nil { - return nil - } - - if err := w.Close(); err != nil { - return nil - } - - return b.Bytes() -} - -func (k Key) Decrypt(ciphertext []byte, passphrase string) []byte { - unarmored, err := armor.Unarmor(string(ciphertext)) - if err != nil { - // Assume ciphertext is already in binary format - unarmored = ciphertext - } - - err = k.kr.Unlock([]byte(passphrase)) - if err != nil { - return nil - } - - r, _, err := k.kr.Decrypt(bytes.NewReader(unarmored)) - if err != nil { - return nil - } - - if b, err := ioutil.ReadAll(r); err != nil { - return nil - } else { - return b - } -} - -func ReadKey(data []byte) *Key { - kr, err := crypto.ReadArmoredKeyRing(bytes.NewReader(data)) - if err != nil { - // Assume keyring is in binary form - kr, err = crypto.ReadKeyRing(bytes.NewReader(data)) - if err != nil { - return nil - } - } - - return &Key{kr: *kr} -} diff --git a/gopenpgp_build.sh b/gopenpgp_build.sh index 59f3cf8..13ec7f3 100755 --- a/gopenpgp_build.sh +++ b/gopenpgp_build.sh @@ -3,6 +3,7 @@ OLDGOPATH=$GOPATH OLDPATH=$PATH +mkdir go export GOPATH=$(pwd)/go go get -u golang.org/x/mobile/cmd/gomobile @@ -13,19 +14,17 @@ go get -u github.com/ProtonMail/gopenpgp cd $GOPATH/src/github.com/ProtonMail/gopenpgp -git fetch && git fetch --tags - -git checkout v0 - GO111MODULE=on go mod vendor -git checkout v1.0.0 - cd $GOPATH export PATH=$PATH:$GOPATH/bin mkdir dist -$GOPATH/bin/gomobile bind -v -ldflags="-s -w" -target ios -o dist/Gopenpgpwrapper.framework gopenpgpwrapper +OUTPUT_PATH="dist" +PACKAGE_PATH=github.com/ProtonMail/gopenpgp + +$GOPATH/bin/gomobile bind -target ios -o ${OUTPUT_PATH}/Crypto.framework $PACKAGE_PATH/crypto $PACKAGE_PATH/armor $PACKAGE_PATH/constants $PACKAGE_PATH/models $PACKAGE_PATH/subtle + export GOPATH=$OLDGOPATH export PATH=$OLDPATH diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 87d3997..744b0e5 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 116F7CC922E134FA003B3BAC /* Crypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 116F7CC822E134FA003B3BAC /* Crypto.framework */; }; + 116F7CCA22E134FA003B3BAC /* Crypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 116F7CC822E134FA003B3BAC /* Crypto.framework */; }; 300713C52219D54100F553AC /* AutoCellHeightUITableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300713C42219D54100F553AC /* AutoCellHeightUITableViewController.swift */; }; 301F6463216162550071A4CE /* AdditionField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 301F6462216162550071A4CE /* AdditionField.swift */; }; 301F6468216165290071A4CE /* ConstantsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 301F6467216165290071A4CE /* ConstantsTest.swift */; }; @@ -71,7 +73,6 @@ 556EC3DA22335D3400934F9C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 30C25DBF21F3599E00BB27BB /* InfoPlist.strings */; }; 556EC3DB22335D3D00934F9C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 30C25DBF21F3599E00BB27BB /* InfoPlist.strings */; }; 8BA607EB4C9C8258741AC18C /* Pods_passExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E955B67C88672AA3A40BA0 /* Pods_passExtension.framework */; }; - 9A714BD022AC61170020C3BB /* Gopenpgpwrapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1154BEDB229AC00F00454075 /* Gopenpgpwrapper.framework */; }; 9A8A8387402FCCCECB1232A4 /* Pods_passKitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B2B2F844061EFA534FE9506 /* Pods_passKitTests.framework */; }; A20691F41F2A3D0E0096483D /* SecurePasteboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20691F31F2A3D0E0096483D /* SecurePasteboard.swift */; }; A217ACE41E9BBBBD00A1A6CF /* GitConfigSettingTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A217ACE31E9BBBBD00A1A6CF /* GitConfigSettingTableViewController.swift */; }; @@ -215,7 +216,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 1154BEDB229AC00F00454075 /* Gopenpgpwrapper.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Gopenpgpwrapper.framework; path = go/dist/Gopenpgpwrapper.framework; sourceTree = ""; }; + 116F7CC822E134FA003B3BAC /* Crypto.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crypto.framework; path = go/dist/Crypto.framework; sourceTree = ""; }; 134DA5B66070BA56678688CF /* Pods_passKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_passKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 14E955B67C88672AA3A40BA0 /* Pods_passExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_passExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 300713C42219D54100F553AC /* AutoCellHeightUITableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCellHeightUITableViewController.swift; sourceTree = ""; }; @@ -378,8 +379,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9A714BD022AC61170020C3BB /* Gopenpgpwrapper.framework in Frameworks */, E813E400BBF3E7E8975EBAEF /* Pods_passKit.framework in Frameworks */, + 116F7CCA22E134FA003B3BAC /* Crypto.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -418,6 +419,7 @@ buildActionMask = 2147483647; files = ( A239F5902158C07D00576CBF /* AuthenticationServices.framework in Frameworks */, + 116F7CC922E134FA003B3BAC /* Crypto.framework in Frameworks */, A260758D1EEC6F34005DB03E /* passKit.framework in Frameworks */, DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */, 3EA2386CD0E9CE2A702A0B3E /* Pods_pass.framework in Frameworks */, @@ -774,11 +776,11 @@ DC1208571E35EBE60042942E /* ObjectiveGit.framework */, DCA049951E3357E000522E8F /* SwiftyUserDefaults.framework */, DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */, - 1154BEDB229AC00F00454075 /* Gopenpgpwrapper.framework */, FE627E8F3DACEDD8FA220081 /* Pods_pass.framework */, 14E955B67C88672AA3A40BA0 /* Pods_passExtension.framework */, 134DA5B66070BA56678688CF /* Pods_passKit.framework */, 3B2B2F844061EFA534FE9506 /* Pods_passKitTests.framework */, + 116F7CC822E134FA003B3BAC /* Crypto.framework */, ); name = Frameworks; sourceTree = ""; diff --git a/passKit/Models/PGPAgent.swift b/passKit/Models/PGPAgent.swift index 871cebe..f32ae6a 100644 --- a/passKit/Models/PGPAgent.swift +++ b/passKit/Models/PGPAgent.swift @@ -9,7 +9,7 @@ import Foundation import ObjectivePGP import KeychainAccess -import Gopenpgpwrapper +import Crypto public class PGPAgent { @@ -31,12 +31,18 @@ public class PGPAgent { } // Gopenpgpwrapper - private var publicKey: GopenpgpwrapperKey? { + private var publicKey: CryptoKeyRing? { didSet { - pgpKeyID = publicKey?.getID() + var err: NSError? = nil + let fp = publicKey?.getFingerprint(&err) + if err == nil && fp != nil { + pgpKeyID = String(fp!.suffix(8)).uppercased() + } else { + pgpKeyID = "" + } } } - private var privateKey: GopenpgpwrapperKey? + private var privateKey: CryptoKeyRing? // ObjectivePGP private let keyring = ObjectivePGP.defaultKeyring private var publicKeyV2: Key? { @@ -81,8 +87,23 @@ public class PGPAgent { // Remove the key data from keychain temporary, in case the following step crashes repeatedly. keyStore.removeContent(for: keyType.getKeychainKey()) - // Try GopenpgpwrapperReadKey first. - if let key = GopenpgpwrapperReadKey(pgpKeyData) { + // Try GopenPGP first. + let pgp = CryptoGetGopenPGP() + + // Treat keys as binary first + if let key = try? pgp?.buildKeyRing(pgpKeyData) { + switch keyType { + case .PUBLIC: + self.publicKey = key + case .PRIVATE: + self.privateKey = key + } + keyStore.add(data: pgpKeyData, for: keyType.getKeychainKey()) + return + } + + // Treat key as ASCII armored keys if binary fails + if let key = try? pgp?.buildKeyRingArmored(String(data: pgpKeyData, encoding: .ascii)) { switch keyType { case .PUBLIC: self.publicKey = key @@ -136,8 +157,16 @@ public class PGPAgent { let passphrase = self.passphrase ?? requestPGPKeyPassphrase() // Try Gopenpgp. if privateKey != nil { - if let decryptedData = privateKey?.decrypt(encryptedData, passphrase: passphrase) { - return decryptedData + try privateKey?.unlock(withPassphrase: passphrase) + + var err : NSError? = nil + var message = CryptoNewPGPMessageFromArmored(String(data: encryptedData, encoding: .ascii), &err) + if err != nil { + message = CryptoNewPGPMessage(encryptedData) + } + + if let decryptedData = try? privateKey?.decrypt(message, verifyKey: nil, verifyTime: 0) { + return decryptedData.data } } // Try ObjectivePGP. @@ -155,10 +184,19 @@ public class PGPAgent { } // Try Gopenpgp. if publicKey != nil { - if let encryptedData = publicKey?.encrypt(plainData, armor: SharedDefaults[.encryptInArmored]) { - return encryptedData + if let encryptedData = try? publicKey?.encrypt(CryptoNewPlainMessageFromString(String(data: plainData, encoding: .utf8)), privateKey: nil) { + if SharedDefaults[.encryptInArmored] { + var err : NSError? = nil + let armor = encryptedData.getArmored(&err) + if err == nil { + return armor.data(using: .ascii)! + } + } else { + return encryptedData.getBinary()! + } } } + // Try ObjectivePGP. if publicKeyV2 != nil { if let encryptedData = try? ObjectivePGP.encrypt(plainData, addSignature: false, using: keyring.keys, passphraseForKey: nil) {