From 2bf2d4b4fc8a62a04455e48ecbfda474ce7ead6f Mon Sep 17 00:00:00 2001 From: Andrew Arpasi Date: Fri, 8 Aug 2014 12:35:06 -0400 Subject: [PATCH] Version 2.0.0 Final --- DogeKeeper.xcodeproj/project.pbxproj | 102 +- .../xcshareddata/DogeKeeper.xccheckout | 41 + .../UserInterfaceState.xcuserstate | Bin 66560 -> 21465 bytes DogeKeeper/AESCrypt/.gitignore | 15 + DogeKeeper/AESCrypt/AESCrypt.h | 37 + DogeKeeper/AESCrypt/AESCrypt.m | 50 + DogeKeeper/AESCrypt/LICENSE | 22 + DogeKeeper/AESCrypt/NSData+Base64.h | 17 + DogeKeeper/AESCrypt/NSData+Base64.m | 110 +++ DogeKeeper/AESCrypt/NSData+CommonCrypto.h | 112 +++ DogeKeeper/AESCrypt/NSData+CommonCrypto.m | 546 +++++++++++ DogeKeeper/AESCrypt/NSString+Base64.h | 15 + DogeKeeper/AESCrypt/NSString+Base64.m | 82 ++ DogeKeeper/AESCrypt/README.md | 57 ++ DogeKeeper/AboutViewController.m | 4 + DogeKeeper/AddWalletViewController.m | 1 - DogeKeeper/AnnouncementHandler.h | 21 + DogeKeeper/AnnouncementHandler.m | 61 ++ DogeKeeper/AnnouncementViewController.h | 16 + DogeKeeper/AnnouncementViewController.m | 61 ++ DogeKeeper/AppDelegate.h | 1 - DogeKeeper/Base.lproj/Main_iPhone.storyboard | 887 +++++++++++------- DogeKeeper/BlockIOHandler.h | 29 + DogeKeeper/BlockIOHandler.m | 256 +++++ ...iewController.h => BlockIoKeyController.h} | 12 +- ...iewController.m => BlockIoKeyController.m} | 46 +- DogeKeeper/DogeAPIHandler.h | 32 - DogeKeeper/DogeAPIHandler.m | 269 ------ DogeKeeper/DogeChainHandler.h | 2 + DogeKeeper/DogeChainHandler.m | 15 +- DogeKeeper/DogeKeeper-Info.plist | 4 +- DogeKeeper/DogeTransaction.h | 1 + DogeKeeper/DogeTransaction.m | 4 +- DogeKeeper/DogeViewController.h | 3 +- DogeKeeper/DogeViewController.m | 114 ++- DogeKeeper/ExchangeViewController.h | 13 + DogeKeeper/ExchangeViewController.m | 49 + DogeKeeper/HistoryViewController.m | 2 +- .../Lock.imageset/Contents.json | 18 + .../Lock.imageset/rsz_1rsz_lock-100.png | Bin 0 -> 718 bytes .../Lock.imageset/rsz_lock-100.png | Bin 0 -> 1130 bytes .../Megaphone.imageset/Contents.json | 18 + .../Megaphone.imageset/mp30.png | Bin 0 -> 889 bytes .../Megaphone.imageset/mp60.png | Bin 0 -> 1585 bytes DogeKeeper/MainViewController.m | 2 +- DogeKeeper/SendViewController.h | 2 +- DogeKeeper/SendViewController.m | 64 +- DogeKeeper/SettingsViewController.h | 11 +- DogeKeeper/SettingsViewController.m | 54 +- .../TransactionCompleteViewController.h | 1 + .../TransactionCompleteViewController.m | 3 +- DogeKeeper/WalletDetailViewController.h | 4 +- DogeKeeper/WalletDetailViewController.m | 35 +- DogeKeeper/bar-128.png | Bin 772 -> 0 bytes DogeKeeper/lock-32.png | Bin 0 -> 560 bytes DogeKeeper/mp30.png | Bin 0 -> 889 bytes DogeKeeper/mp60.png | Bin 0 -> 1585 bytes ExchangeRateViewController.h | 21 + ExchangeRateViewController.m | 185 ++++ PriceHandler.h | 16 + PriceHandler.m | 43 + TransactionDetalViewController.h | 24 + TransactionDetalViewController.m | 65 ++ WalletListController.h | 2 + WalletListController.m | 36 +- WelcomeViewController.m | 4 +- 66 files changed, 2828 insertions(+), 889 deletions(-) create mode 100644 DogeKeeper.xcodeproj/project.xcworkspace/xcshareddata/DogeKeeper.xccheckout create mode 100755 DogeKeeper/AESCrypt/.gitignore create mode 100755 DogeKeeper/AESCrypt/AESCrypt.h create mode 100755 DogeKeeper/AESCrypt/AESCrypt.m create mode 100755 DogeKeeper/AESCrypt/LICENSE create mode 100755 DogeKeeper/AESCrypt/NSData+Base64.h create mode 100755 DogeKeeper/AESCrypt/NSData+Base64.m create mode 100755 DogeKeeper/AESCrypt/NSData+CommonCrypto.h create mode 100755 DogeKeeper/AESCrypt/NSData+CommonCrypto.m create mode 100755 DogeKeeper/AESCrypt/NSString+Base64.h create mode 100755 DogeKeeper/AESCrypt/NSString+Base64.m create mode 100755 DogeKeeper/AESCrypt/README.md create mode 100644 DogeKeeper/AnnouncementHandler.h create mode 100644 DogeKeeper/AnnouncementHandler.m create mode 100644 DogeKeeper/AnnouncementViewController.h create mode 100644 DogeKeeper/AnnouncementViewController.m create mode 100644 DogeKeeper/BlockIOHandler.h create mode 100644 DogeKeeper/BlockIOHandler.m rename DogeKeeper/{ApiKeyViewController.h => BlockIoKeyController.h} (57%) rename DogeKeeper/{ApiKeyViewController.m => BlockIoKeyController.m} (69%) delete mode 100644 DogeKeeper/DogeAPIHandler.h delete mode 100644 DogeKeeper/DogeAPIHandler.m create mode 100644 DogeKeeper/ExchangeViewController.h create mode 100644 DogeKeeper/ExchangeViewController.m create mode 100644 DogeKeeper/Images.xcassets/Lock.imageset/Contents.json create mode 100644 DogeKeeper/Images.xcassets/Lock.imageset/rsz_1rsz_lock-100.png create mode 100644 DogeKeeper/Images.xcassets/Lock.imageset/rsz_lock-100.png create mode 100644 DogeKeeper/Images.xcassets/Megaphone.imageset/Contents.json create mode 100644 DogeKeeper/Images.xcassets/Megaphone.imageset/mp30.png create mode 100644 DogeKeeper/Images.xcassets/Megaphone.imageset/mp60.png delete mode 100644 DogeKeeper/bar-128.png create mode 100755 DogeKeeper/lock-32.png create mode 100644 DogeKeeper/mp30.png create mode 100644 DogeKeeper/mp60.png create mode 100644 ExchangeRateViewController.h create mode 100644 ExchangeRateViewController.m create mode 100644 PriceHandler.h create mode 100644 PriceHandler.m create mode 100644 TransactionDetalViewController.h create mode 100644 TransactionDetalViewController.m diff --git a/DogeKeeper.xcodeproj/project.pbxproj b/DogeKeeper.xcodeproj/project.pbxproj index 7e35330..2a7d342 100644 --- a/DogeKeeper.xcodeproj/project.pbxproj +++ b/DogeKeeper.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 490B0DD41988384000154F92 /* AnnouncementViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 490B0DD31988384000154F92 /* AnnouncementViewController.m */; }; + 490B0DDA19883A0400154F92 /* AnnouncementHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 490B0DD919883A0400154F92 /* AnnouncementHandler.m */; }; 4911D6371926F25C009B9C5B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4911D6361926F25C009B9C5B /* Foundation.framework */; }; 4911D6391926F25C009B9C5B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4911D6381926F25C009B9C5B /* CoreGraphics.framework */; }; 4911D63B1926F25C009B9C5B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4911D63A1926F25C009B9C5B /* UIKit.framework */; }; @@ -20,9 +22,10 @@ 4911D65E1926F25D009B9C5B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4911D63A1926F25C009B9C5B /* UIKit.framework */; }; 4911D6661926F25D009B9C5B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4911D6641926F25D009B9C5B /* InfoPlist.strings */; }; 4911D6681926F25D009B9C5B /* DogeKeeperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4911D6671926F25D009B9C5B /* DogeKeeperTests.m */; }; - 4911D6731926FA5F009B9C5B /* DogeAPIHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 4911D6721926FA5F009B9C5B /* DogeAPIHandler.m */; }; 4911D6781927090B009B9C5B /* dogecoind.png in Resources */ = {isa = PBXBuildFile; fileRef = 4911D6771927090B009B9C5B /* dogecoind.png */; }; - 493BF7A2196E2F0F00947A05 /* EncryptionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 493BF7A1196E2F0F00947A05 /* EncryptionHelper.m */; }; + 4919796D19897DFE00147FC9 /* ExchangeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4919796C19897DFE00147FC9 /* ExchangeViewController.m */; }; + 4919797019897FED00147FC9 /* ExchangeRateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4919796F19897FED00147FC9 /* ExchangeRateViewController.m */; }; + 491979731989807600147FC9 /* PriceHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 491979721989807600147FC9 /* PriceHandler.m */; }; 493BF7A4196E305000947A05 /* lock-32.png in Resources */ = {isa = PBXBuildFile; fileRef = 493BF7A3196E305000947A05 /* lock-32.png */; }; 4940B91A196CE84C008D95CE /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = 4940B90F196CE84C008D95CE /* .gitignore */; }; 4940B91B196CE84C008D95CE /* AESCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = 4940B911196CE84C008D95CE /* AESCrypt.m */; }; @@ -39,18 +42,15 @@ 49448D601946913200765F66 /* BCScannerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49448D5F1946913200765F66 /* BCScannerViewController.m */; }; 49448D64194693F100765F66 /* BCVideoPreviewView.m in Sources */ = {isa = PBXBuildFile; fileRef = 49448D63194693F100765F66 /* BCVideoPreviewView.m */; }; 49448D6A19469ED500765F66 /* WalletListController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49448D6919469ED500765F66 /* WalletListController.m */; }; + 4946E687198448A20039888F /* BlockIOHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 4946E686198448A20039888F /* BlockIOHandler.m */; }; 494C4C79192C1D8500545434 /* AddWalletViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 494C4C78192C1D8500545434 /* AddWalletViewController.m */; }; 494C4C7C192C1D8F00545434 /* DogeChainHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 494C4C7B192C1D8F00545434 /* DogeChainHandler.m */; }; 494C4C7F192C1D9A00545434 /* DogecoinWallet.m in Sources */ = {isa = PBXBuildFile; fileRef = 494C4C7E192C1D9A00545434 /* DogecoinWallet.m */; }; - 49521D83196F204A00BFCF95 /* PassViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49521D82196F204A00BFCF95 /* PassViewController.m */; }; - 4952F46C1970D89400FE9D96 /* Graveyard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4952F46B1970D89400FE9D96 /* Graveyard.storyboard */; }; - 49606ECF19299A33005072D2 /* ApiKeyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49606ECE19299A33005072D2 /* ApiKeyViewController.m */; }; 4975EA31192D77D600D136A9 /* TransactionCompleteViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4975EA30192D77D600D136A9 /* TransactionCompleteViewController.m */; }; 498D03031943E731004BC0B0 /* dknobg.png in Resources */ = {isa = PBXBuildFile; fileRef = 498D03021943E731004BC0B0 /* dknobg.png */; }; 498D03061943E963004BC0B0 /* AboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 498D03051943E963004BC0B0 /* AboutViewController.m */; }; 499705D91927D6CE00C53D78 /* DogeTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 499705D81927D6CE00C53D78 /* DogeTransaction.m */; }; 499705DC1927D9DF00C53D78 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 499705DB1927D9DF00C53D78 /* MainViewController.m */; }; - 499705DF1927DE4C00C53D78 /* ExchangeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 499705DE1927DE4C00C53D78 /* ExchangeViewController.m */; }; 499705E21927DFFE00C53D78 /* WelcomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 499705E11927DFFE00C53D78 /* WelcomeViewController.m */; }; 499705E51927E06100C53D78 /* WalletsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 499705E41927E06100C53D78 /* WalletsViewController.m */; }; 499705E81927E78000C53D78 /* SendViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 499705E71927E78000C53D78 /* SendViewController.m */; }; @@ -58,6 +58,8 @@ 49A1CB66192AD8EE00D4EA5F /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49A1CB65192AD8EE00D4EA5F /* SettingsViewController.m */; }; 49B82A1A194CE0FD00B9B4B6 /* HistoryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49B82A19194CE0FD00B9B4B6 /* HistoryViewController.m */; }; 49B82A20194CED2100B9B4B6 /* WalletDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49B82A1F194CED2100B9B4B6 /* WalletDetailViewController.m */; }; + 49D0BBD1198AC08700945096 /* mp30.png in Resources */ = {isa = PBXBuildFile; fileRef = 49D0BBCF198AC08700945096 /* mp30.png */; }; + 49D0BBD2198AC08700945096 /* mp60.png in Resources */ = {isa = PBXBuildFile; fileRef = 49D0BBD0198AC08700945096 /* mp60.png */; }; 49DDD478194E026200C3C6FD /* bitstream.c in Sources */ = {isa = PBXBuildFile; fileRef = 49DDD468194E026200C3C6FD /* bitstream.c */; }; 49DDD479194E026200C3C6FD /* mask.c in Sources */ = {isa = PBXBuildFile; fileRef = 49DDD46A194E026200C3C6FD /* mask.c */; }; 49DDD47A194E026200C3C6FD /* qrencode.c in Sources */ = {isa = PBXBuildFile; fileRef = 49DDD46C194E026200C3C6FD /* qrencode.c */; }; @@ -75,6 +77,7 @@ 49DDD48D194E80DD00C3C6FD /* settings-32.png in Resources */ = {isa = PBXBuildFile; fileRef = 49DDD48C194E80DD00C3C6FD /* settings-32.png */; }; 49DDD48F194E811000C3C6FD /* line_chart-32.png in Resources */ = {isa = PBXBuildFile; fileRef = 49DDD48E194E811000C3C6FD /* line_chart-32.png */; }; 49E381D5194B83AE00E38558 /* donate.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 49E381D4194B83AD00E38558 /* donate.jpeg */; }; + 49FCD6B51985D7A600D336C4 /* BlockIoKeyController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49FCD6B41985D7A600D336C4 /* BlockIoKeyController.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -88,6 +91,10 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 490B0DD21988384000154F92 /* AnnouncementViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnnouncementViewController.h; sourceTree = ""; }; + 490B0DD31988384000154F92 /* AnnouncementViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnnouncementViewController.m; sourceTree = ""; }; + 490B0DD819883A0400154F92 /* AnnouncementHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnnouncementHandler.h; sourceTree = ""; }; + 490B0DD919883A0400154F92 /* AnnouncementHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnnouncementHandler.m; sourceTree = ""; }; 4911D6331926F25C009B9C5B /* DogeKeeper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DogeKeeper.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4911D6361926F25C009B9C5B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 4911D6381926F25C009B9C5B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -105,11 +112,13 @@ 4911D6631926F25D009B9C5B /* DogeKeeperTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DogeKeeperTests-Info.plist"; sourceTree = ""; }; 4911D6651926F25D009B9C5B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 4911D6671926F25D009B9C5B /* DogeKeeperTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DogeKeeperTests.m; sourceTree = ""; }; - 4911D6711926FA5F009B9C5B /* DogeAPIHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DogeAPIHandler.h; sourceTree = ""; }; - 4911D6721926FA5F009B9C5B /* DogeAPIHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DogeAPIHandler.m; sourceTree = ""; wrapsLines = 0; }; 4911D6771927090B009B9C5B /* dogecoind.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dogecoind.png; sourceTree = ""; }; - 493BF7A0196E2F0F00947A05 /* EncryptionHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncryptionHelper.h; sourceTree = ""; }; - 493BF7A1196E2F0F00947A05 /* EncryptionHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncryptionHelper.m; sourceTree = ""; }; + 4919796B19897DFE00147FC9 /* ExchangeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExchangeViewController.h; sourceTree = ""; }; + 4919796C19897DFE00147FC9 /* ExchangeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExchangeViewController.m; sourceTree = ""; }; + 4919796E19897FED00147FC9 /* ExchangeRateViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExchangeRateViewController.h; path = ../ExchangeRateViewController.h; sourceTree = ""; }; + 4919796F19897FED00147FC9 /* ExchangeRateViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ExchangeRateViewController.m; path = ../ExchangeRateViewController.m; sourceTree = ""; }; + 491979711989807600147FC9 /* PriceHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PriceHandler.h; path = ../PriceHandler.h; sourceTree = ""; }; + 491979721989807600147FC9 /* PriceHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PriceHandler.m; path = ../PriceHandler.m; sourceTree = ""; }; 493BF7A3196E305000947A05 /* lock-32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock-32.png"; sourceTree = ""; }; 4940B90F196CE84C008D95CE /* .gitignore */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; 4940B910196CE84C008D95CE /* AESCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESCrypt.h; sourceTree = ""; }; @@ -133,17 +142,14 @@ 49448D63194693F100765F66 /* BCVideoPreviewView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BCVideoPreviewView.m; sourceTree = ""; }; 49448D6819469ED500765F66 /* WalletListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WalletListController.h; path = ../WalletListController.h; sourceTree = ""; }; 49448D6919469ED500765F66 /* WalletListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WalletListController.m; path = ../WalletListController.m; sourceTree = ""; }; + 4946E685198448A20039888F /* BlockIOHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockIOHandler.h; sourceTree = ""; }; + 4946E686198448A20039888F /* BlockIOHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockIOHandler.m; sourceTree = ""; }; 494C4C77192C1D8500545434 /* AddWalletViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddWalletViewController.h; sourceTree = ""; }; 494C4C78192C1D8500545434 /* AddWalletViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddWalletViewController.m; sourceTree = ""; }; 494C4C7A192C1D8F00545434 /* DogeChainHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DogeChainHandler.h; sourceTree = ""; }; 494C4C7B192C1D8F00545434 /* DogeChainHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DogeChainHandler.m; sourceTree = ""; }; 494C4C7D192C1D9A00545434 /* DogecoinWallet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DogecoinWallet.h; sourceTree = ""; }; 494C4C7E192C1D9A00545434 /* DogecoinWallet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DogecoinWallet.m; sourceTree = ""; }; - 49521D81196F204A00BFCF95 /* PassViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassViewController.h; sourceTree = ""; }; - 49521D82196F204A00BFCF95 /* PassViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PassViewController.m; sourceTree = ""; }; - 4952F46B1970D89400FE9D96 /* Graveyard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Graveyard.storyboard; sourceTree = ""; }; - 49606ECD19299A33005072D2 /* ApiKeyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApiKeyViewController.h; sourceTree = ""; }; - 49606ECE19299A33005072D2 /* ApiKeyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ApiKeyViewController.m; sourceTree = ""; }; 4975EA2F192D77D600D136A9 /* TransactionCompleteViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransactionCompleteViewController.h; sourceTree = ""; }; 4975EA30192D77D600D136A9 /* TransactionCompleteViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransactionCompleteViewController.m; sourceTree = ""; }; 498D03021943E731004BC0B0 /* dknobg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dknobg.png; sourceTree = ""; }; @@ -153,8 +159,6 @@ 499705D81927D6CE00C53D78 /* DogeTransaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DogeTransaction.m; sourceTree = ""; }; 499705DA1927D9DF00C53D78 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; 499705DB1927D9DF00C53D78 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; - 499705DD1927DE4C00C53D78 /* ExchangeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExchangeViewController.h; path = ../ExchangeViewController.h; sourceTree = ""; }; - 499705DE1927DE4C00C53D78 /* ExchangeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ExchangeViewController.m; path = ../ExchangeViewController.m; sourceTree = ""; }; 499705E01927DFFE00C53D78 /* WelcomeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WelcomeViewController.h; path = ../WelcomeViewController.h; sourceTree = ""; }; 499705E11927DFFE00C53D78 /* WelcomeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WelcomeViewController.m; path = ../WelcomeViewController.m; sourceTree = ""; }; 499705E31927E06100C53D78 /* WalletsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WalletsViewController.h; sourceTree = ""; }; @@ -169,6 +173,8 @@ 49B82A19194CE0FD00B9B4B6 /* HistoryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryViewController.m; sourceTree = ""; }; 49B82A1E194CED2100B9B4B6 /* WalletDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WalletDetailViewController.h; sourceTree = ""; }; 49B82A1F194CED2100B9B4B6 /* WalletDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WalletDetailViewController.m; sourceTree = ""; }; + 49D0BBCF198AC08700945096 /* mp30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mp30.png; sourceTree = ""; }; + 49D0BBD0198AC08700945096 /* mp60.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mp60.png; sourceTree = ""; }; 49DDD468194E026200C3C6FD /* bitstream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bitstream.c; sourceTree = ""; }; 49DDD469194E026200C3C6FD /* bitstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitstream.h; sourceTree = ""; }; 49DDD46A194E026200C3C6FD /* mask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mask.c; sourceTree = ""; }; @@ -194,6 +200,8 @@ 49DDD48C194E80DD00C3C6FD /* settings-32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "settings-32.png"; sourceTree = ""; }; 49DDD48E194E811000C3C6FD /* line_chart-32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "line_chart-32.png"; sourceTree = ""; }; 49E381D4194B83AD00E38558 /* donate.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = donate.jpeg; sourceTree = ""; }; + 49FCD6B31985D7A600D336C4 /* BlockIoKeyController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockIoKeyController.h; sourceTree = ""; }; + 49FCD6B41985D7A600D336C4 /* BlockIoKeyController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockIoKeyController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -282,20 +290,27 @@ 49DDD48C194E80DD00C3C6FD /* settings-32.png */, 49DDD48E194E811000C3C6FD /* line_chart-32.png */, 493BF7A3196E305000947A05 /* lock-32.png */, - 4911D6711926FA5F009B9C5B /* DogeAPIHandler.h */, - 4911D6721926FA5F009B9C5B /* DogeAPIHandler.m */, - 493BF7A0196E2F0F00947A05 /* EncryptionHelper.h */, - 493BF7A1196E2F0F00947A05 /* EncryptionHelper.m */, + 49D0BBCF198AC08700945096 /* mp30.png */, + 49D0BBD0198AC08700945096 /* mp60.png */, + 4946E685198448A20039888F /* BlockIOHandler.h */, + 4946E686198448A20039888F /* BlockIOHandler.m */, 494C4C7A192C1D8F00545434 /* DogeChainHandler.h */, 494C4C7B192C1D8F00545434 /* DogeChainHandler.m */, + 491979711989807600147FC9 /* PriceHandler.h */, + 491979721989807600147FC9 /* PriceHandler.m */, + 490B0DD819883A0400154F92 /* AnnouncementHandler.h */, + 490B0DD919883A0400154F92 /* AnnouncementHandler.m */, 494C4C7D192C1D9A00545434 /* DogecoinWallet.h */, 494C4C7E192C1D9A00545434 /* DogecoinWallet.m */, 499705D71927D6CE00C53D78 /* DogeTransaction.h */, 499705D81927D6CE00C53D78 /* DogeTransaction.m */, - 4952F46B1970D89400FE9D96 /* Graveyard.storyboard */, 4911D6481926F25D009B9C5B /* Main_iPhone.storyboard */, - 49521D81196F204A00BFCF95 /* PassViewController.h */, - 49521D82196F204A00BFCF95 /* PassViewController.m */, + 499705E91927E82D00C53D78 /* DogeViewController.h */, + 499705EA1927E82D00C53D78 /* DogeViewController.m */, + 4919796E19897FED00147FC9 /* ExchangeRateViewController.h */, + 4919796F19897FED00147FC9 /* ExchangeRateViewController.m */, + 4919796B19897DFE00147FC9 /* ExchangeViewController.h */, + 4919796C19897DFE00147FC9 /* ExchangeViewController.m */, 4975EA2F192D77D600D136A9 /* TransactionCompleteViewController.h */, 4975EA30192D77D600D136A9 /* TransactionCompleteViewController.m */, 49B82A18194CE0FD00B9B4B6 /* HistoryViewController.h */, @@ -308,18 +323,16 @@ 494C4C78192C1D8500545434 /* AddWalletViewController.m */, 49A1CB64192AD8EE00D4EA5F /* SettingsViewController.h */, 49A1CB65192AD8EE00D4EA5F /* SettingsViewController.m */, - 49606ECD19299A33005072D2 /* ApiKeyViewController.h */, - 49606ECE19299A33005072D2 /* ApiKeyViewController.m */, - 499705E91927E82D00C53D78 /* DogeViewController.h */, - 499705EA1927E82D00C53D78 /* DogeViewController.m */, + 49FCD6B31985D7A600D336C4 /* BlockIoKeyController.h */, + 49FCD6B41985D7A600D336C4 /* BlockIoKeyController.m */, 499705E61927E78000C53D78 /* SendViewController.h */, 499705E71927E78000C53D78 /* SendViewController.m */, 499705E31927E06100C53D78 /* WalletsViewController.h */, 499705E41927E06100C53D78 /* WalletsViewController.m */, 499705DA1927D9DF00C53D78 /* MainViewController.h */, 499705DB1927D9DF00C53D78 /* MainViewController.m */, - 499705DD1927DE4C00C53D78 /* ExchangeViewController.h */, - 499705DE1927DE4C00C53D78 /* ExchangeViewController.m */, + 490B0DD21988384000154F92 /* AnnouncementViewController.h */, + 490B0DD31988384000154F92 /* AnnouncementViewController.m */, 499705E01927DFFE00C53D78 /* WelcomeViewController.h */, 499705E11927DFFE00C53D78 /* WelcomeViewController.m */, 498D03041943E963004BC0B0 /* AboutViewController.h */, @@ -499,16 +512,17 @@ 49DDD485194E802000C3C6FD /* money-128.png in Resources */, 49E381D5194B83AE00E38558 /* donate.jpeg in Resources */, 49DDD484194E802000C3C6FD /* bar-128.png in Resources */, - 4952F46C1970D89400FE9D96 /* Graveyard.storyboard in Resources */, 498D03031943E731004BC0B0 /* dknobg.png in Resources */, 4911D6781927090B009B9C5B /* dogecoind.png in Resources */, 4911D6551926F25D009B9C5B /* Images.xcassets in Resources */, + 49D0BBD2198AC08700945096 /* mp60.png in Resources */, 49DDD487194E802000C3C6FD /* wallet-128.png in Resources */, 49DDD48B194E80D100C3C6FD /* wallet-32.png in Resources */, 49DDD48D194E80DD00C3C6FD /* settings-32.png in Resources */, 49DDD486194E802000C3C6FD /* settings-128.png in Resources */, 4940B91C196CE84C008D95CE /* LICENSE in Resources */, 4940B920196CE84C008D95CE /* README.md in Resources */, + 49D0BBD1198AC08700945096 /* mp30.png in Resources */, 4940B91A196CE84C008D95CE /* .gitignore in Resources */, 493BF7A4196E305000947A05 /* lock-32.png in Resources */, 49DDD489194E809000C3C6FD /* money-32.png in Resources */, @@ -535,27 +549,28 @@ files = ( 498D03061943E963004BC0B0 /* AboutViewController.m in Sources */, 499705E81927E78000C53D78 /* SendViewController.m in Sources */, - 4911D6731926FA5F009B9C5B /* DogeAPIHandler.m in Sources */, - 49606ECF19299A33005072D2 /* ApiKeyViewController.m in Sources */, 49DDD47A194E026200C3C6FD /* qrencode.c in Sources */, - 49521D83196F204A00BFCF95 /* PassViewController.m in Sources */, + 4919796D19897DFE00147FC9 /* ExchangeViewController.m in Sources */, + 4946E687198448A20039888F /* BlockIOHandler.m in Sources */, 49A1CB66192AD8EE00D4EA5F /* SettingsViewController.m in Sources */, 4940B91E196CE84C008D95CE /* NSData+CommonCrypto.m in Sources */, 49DDD47D194E026200C3C6FD /* rscode.c in Sources */, 494C4C79192C1D8500545434 /* AddWalletViewController.m in Sources */, - 499705DF1927DE4C00C53D78 /* ExchangeViewController.m in Sources */, 49DDD478194E026200C3C6FD /* bitstream.c in Sources */, 4911D6471926F25D009B9C5B /* AppDelegate.m in Sources */, + 4919797019897FED00147FC9 /* ExchangeRateViewController.m in Sources */, 49448D64194693F100765F66 /* BCVideoPreviewView.m in Sources */, 49DDD47C194E026200C3C6FD /* qrspec.c in Sources */, + 490B0DD41988384000154F92 /* AnnouncementViewController.m in Sources */, + 491979731989807600147FC9 /* PriceHandler.m in Sources */, 49DDD479194E026200C3C6FD /* mask.c in Sources */, 4940B91D196CE84C008D95CE /* NSData+Base64.m in Sources */, - 493BF7A2196E2F0F00947A05 /* EncryptionHelper.m in Sources */, 499705D91927D6CE00C53D78 /* DogeTransaction.m in Sources */, 49DDD47B194E026200C3C6FD /* qrinput.c in Sources */, 4940B91B196CE84C008D95CE /* AESCrypt.m in Sources */, 49B82A20194CED2100B9B4B6 /* WalletDetailViewController.m in Sources */, 49DDD47F194E026200C3C6FD /* UIImage+MDQRCode.m in Sources */, + 49FCD6B51985D7A600D336C4 /* BlockIoKeyController.m in Sources */, 49DDD47E194E026200C3C6FD /* split.c in Sources */, 499705DC1927D9DF00C53D78 /* MainViewController.m in Sources */, 494C4C7F192C1D9A00545434 /* DogecoinWallet.m in Sources */, @@ -566,6 +581,7 @@ 4975EA31192D77D600D136A9 /* TransactionCompleteViewController.m in Sources */, 49448D6A19469ED500765F66 /* WalletListController.m in Sources */, 499705E21927DFFE00C53D78 /* WelcomeViewController.m in Sources */, + 490B0DDA19883A0400154F92 /* AnnouncementHandler.m in Sources */, 4911D6431926F25C009B9C5B /* main.m in Sources */, 499705EB1927E82D00C53D78 /* DogeViewController.m in Sources */, 4940B91F196CE84C008D95CE /* NSString+Base64.m in Sources */, @@ -696,16 +712,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Distribution: Paul Arpasi (NJKXF7XV99)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Paul Arpasi (NJKXF7XV99)"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "DogeKeeper/DogeKeeper-Prefix.pch"; INFOPLIST_FILE = "DogeKeeper/DogeKeeper-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.0; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/DogeKeeper/ZBarSDK", - ); PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "D63C0EB6-204A-4DC9-939D-FB0322F1DA1B"; + PROVISIONING_PROFILE = "4B6DAC64-8768-4693-981B-3D326A1A4C3F"; TARGETED_DEVICE_FAMILY = 1; WRAPPER_EXTENSION = app; }; @@ -717,16 +730,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Distribution: Paul Arpasi (NJKXF7XV99)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Paul Arpasi (NJKXF7XV99)"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "DogeKeeper/DogeKeeper-Prefix.pch"; INFOPLIST_FILE = "DogeKeeper/DogeKeeper-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.0; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/DogeKeeper/ZBarSDK", - ); PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "D63C0EB6-204A-4DC9-939D-FB0322F1DA1B"; + PROVISIONING_PROFILE = "4B6DAC64-8768-4693-981B-3D326A1A4C3F"; TARGETED_DEVICE_FAMILY = 1; WRAPPER_EXTENSION = app; }; diff --git a/DogeKeeper.xcodeproj/project.xcworkspace/xcshareddata/DogeKeeper.xccheckout b/DogeKeeper.xcodeproj/project.xcworkspace/xcshareddata/DogeKeeper.xccheckout new file mode 100644 index 0000000..385d04d --- /dev/null +++ b/DogeKeeper.xcodeproj/project.xcworkspace/xcshareddata/DogeKeeper.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 58D1F5F1-A270-4E20-9220-EE63D55E35AB + IDESourceControlProjectName + DogeKeeper + IDESourceControlProjectOriginsDictionary + + 3BEB338D-BAF1-4438-9ADD-75E41B72459F + ssh://github.com/Andrew-Dev/DogeKeeper.git + + IDESourceControlProjectPath + DogeKeeper.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 3BEB338D-BAF1-4438-9ADD-75E41B72459F + ../.. + + IDESourceControlProjectURL + ssh://github.com/Andrew-Dev/DogeKeeper.git + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 3BEB338D-BAF1-4438-9ADD-75E41B72459F + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 3BEB338D-BAF1-4438-9ADD-75E41B72459F + IDESourceControlWCCName + DogeKeeper + + + + diff --git a/DogeKeeper.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate b/DogeKeeper.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate index c2edc7a21a16ecd0d24e7c49f8dbb31b17145694..f490d6051e489e2ddcb562ed0266b2840898e61f 100644 GIT binary patch literal 21465 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 WQ}UxLg@Gta{Nyf(pYFdUSN|6iL`Qu9 literal 66560 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 diff --git a/DogeKeeper/AESCrypt/.gitignore b/DogeKeeper/AESCrypt/.gitignore new file mode 100755 index 0000000..edc082c --- /dev/null +++ b/DogeKeeper/AESCrypt/.gitignore @@ -0,0 +1,15 @@ +# Xcode +build/* +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +*.xcworkspace +!default.xcworkspace +xcuserdata +profile +*.moved-aside diff --git a/DogeKeeper/AESCrypt/AESCrypt.h b/DogeKeeper/AESCrypt/AESCrypt.h new file mode 100755 index 0000000..8e3606e --- /dev/null +++ b/DogeKeeper/AESCrypt/AESCrypt.h @@ -0,0 +1,37 @@ +// +// AESCrypt.h +// Gurpartap Singh +// +// Created by Gurpartap Singh on 06/05/12. +// Copyright (c) 2012 Gurpartap Singh +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#import + +@interface AESCrypt : NSObject + ++ (NSString *)encrypt:(NSString *)message password:(NSString *)password; ++ (NSString *)decrypt:(NSString *)base64EncodedString password:(NSString *)password; + +@end diff --git a/DogeKeeper/AESCrypt/AESCrypt.m b/DogeKeeper/AESCrypt/AESCrypt.m new file mode 100755 index 0000000..721d49b --- /dev/null +++ b/DogeKeeper/AESCrypt/AESCrypt.m @@ -0,0 +1,50 @@ +// +// AESCrypt.m +// Gurpartap Singh +// +// Created by Gurpartap Singh on 06/05/12. +// Copyright (c) 2012 Gurpartap Singh +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#import "AESCrypt.h" + +#import "NSData+Base64.h" +#import "NSString+Base64.h" +#import "NSData+CommonCrypto.h" + +@implementation AESCrypt + ++ (NSString *)encrypt:(NSString *)message password:(NSString *)password { + NSData *encryptedData = [[message dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptedDataUsingKey:[[password dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash] error:nil]; + NSString *base64EncodedString = [NSString base64StringFromData:encryptedData length:[encryptedData length]]; + return base64EncodedString; +} + ++ (NSString *)decrypt:(NSString *)base64EncodedString password:(NSString *)password { + NSData *encryptedData = [NSData base64DataFromString:base64EncodedString]; + NSData *decryptedData = [encryptedData decryptedAES256DataUsingKey:[[password dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash] error:nil]; + return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding]; +} + +@end diff --git a/DogeKeeper/AESCrypt/LICENSE b/DogeKeeper/AESCrypt/LICENSE new file mode 100755 index 0000000..71f582f --- /dev/null +++ b/DogeKeeper/AESCrypt/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012 Gurpartap Singh + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/DogeKeeper/AESCrypt/NSData+Base64.h b/DogeKeeper/AESCrypt/NSData+Base64.h new file mode 100755 index 0000000..abf48de --- /dev/null +++ b/DogeKeeper/AESCrypt/NSData+Base64.h @@ -0,0 +1,17 @@ +// +// NSData+Base64.m +// Gurpartap Singh +// +// Created by Gurpartap Singh on 06/05/12. +// Copyright (c) 2012 Gurpartap Singh. All rights reserved. +// + +#import + +@class NSString; + +@interface NSData (Base64Additions) + ++ (NSData *)base64DataFromString:(NSString *)string; + +@end \ No newline at end of file diff --git a/DogeKeeper/AESCrypt/NSData+Base64.m b/DogeKeeper/AESCrypt/NSData+Base64.m new file mode 100755 index 0000000..fde3584 --- /dev/null +++ b/DogeKeeper/AESCrypt/NSData+Base64.m @@ -0,0 +1,110 @@ +// +// NSData+Base64.h +// Gurpartap Singh +// +// Created by Gurpartap Singh on 06/05/12. +// Copyright (c) 2012 Gurpartap Singh. All rights reserved. +// + +#import "NSData+Base64.h" + +@implementation NSData (Base64Additions) + ++ (NSData *)base64DataFromString:(NSString *)string { + unsigned long ixtext, lentext; + unsigned char ch, inbuf[4], outbuf[3]; + short i, ixinbuf; + Boolean flignore, flendtext = false; + const unsigned char *tempcstring; + NSMutableData *theData; + + if (string == nil) { + return [NSData data]; + } + + ixtext = 0; + + tempcstring = (const unsigned char *)[string UTF8String]; + + lentext = [string length]; + + theData = [NSMutableData dataWithCapacity: lentext]; + + ixinbuf = 0; + + while (true) { + if (ixtext >= lentext) { + break; + } + + ch = tempcstring [ixtext++]; + + flignore = false; + + if ((ch >= 'A') && (ch <= 'Z')) { + ch = ch - 'A'; + } + else if ((ch >= 'a') && (ch <= 'z')) { + ch = ch - 'a' + 26; + } + else if ((ch >= '0') && (ch <= '9')) { + ch = ch - '0' + 52; + } + else if (ch == '+') { + ch = 62; + } + else if (ch == '=') { + flendtext = true; + } + else if (ch == '/') { + ch = 63; + } + else { + flignore = true; + } + + if (!flignore) { + short ctcharsinbuf = 3; + Boolean flbreak = false; + + if (flendtext) { + if (ixinbuf == 0) { + break; + } + + if ((ixinbuf == 1) || (ixinbuf == 2)) { + ctcharsinbuf = 1; + } + else { + ctcharsinbuf = 2; + } + + ixinbuf = 3; + + flbreak = true; + } + + inbuf [ixinbuf++] = ch; + + if (ixinbuf == 4) { + ixinbuf = 0; + + outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4); + outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2); + outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F); + + for (i = 0; i < ctcharsinbuf; i++) { + [theData appendBytes: &outbuf[i] length: 1]; + } + } + + if (flbreak) { + break; + } + } + } + + return theData; +} + +@end diff --git a/DogeKeeper/AESCrypt/NSData+CommonCrypto.h b/DogeKeeper/AESCrypt/NSData+CommonCrypto.h new file mode 100755 index 0000000..95cce99 --- /dev/null +++ b/DogeKeeper/AESCrypt/NSData+CommonCrypto.h @@ -0,0 +1,112 @@ +/* + * NSData+CommonCrypto.h + * AQToolkit + * + * Created by Jim Dovey on 31/8/2008. + * + * Copyright (c) 2008-2009, Jim Dovey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of this project's author nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import +#import +#import +#import + +extern NSString * const kCommonCryptoErrorDomain; + +@interface NSError (CommonCryptoErrorDomain) ++ (NSError *) errorWithCCCryptorStatus: (CCCryptorStatus) status; +@end + +@interface NSData (CommonDigest) + +- (NSData *) MD2Sum; +- (NSData *) MD4Sum; +- (NSData *) MD5Sum; + +- (NSData *) SHA1Hash; +- (NSData *) SHA224Hash; +- (NSData *) SHA256Hash; +- (NSData *) SHA384Hash; +- (NSData *) SHA512Hash; + +@end + +@interface NSData (CommonCryptor) + +- (NSData *) AES256EncryptedDataUsingKey: (id) key error: (NSError **) error; +- (NSData *) decryptedAES256DataUsingKey: (id) key error: (NSError **) error; + +- (NSData *) DESEncryptedDataUsingKey: (id) key error: (NSError **) error; +- (NSData *) decryptedDESDataUsingKey: (id) key error: (NSError **) error; + +- (NSData *) CASTEncryptedDataUsingKey: (id) key error: (NSError **) error; +- (NSData *) decryptedCASTDataUsingKey: (id) key error: (NSError **) error; + +@end + +@interface NSData (LowLevelCommonCryptor) + +- (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + error: (CCCryptorStatus *) error; +- (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + options: (CCOptions) options + error: (CCCryptorStatus *) error; +- (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + initializationVector: (id) iv // data or string + options: (CCOptions) options + error: (CCCryptorStatus *) error; + +- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + error: (CCCryptorStatus *) error; +- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + options: (CCOptions) options + error: (CCCryptorStatus *) error; +- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + initializationVector: (id) iv // data or string + options: (CCOptions) options + error: (CCCryptorStatus *) error; + +@end + +@interface NSData (CommonHMAC) + +- (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm; +- (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm key: (id) key; + +@end \ No newline at end of file diff --git a/DogeKeeper/AESCrypt/NSData+CommonCrypto.m b/DogeKeeper/AESCrypt/NSData+CommonCrypto.m new file mode 100755 index 0000000..47dbd3d --- /dev/null +++ b/DogeKeeper/AESCrypt/NSData+CommonCrypto.m @@ -0,0 +1,546 @@ +/* + * NSData+CommonCrypto.m + * AQToolkit + * + * Created by Jim Dovey on 31/8/2008. + * + * Copyright (c) 2008-2009, Jim Dovey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of this project's author nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import +#import "NSData+CommonCrypto.h" +#import +#import +#import + +NSString * const kCommonCryptoErrorDomain = @"CommonCryptoErrorDomain"; + +@implementation NSError (CommonCryptoErrorDomain) + ++ (NSError *) errorWithCCCryptorStatus: (CCCryptorStatus) status +{ + NSString * description = nil, * reason = nil; + + switch ( status ) + { + case kCCSuccess: + description = NSLocalizedString(@"Success", @"Error description"); + break; + + case kCCParamError: + description = NSLocalizedString(@"Parameter Error", @"Error description"); + reason = NSLocalizedString(@"Illegal parameter supplied to encryption/decryption algorithm", @"Error reason"); + break; + + case kCCBufferTooSmall: + description = NSLocalizedString(@"Buffer Too Small", @"Error description"); + reason = NSLocalizedString(@"Insufficient buffer provided for specified operation", @"Error reason"); + break; + + case kCCMemoryFailure: + description = NSLocalizedString(@"Memory Failure", @"Error description"); + reason = NSLocalizedString(@"Failed to allocate memory", @"Error reason"); + break; + + case kCCAlignmentError: + description = NSLocalizedString(@"Alignment Error", @"Error description"); + reason = NSLocalizedString(@"Input size to encryption algorithm was not aligned correctly", @"Error reason"); + break; + + case kCCDecodeError: + description = NSLocalizedString(@"Decode Error", @"Error description"); + reason = NSLocalizedString(@"Input data did not decode or decrypt correctly", @"Error reason"); + break; + + case kCCUnimplemented: + description = NSLocalizedString(@"Unimplemented Function", @"Error description"); + reason = NSLocalizedString(@"Function not implemented for the current algorithm", @"Error reason"); + break; + + default: + description = NSLocalizedString(@"Unknown Error", @"Error description"); + break; + } + + NSMutableDictionary * userInfo = [[NSMutableDictionary alloc] init]; + [userInfo setObject: description forKey: NSLocalizedDescriptionKey]; + + if ( reason != nil ) + [userInfo setObject: reason forKey: NSLocalizedFailureReasonErrorKey]; + + NSError * result = [NSError errorWithDomain: kCommonCryptoErrorDomain code: status userInfo: userInfo]; + #if !__has_feature(objc_arc) + [userInfo release]; + #endif + + return ( result ); +} + +@end + +#pragma mark - + +@implementation NSData (CommonDigest) + +- (NSData *) MD2Sum +{ + unsigned char hash[CC_MD2_DIGEST_LENGTH]; + (void) CC_MD2( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_MD2_DIGEST_LENGTH] ); +} + +- (NSData *) MD4Sum +{ + unsigned char hash[CC_MD4_DIGEST_LENGTH]; + (void) CC_MD4( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_MD4_DIGEST_LENGTH] ); +} + +- (NSData *) MD5Sum +{ + unsigned char hash[CC_MD5_DIGEST_LENGTH]; + (void) CC_MD5( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_MD5_DIGEST_LENGTH] ); +} + +- (NSData *) SHA1Hash +{ + unsigned char hash[CC_SHA1_DIGEST_LENGTH]; + (void) CC_SHA1( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_SHA1_DIGEST_LENGTH] ); +} + +- (NSData *) SHA224Hash +{ + unsigned char hash[CC_SHA224_DIGEST_LENGTH]; + (void) CC_SHA224( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_SHA224_DIGEST_LENGTH] ); +} + +- (NSData *) SHA256Hash +{ + unsigned char hash[CC_SHA256_DIGEST_LENGTH]; + (void) CC_SHA256( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_SHA256_DIGEST_LENGTH] ); +} + +- (NSData *) SHA384Hash +{ + unsigned char hash[CC_SHA384_DIGEST_LENGTH]; + (void) CC_SHA384( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_SHA384_DIGEST_LENGTH] ); +} + +- (NSData *) SHA512Hash +{ + unsigned char hash[CC_SHA512_DIGEST_LENGTH]; + (void) CC_SHA512( [self bytes], (CC_LONG)[self length], hash ); + return ( [NSData dataWithBytes: hash length: CC_SHA512_DIGEST_LENGTH] ); +} + +@end + +@implementation NSData (CommonCryptor) + +- (NSData *) AES256EncryptedDataUsingKey: (id) key error: (NSError **) error +{ + CCCryptorStatus status = kCCSuccess; + NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmAES128 + key: key + options: kCCOptionPKCS7Padding + error: &status]; + + if ( result != nil ) + return ( result ); + + if ( error != NULL ) + *error = [NSError errorWithCCCryptorStatus: status]; + + return ( nil ); +} + +- (NSData *) decryptedAES256DataUsingKey: (id) key error: (NSError **) error +{ + CCCryptorStatus status = kCCSuccess; + NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmAES128 + key: key + options: kCCOptionPKCS7Padding + error: &status]; + + if ( result != nil ) + return ( result ); + + if ( error != NULL ) + *error = [NSError errorWithCCCryptorStatus: status]; + + return ( nil ); +} + +- (NSData *) DESEncryptedDataUsingKey: (id) key error: (NSError **) error +{ + CCCryptorStatus status = kCCSuccess; + NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmDES + key: key + options: kCCOptionPKCS7Padding + error: &status]; + + if ( result != nil ) + return ( result ); + + if ( error != NULL ) + *error = [NSError errorWithCCCryptorStatus: status]; + + return ( nil ); +} + +- (NSData *) decryptedDESDataUsingKey: (id) key error: (NSError **) error +{ + CCCryptorStatus status = kCCSuccess; + NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmDES + key: key + options: kCCOptionPKCS7Padding + error: &status]; + + if ( result != nil ) + return ( result ); + + if ( error != NULL ) + *error = [NSError errorWithCCCryptorStatus: status]; + + return ( nil ); +} + +- (NSData *) CASTEncryptedDataUsingKey: (id) key error: (NSError **) error +{ + CCCryptorStatus status = kCCSuccess; + NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmCAST + key: key + options: kCCOptionPKCS7Padding + error: &status]; + + if ( result != nil ) + return ( result ); + + if ( error != NULL ) + *error = [NSError errorWithCCCryptorStatus: status]; + + return ( nil ); +} + +- (NSData *) decryptedCASTDataUsingKey: (id) key error: (NSError **) error +{ + CCCryptorStatus status = kCCSuccess; + NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmCAST + key: key + options: kCCOptionPKCS7Padding + error: &status]; + + if ( result != nil ) + return ( result ); + + if ( error != NULL ) + *error = [NSError errorWithCCCryptorStatus: status]; + + return ( nil ); +} + +@end + +static void FixKeyLengths( CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData ) +{ + NSUInteger keyLength = [keyData length]; + switch ( algorithm ) + { + case kCCAlgorithmAES128: + { + if ( keyLength < 16 ) + { + [keyData setLength: 16]; + } + else if ( keyLength < 24 ) + { + [keyData setLength: 24]; + } + else + { + [keyData setLength: 32]; + } + + break; + } + + case kCCAlgorithmDES: + { + [keyData setLength: 8]; + break; + } + + case kCCAlgorithm3DES: + { + [keyData setLength: 24]; + break; + } + + case kCCAlgorithmCAST: + { + if ( keyLength < 5 ) + { + [keyData setLength: 5]; + } + else if ( keyLength > 16 ) + { + [keyData setLength: 16]; + } + + break; + } + + case kCCAlgorithmRC4: + { + if ( keyLength > 512 ) + [keyData setLength: 512]; + break; + } + + default: + break; + } + + [ivData setLength: [keyData length]]; +} + +@implementation NSData (LowLevelCommonCryptor) + +- (NSData *) _runCryptor: (CCCryptorRef) cryptor result: (CCCryptorStatus *) status +{ + size_t bufsize = CCCryptorGetOutputLength( cryptor, (size_t)[self length], true ); + void * buf = malloc( bufsize ); + size_t bufused = 0; + size_t bytesTotal = 0; + *status = CCCryptorUpdate( cryptor, [self bytes], (size_t)[self length], + buf, bufsize, &bufused ); + if ( *status != kCCSuccess ) + { + free( buf ); + return ( nil ); + } + + bytesTotal += bufused; + + // From Brent Royal-Gordon (Twitter: architechies): + // Need to update buf ptr past used bytes when calling CCCryptorFinal() + *status = CCCryptorFinal( cryptor, buf + bufused, bufsize - bufused, &bufused ); + if ( *status != kCCSuccess ) + { + free( buf ); + return ( nil ); + } + + bytesTotal += bufused; + + return ( [NSData dataWithBytesNoCopy: buf length: bytesTotal] ); +} + +- (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key + error: (CCCryptorStatus *) error +{ + return ( [self dataEncryptedUsingAlgorithm: algorithm + key: key + initializationVector: nil + options: 0 + error: error] ); +} + +- (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key + options: (CCOptions) options + error: (CCCryptorStatus *) error +{ + return ( [self dataEncryptedUsingAlgorithm: algorithm + key: key + initializationVector: nil + options: options + error: error] ); +} + +- (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key + initializationVector: (id) iv + options: (CCOptions) options + error: (CCCryptorStatus *) error +{ + CCCryptorRef cryptor = NULL; + CCCryptorStatus status = kCCSuccess; + + NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); + NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]); + + NSMutableData * keyData, * ivData; + if ( [key isKindOfClass: [NSData class]] ) + keyData = (NSMutableData *) [key mutableCopy]; + else + keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; + + if ( [iv isKindOfClass: [NSString class]] ) + ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; + else + ivData = (NSMutableData *) [iv mutableCopy]; // data or nil + + #if !__has_feature(objc_arc) + [keyData autorelease]; + [ivData autorelease]; + #endif + // ensure correct lengths for key and iv data, based on algorithms + FixKeyLengths( algorithm, keyData, ivData ); + + status = CCCryptorCreate( kCCEncrypt, algorithm, options, + [keyData bytes], [keyData length], [ivData bytes], + &cryptor ); + + if ( status != kCCSuccess ) + { + if ( error != NULL ) + *error = status; + return ( nil ); + } + + NSData * result = [self _runCryptor: cryptor result: &status]; + if ( (result == nil) && (error != NULL) ) + *error = status; + + CCCryptorRelease( cryptor ); + + return ( result ); +} + +- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + error: (CCCryptorStatus *) error +{ + return ( [self decryptedDataUsingAlgorithm: algorithm + key: key + initializationVector: nil + options: 0 + error: error] ); +} + +- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + options: (CCOptions) options + error: (CCCryptorStatus *) error +{ + return ( [self decryptedDataUsingAlgorithm: algorithm + key: key + initializationVector: nil + options: options + error: error] ); +} + +- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm + key: (id) key // data or string + initializationVector: (id) iv // data or string + options: (CCOptions) options + error: (CCCryptorStatus *) error +{ + CCCryptorRef cryptor = NULL; + CCCryptorStatus status = kCCSuccess; + + NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); + NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]); + + NSMutableData * keyData, * ivData; + if ( [key isKindOfClass: [NSData class]] ) + keyData = (NSMutableData *) [key mutableCopy]; + else + keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; + + if ( [iv isKindOfClass: [NSString class]] ) + ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; + else + ivData = (NSMutableData *) [iv mutableCopy]; // data or nil + + #if !__has_feature(objc_arc) + [keyData autorelease]; + [ivData autorelease]; + #endif + + // ensure correct lengths for key and iv data, based on algorithms + FixKeyLengths( algorithm, keyData, ivData ); + + status = CCCryptorCreate( kCCDecrypt, algorithm, options, + [keyData bytes], [keyData length], [ivData bytes], + &cryptor ); + + if ( status != kCCSuccess ) + { + if ( error != NULL ) + *error = status; + return ( nil ); + } + + NSData * result = [self _runCryptor: cryptor result: &status]; + if ( (result == nil) && (error != NULL) ) + *error = status; + + CCCryptorRelease( cryptor ); + + return ( result ); +} + +@end + +@implementation NSData (CommonHMAC) + +- (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm +{ + return ( [self HMACWithAlgorithm: algorithm key: nil] ); +} + +- (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm key: (id) key +{ + NSParameterAssert(key == nil || [key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); + + NSData * keyData = nil; + if ( [key isKindOfClass: [NSString class]] ) + keyData = [key dataUsingEncoding: NSUTF8StringEncoding]; + else + keyData = (NSData *) key; + + // this could be either CC_SHA1_DIGEST_LENGTH or CC_MD5_DIGEST_LENGTH. SHA1 is larger. + unsigned char buf[CC_SHA1_DIGEST_LENGTH]; + CCHmac( algorithm, [keyData bytes], [keyData length], [self bytes], [self length], buf ); + + return ( [NSData dataWithBytes: buf length: (algorithm == kCCHmacAlgMD5 ? CC_MD5_DIGEST_LENGTH : CC_SHA1_DIGEST_LENGTH)] ); +} + +@end \ No newline at end of file diff --git a/DogeKeeper/AESCrypt/NSString+Base64.h b/DogeKeeper/AESCrypt/NSString+Base64.h new file mode 100755 index 0000000..11915a9 --- /dev/null +++ b/DogeKeeper/AESCrypt/NSString+Base64.h @@ -0,0 +1,15 @@ +// +// NSString+Base64.h +// Gurpartap Singh +// +// Created by Gurpartap Singh on 06/05/12. +// Copyright (c) 2012 Gurpartap Singh. All rights reserved. +// + +#import + +@interface NSString (Base64Additions) + ++ (NSString *)base64StringFromData:(NSData *)data length:(NSUInteger)length; + +@end diff --git a/DogeKeeper/AESCrypt/NSString+Base64.m b/DogeKeeper/AESCrypt/NSString+Base64.m new file mode 100755 index 0000000..b3daf1f --- /dev/null +++ b/DogeKeeper/AESCrypt/NSString+Base64.m @@ -0,0 +1,82 @@ +// +// NSStringAdditions.m +// Gurpartap Singh +// +// Created by Gurpartap Singh on 06/05/12. +// Copyright (c) 2012 Gurpartap Singh. All rights reserved. +// + +#import "NSString+Base64.h" + +static char base64EncodingTable[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' +}; + +@implementation NSString (Base64Additions) + ++ (NSString *)base64StringFromData: (NSData *)data length: (NSUInteger)length { + unsigned long ixtext, lentext; + long ctremaining; + unsigned char input[3], output[4]; + short i, charsonline = 0, ctcopy; + const unsigned char *raw; + NSMutableString *result; + + lentext = [data length]; + if (lentext < 1) { + return @""; + } + result = [NSMutableString stringWithCapacity: lentext]; + raw = [data bytes]; + ixtext = 0; + + while (true) { + ctremaining = lentext - ixtext; + if (ctremaining <= 0) { + break; + } + for (i = 0; i < 3; i++) { + unsigned long ix = ixtext + i; + if (ix < lentext) { + input[i] = raw[ix]; + } + else { + input[i] = 0; + } + } + output[0] = (input[0] & 0xFC) >> 2; + output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4); + output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6); + output[3] = input[2] & 0x3F; + ctcopy = 4; + switch (ctremaining) { + case 1: + ctcopy = 2; + break; + case 2: + ctcopy = 3; + break; + } + + for (i = 0; i < ctcopy; i++) { + [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]]; + } + + for (i = ctcopy; i < 4; i++) { + [result appendString: @"="]; + } + + ixtext += 3; + charsonline += 4; + + if ((length > 0) && (charsonline >= length)) { + charsonline = 0; + } + } + return result; +} + +@end \ No newline at end of file diff --git a/DogeKeeper/AESCrypt/README.md b/DogeKeeper/AESCrypt/README.md new file mode 100755 index 0000000..38c795d --- /dev/null +++ b/DogeKeeper/AESCrypt/README.md @@ -0,0 +1,57 @@ +# AESCrypt-ObjC - Simple AES encryption / decryption for iOS and OS X + +AESCrypt is a simple to use, opinionated AES encryption / decryption Objective-C class that just works. + +AESCrypt uses the AES-256-CBC cipher and encodes the encrypted data with base64. + +A corresponding gem to easily handle AES encryption / decryption in Ruby is available at http://github.com/Gurpartap/aescrypt. + +## Installation + +Add this line to your class: + + #import "AESCrypt.h" + +## Usage + + NSString *message = @"top secret message"; + NSString *password = @"p4ssw0rd"; + +Encrypting + + NSString *encryptedData = [AESCrypt encrypt:message password:password]; + +Decrypting + + NSString *message = [AESCrypt decrypt:encryptedData password:password]; + +## Common sense + +AESCrypt includes Base64 and Crypto extensions for NSData and NSString classes. If you're already using an extension that provides these, there is no need to use the included classes. Change the code in the AESCrypt class to correspond to your existing implementation of these extensions. + +## Corresponding usage in Ruby + +The AESCrypt Ruby gem, available at http://github.com/Gurpartap/aescrypt, understands what you're talking about in your Objective-C code. The purpose of the Ruby gem and Objective-C class is to have something that works out of the box across the server (Ruby) and client (Objective-C). However, a standard encryption technique is implemented, which ensures that you can handle the data with any AES compatible library available across the web. So, you're not locked-in. + +Here's how you would use the Ruby gem: + + message = "top secret message" + password = "p4ssw0rd" + +Encrypting + + encrypted_data = AESCrypt.encrypt(message, password) + +Decrypting + + message = AESCrypt.decrypt(encrypted_data, password) + +See the Ruby gem README at http://github.com/Gurpartap/aescrypt for more details. + +## License + +NSData+CommonCrypto is Copyright (c) 2008-2009, Jim Dovey + +AESCrypt is Copyright (c) 2012 Gurpartap Singh + +See LICENSE for license terms. diff --git a/DogeKeeper/AboutViewController.m b/DogeKeeper/AboutViewController.m index 7ab99f1..d53028f 100644 --- a/DogeKeeper/AboutViewController.m +++ b/DogeKeeper/AboutViewController.m @@ -65,6 +65,10 @@ -(IBAction)dogeChain:(id)sender { [self openWebURL:@"http://dogechain.info"]; } +-(IBAction)SoChain:(id)sender +{ + [self openWebURL:@"http://chain.so"]; +} -(IBAction)bcscanner:(id)sender { [self openWebURL:@"https://github.com/michaelochs/BCScanner"]; diff --git a/DogeKeeper/AddWalletViewController.m b/DogeKeeper/AddWalletViewController.m index cb3e866..6975aa2 100644 --- a/DogeKeeper/AddWalletViewController.m +++ b/DogeKeeper/AddWalletViewController.m @@ -50,7 +50,6 @@ -(IBAction)saveWallet:(id)sender -(IBAction)scanQR:(id)sender { if ([BCScannerViewController scannerAvailable]) { - NSLog(@"the crap is available"); BCScannerViewController *scanner = [[BCScannerViewController alloc] init]; scanner.delegate = self; scanner.codeTypes = @[ BCScannerQRCode ]; diff --git a/DogeKeeper/AnnouncementHandler.h b/DogeKeeper/AnnouncementHandler.h new file mode 100644 index 0000000..b70ea57 --- /dev/null +++ b/DogeKeeper/AnnouncementHandler.h @@ -0,0 +1,21 @@ +// +// AnnouncementHandler.h +// DogeKeeper +// +// Created by Andrew on 7/29/14. +// Copyright (c) 2014 Andrew Arpasi. All rights reserved. +// + +#import + +@interface AnnouncementHandler : NSObject + ++(NSString*)makeUrlRequest:(NSURL*)requestURL; ++(BOOL)isUrgentAnnouncement; ++(BOOL)readUrgentAnnouncement; ++(void)markAsRead; ++(void)markAsRead:(NSString*)announcementid; ++(NSString*)getAnnouncementID; + + +@end diff --git a/DogeKeeper/AnnouncementHandler.m b/DogeKeeper/AnnouncementHandler.m new file mode 100644 index 0000000..d794cff --- /dev/null +++ b/DogeKeeper/AnnouncementHandler.m @@ -0,0 +1,61 @@ +// +// AnnouncementHandler.m +// DogeKeeper +// +// Created by Andrew on 7/29/14. +// Copyright (c) 2014 Andrew Arpasi. All rights reserved. +// + +#import "AnnouncementHandler.h" + +@implementation AnnouncementHandler + ++(NSString*)makeUrlRequest:(NSURL*)requestURL +{ + [[NSURLCache sharedURLCache] removeAllCachedResponses]; + NSURLRequest* request = [NSURLRequest requestWithURL:requestURL cachePolicy:0 timeoutInterval:15]; + NSData* data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; + NSString* stringFromServer = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + return stringFromServer; +} ++(BOOL)isUrgentAnnouncement +{ + NSString * idresponse = [self makeUrlRequest:[[NSURL alloc] initWithString:@"http://dogekeeper.com/urgent.php?a=id"]]; + NSLog(@"idresponse: %@",idresponse); + NSString * contentresponse = [self makeUrlRequest:[[NSURL alloc] initWithString:@"http://dogekeeper.com/urgent.php"]]; + NSLog(@"cr: %@",contentresponse); + if([idresponse isEqualToString:@"0"] || [contentresponse rangeOfString:@""].location == NSNotFound) + { + NSLog(@"not urgent"); + return FALSE; + } + return TRUE; + NSLog(@"urgent"); +} ++(BOOL)readUrgentAnnouncement +{ + if([[self getAnnouncementID] isEqualToString:[[NSUserDefaults standardUserDefaults] objectForKey:@"lastannouncement"]]) + { + return TRUE; + } + return FALSE; +} ++(void)markAsRead +{ + NSString * announcementid = [self getAnnouncementID]; + [[NSUserDefaults standardUserDefaults] setObject:announcementid forKey:@"lastannouncement"]; +} ++(NSString*)getAnnouncementID +{ + NSString * idresponse = [self makeUrlRequest:[[NSURL alloc] initWithString:@"http://dogekeeper.com/urgent.php?a=id"]]; + if(idresponse.length < 4) + { + return idresponse; + } + else + { + return FALSE; + } +} + +@end diff --git a/DogeKeeper/AnnouncementViewController.h b/DogeKeeper/AnnouncementViewController.h new file mode 100644 index 0000000..d78155e --- /dev/null +++ b/DogeKeeper/AnnouncementViewController.h @@ -0,0 +1,16 @@ +// +// AnnouncementViewController.h +// DogeKeeper +// +// Created by Andrew on 7/29/14. +// Copyright (c) 2014 Andrew Arpasi. All rights reserved. +// + +#import +#import "AnnouncementHandler.h" + +@interface AnnouncementViewController : UIViewController +{ + IBOutlet UIWebView * announcementView; +} +@end diff --git a/DogeKeeper/AnnouncementViewController.m b/DogeKeeper/AnnouncementViewController.m new file mode 100644 index 0000000..8aeb77d --- /dev/null +++ b/DogeKeeper/AnnouncementViewController.m @@ -0,0 +1,61 @@ +// +// AnnouncementViewController.m +// DogeKeeper +// +// Created by Andrew on 7/29/14. +// Copyright (c) 2014 Andrew Arpasi. All rights reserved. +// + +#import "AnnouncementViewController.h" + +@interface AnnouncementViewController () + +@end + +@implementation AnnouncementViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + NSURLRequest * request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString: @"http://dogekeeper.com/news.php"] cachePolicy:0 timeoutInterval:20]; + [announcementView loadRequest:request]; + // Do any additional setup after loading the view. +} +-(IBAction)close:(id)sender +{ + [self dismissViewControllerAnimated:true completion:nil]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, + (unsigned long)NULL), ^(void) { + if(![AnnouncementHandler readUrgentAnnouncement]) + { + [AnnouncementHandler markAsRead]; + } + }); +} +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/DogeKeeper/AppDelegate.h b/DogeKeeper/AppDelegate.h index cc2b095..83b7569 100644 --- a/DogeKeeper/AppDelegate.h +++ b/DogeKeeper/AppDelegate.h @@ -7,7 +7,6 @@ // #import -#import "EncryptionHelper.h" @interface AppDelegate : UIResponder diff --git a/DogeKeeper/Base.lproj/Main_iPhone.storyboard b/DogeKeeper/Base.lproj/Main_iPhone.storyboard index 2beba32..07b9cba 100644 --- a/DogeKeeper/Base.lproj/Main_iPhone.storyboard +++ b/DogeKeeper/Base.lproj/Main_iPhone.storyboard @@ -58,7 +58,7 @@ -