├── LICENSE ├── O2SECCKit.podspec ├── O2SECCKit ├── O2SECCKit.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── wkx.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ ├── xcshareddata │ │ └── xcschemes │ │ │ ├── O2SECCKit.xcscheme │ │ │ └── O2SECCKitTests.xcscheme │ └── xcuserdata │ │ └── wkx.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── O2SECCKit │ ├── BigInt │ │ ├── O2SBigInt.h │ │ ├── O2SBigInt.mm │ │ ├── O2SCalculator.h │ │ └── O2SCalculator.m │ ├── EC_Fp │ │ ├── O2SECCurveFp.h │ │ ├── O2SECCurveFp.m │ │ ├── O2SECFieldElementFp.h │ │ ├── O2SECFieldElementFp.m │ │ ├── O2SECPointFp.h │ │ └── O2SECPointFp.m │ ├── Info.plist │ ├── O2SECCKit.h │ ├── O2SSMxHelper.h │ ├── O2SSMxHelper.m │ ├── O2SSMxUtils.h │ ├── O2SSMxUtils.m │ ├── SM2 │ │ ├── O2SSM2Cipher+Private.h │ │ ├── O2SSM2Cipher.h │ │ └── O2SSM2Cipher.m │ └── SM3 │ │ ├── O2SSM3Digest.h │ │ └── O2SSM3Digest.mm └── O2SECCKitTests │ ├── Info.plist │ └── O2SECCKitTests.m ├── O2SECCKitDemo ├── O2SECCKitDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── wkx.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── wkx.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── O2SECCKitDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── SceneDelegate.h │ ├── SceneDelegate.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── O2SECCKitProject.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── wkx.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── O2SPACE_SDK └── O2SECCSDK │ └── O2SECCKit.framework │ ├── Headers │ ├── O2SECCKit.h │ ├── O2SSM2Cipher.h │ ├── O2SSMxHelper.h │ └── O2SSMxUtils.h │ ├── Info.plist │ ├── Modules │ └── module.modulemap │ └── O2SECCKit ├── README.md ├── README_FILE ├── sm2_privatekey.jpg ├── sm2_privatekey_min.jpg ├── sm2_publickey.jpg └── sm2_publickey_min.jpg └── 参考文献 ├── SM2公钥密码加密.pdf ├── SM2椭圆曲线公钥密码算法推荐曲线参数.pdf ├── sm2官网pdf里面包含4部分每部分有单独目录.pdf └── 二元域椭圆曲线加密算法.pdf /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2020 O2Space -------------------------------------------------------------------------------- /O2SECCKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'O2SECCKit' 3 | s.version = "1.0.0" 4 | s.summary = 'iOS 椭圆曲线SM2加解密、签验及SM3摘要,不依赖第三方OpenSSL' 5 | s.license = 'MIT' 6 | s.author = { "o2space" => "o2space@163.com" } 7 | 8 | s.homepage = 'http://www.by2code.com' 9 | s.source = { :git => 'https://github.com/o2space/O2SECCKit.git', :tag => s.version.to_s } 10 | s.platform = :ios 11 | s.ios.deployment_target = "8.0" 12 | s.libraries = 'c++' 13 | s.default_subspecs = 'O2SECCKit' 14 | 15 | # 核心模块 16 | s.subspec 'O2SECCKit' do |sp| 17 | sp.vendored_frameworks = 'O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework' 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | 0B6432C02493344400A1A965 /* O2SECCKit_CreatePackage */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = 0B6432C12493344400A1A965 /* Build configuration list for PBXAggregateTarget "O2SECCKit_CreatePackage" */; 13 | buildPhases = ( 14 | 0B6432C42493345F00A1A965 /* ShellScript */, 15 | ); 16 | dependencies = ( 17 | ); 18 | name = O2SECCKit_CreatePackage; 19 | productName = O2SECCKit_CreatePackage; 20 | }; 21 | /* End PBXAggregateTarget section */ 22 | 23 | /* Begin PBXBuildFile section */ 24 | 0B6432B02493329400A1A965 /* O2SECCKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6432A62493329400A1A965 /* O2SECCKit.framework */; }; 25 | 0B6432B52493329400A1A965 /* O2SECCKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432B42493329400A1A965 /* O2SECCKitTests.m */; }; 26 | 0B6432B72493329400A1A965 /* O2SECCKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432A92493329400A1A965 /* O2SECCKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27 | 0B6432C8249335CB00A1A965 /* O2SBigInt.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432C6249335CB00A1A965 /* O2SBigInt.h */; }; 28 | 0B6432C9249335CB00A1A965 /* O2SBigInt.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432C7249335CB00A1A965 /* O2SBigInt.mm */; }; 29 | 0B6432CC2493669400A1A965 /* O2SCalculator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432CA2493669400A1A965 /* O2SCalculator.h */; }; 30 | 0B6432CD2493669400A1A965 /* O2SCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432CB2493669400A1A965 /* O2SCalculator.m */; }; 31 | 0B6432D12493820600A1A965 /* O2SSMxHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432CF2493820600A1A965 /* O2SSMxHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32 | 0B6432D22493820600A1A965 /* O2SSMxHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432D02493820600A1A965 /* O2SSMxHelper.m */; }; 33 | 0B6432DC2493899E00A1A965 /* O2SECPointFp.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432DA2493899E00A1A965 /* O2SECPointFp.h */; }; 34 | 0B6432DD2493899E00A1A965 /* O2SECPointFp.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432DB2493899E00A1A965 /* O2SECPointFp.m */; }; 35 | 0B6432E0249389D300A1A965 /* O2SECFieldElementFp.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432DE249389D300A1A965 /* O2SECFieldElementFp.h */; }; 36 | 0B6432E1249389D300A1A965 /* O2SECFieldElementFp.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432DF249389D300A1A965 /* O2SECFieldElementFp.m */; }; 37 | 0B6432E4249389F100A1A965 /* O2SECCurveFp.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432E2249389F100A1A965 /* O2SECCurveFp.h */; }; 38 | 0B6432E5249389F100A1A965 /* O2SECCurveFp.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432E3249389F100A1A965 /* O2SECCurveFp.m */; }; 39 | 0B6432E824939B9E00A1A965 /* O2SSMxUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432E624939B9E00A1A965 /* O2SSMxUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; 40 | 0B6432E924939B9E00A1A965 /* O2SSMxUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432E724939B9E00A1A965 /* O2SSMxUtils.m */; }; 41 | 0B6432F72493A7D200A1A965 /* O2SSM2Cipher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432F12493A7D200A1A965 /* O2SSM2Cipher.m */; }; 42 | 0B6432F82493A7D200A1A965 /* O2SSM2Cipher+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432F22493A7D200A1A965 /* O2SSM2Cipher+Private.h */; }; 43 | 0B6432F92493A7D200A1A965 /* O2SSM2Cipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432F32493A7D200A1A965 /* O2SSM2Cipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 44 | 0B6432FA2493A7D200A1A965 /* O2SSM3Digest.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B6432F52493A7D200A1A965 /* O2SSM3Digest.h */; }; 45 | 0B6432FB2493A7D200A1A965 /* O2SSM3Digest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0B6432F62493A7D200A1A965 /* O2SSM3Digest.mm */; }; 46 | 0B6433272493B13500A1A965 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6433262493B13500A1A965 /* libc++.tbd */; }; 47 | /* End PBXBuildFile section */ 48 | 49 | /* Begin PBXContainerItemProxy section */ 50 | 0B6432B12493329400A1A965 /* PBXContainerItemProxy */ = { 51 | isa = PBXContainerItemProxy; 52 | containerPortal = 0B64329D2493329400A1A965 /* Project object */; 53 | proxyType = 1; 54 | remoteGlobalIDString = 0B6432A52493329400A1A965; 55 | remoteInfo = O2SECCKit; 56 | }; 57 | /* End PBXContainerItemProxy section */ 58 | 59 | /* Begin PBXFileReference section */ 60 | 0B6432A62493329400A1A965 /* O2SECCKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = O2SECCKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 0B6432A92493329400A1A965 /* O2SECCKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SECCKit.h; sourceTree = ""; }; 62 | 0B6432AA2493329400A1A965 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 0B6432AF2493329400A1A965 /* O2SECCKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = O2SECCKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 0B6432B42493329400A1A965 /* O2SECCKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = O2SECCKitTests.m; sourceTree = ""; }; 65 | 0B6432B62493329400A1A965 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 66 | 0B6432C6249335CB00A1A965 /* O2SBigInt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SBigInt.h; sourceTree = ""; }; 67 | 0B6432C7249335CB00A1A965 /* O2SBigInt.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = O2SBigInt.mm; sourceTree = ""; }; 68 | 0B6432CA2493669400A1A965 /* O2SCalculator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SCalculator.h; sourceTree = ""; }; 69 | 0B6432CB2493669400A1A965 /* O2SCalculator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = O2SCalculator.m; sourceTree = ""; }; 70 | 0B6432CF2493820600A1A965 /* O2SSMxHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SSMxHelper.h; sourceTree = ""; }; 71 | 0B6432D02493820600A1A965 /* O2SSMxHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = O2SSMxHelper.m; sourceTree = ""; }; 72 | 0B6432DA2493899E00A1A965 /* O2SECPointFp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SECPointFp.h; sourceTree = ""; }; 73 | 0B6432DB2493899E00A1A965 /* O2SECPointFp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = O2SECPointFp.m; sourceTree = ""; }; 74 | 0B6432DE249389D300A1A965 /* O2SECFieldElementFp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SECFieldElementFp.h; sourceTree = ""; }; 75 | 0B6432DF249389D300A1A965 /* O2SECFieldElementFp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = O2SECFieldElementFp.m; sourceTree = ""; }; 76 | 0B6432E2249389F100A1A965 /* O2SECCurveFp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SECCurveFp.h; sourceTree = ""; }; 77 | 0B6432E3249389F100A1A965 /* O2SECCurveFp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = O2SECCurveFp.m; sourceTree = ""; }; 78 | 0B6432E624939B9E00A1A965 /* O2SSMxUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = O2SSMxUtils.h; sourceTree = ""; }; 79 | 0B6432E724939B9E00A1A965 /* O2SSMxUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = O2SSMxUtils.m; sourceTree = ""; }; 80 | 0B6432F12493A7D200A1A965 /* O2SSM2Cipher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = O2SSM2Cipher.m; sourceTree = ""; }; 81 | 0B6432F22493A7D200A1A965 /* O2SSM2Cipher+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "O2SSM2Cipher+Private.h"; sourceTree = ""; }; 82 | 0B6432F32493A7D200A1A965 /* O2SSM2Cipher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = O2SSM2Cipher.h; sourceTree = ""; }; 83 | 0B6432F52493A7D200A1A965 /* O2SSM3Digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = O2SSM3Digest.h; sourceTree = ""; }; 84 | 0B6432F62493A7D200A1A965 /* O2SSM3Digest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = O2SSM3Digest.mm; sourceTree = ""; }; 85 | 0B6433262493B13500A1A965 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/lib/libc++.tbd"; sourceTree = DEVELOPER_DIR; }; 86 | /* End PBXFileReference section */ 87 | 88 | /* Begin PBXFrameworksBuildPhase section */ 89 | 0B6432A32493329400A1A965 /* Frameworks */ = { 90 | isa = PBXFrameworksBuildPhase; 91 | buildActionMask = 2147483647; 92 | files = ( 93 | 0B6433272493B13500A1A965 /* libc++.tbd in Frameworks */, 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | 0B6432AC2493329400A1A965 /* Frameworks */ = { 98 | isa = PBXFrameworksBuildPhase; 99 | buildActionMask = 2147483647; 100 | files = ( 101 | 0B6432B02493329400A1A965 /* O2SECCKit.framework in Frameworks */, 102 | ); 103 | runOnlyForDeploymentPostprocessing = 0; 104 | }; 105 | /* End PBXFrameworksBuildPhase section */ 106 | 107 | /* Begin PBXGroup section */ 108 | 0B64329C2493329400A1A965 = { 109 | isa = PBXGroup; 110 | children = ( 111 | 0B6432A82493329400A1A965 /* O2SECCKit */, 112 | 0B6432B32493329400A1A965 /* O2SECCKitTests */, 113 | 0B6432A72493329400A1A965 /* Products */, 114 | 0B6433252493B13500A1A965 /* Frameworks */, 115 | ); 116 | sourceTree = ""; 117 | }; 118 | 0B6432A72493329400A1A965 /* Products */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 0B6432A62493329400A1A965 /* O2SECCKit.framework */, 122 | 0B6432AF2493329400A1A965 /* O2SECCKitTests.xctest */, 123 | ); 124 | name = Products; 125 | sourceTree = ""; 126 | }; 127 | 0B6432A82493329400A1A965 /* O2SECCKit */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 0B6432A92493329400A1A965 /* O2SECCKit.h */, 131 | 0B6432CF2493820600A1A965 /* O2SSMxHelper.h */, 132 | 0B6432D02493820600A1A965 /* O2SSMxHelper.m */, 133 | 0B6432E624939B9E00A1A965 /* O2SSMxUtils.h */, 134 | 0B6432E724939B9E00A1A965 /* O2SSMxUtils.m */, 135 | 0B6432F02493A7D200A1A965 /* SM2 */, 136 | 0B6432F42493A7D200A1A965 /* SM3 */, 137 | 0B6432D82493864A00A1A965 /* EC_Fp */, 138 | 0B6432D92493866900A1A965 /* EC_F2m */, 139 | 0B6432C52493358500A1A965 /* BigInt */, 140 | 0B6432AA2493329400A1A965 /* Info.plist */, 141 | ); 142 | path = O2SECCKit; 143 | sourceTree = ""; 144 | }; 145 | 0B6432B32493329400A1A965 /* O2SECCKitTests */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 0B6432B42493329400A1A965 /* O2SECCKitTests.m */, 149 | 0B6432B62493329400A1A965 /* Info.plist */, 150 | ); 151 | path = O2SECCKitTests; 152 | sourceTree = ""; 153 | }; 154 | 0B6432C52493358500A1A965 /* BigInt */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 0B6432C6249335CB00A1A965 /* O2SBigInt.h */, 158 | 0B6432C7249335CB00A1A965 /* O2SBigInt.mm */, 159 | 0B6432CA2493669400A1A965 /* O2SCalculator.h */, 160 | 0B6432CB2493669400A1A965 /* O2SCalculator.m */, 161 | ); 162 | path = BigInt; 163 | sourceTree = ""; 164 | }; 165 | 0B6432D82493864A00A1A965 /* EC_Fp */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 0B6432E2249389F100A1A965 /* O2SECCurveFp.h */, 169 | 0B6432E3249389F100A1A965 /* O2SECCurveFp.m */, 170 | 0B6432DA2493899E00A1A965 /* O2SECPointFp.h */, 171 | 0B6432DB2493899E00A1A965 /* O2SECPointFp.m */, 172 | 0B6432DE249389D300A1A965 /* O2SECFieldElementFp.h */, 173 | 0B6432DF249389D300A1A965 /* O2SECFieldElementFp.m */, 174 | ); 175 | path = EC_Fp; 176 | sourceTree = ""; 177 | }; 178 | 0B6432D92493866900A1A965 /* EC_F2m */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | ); 182 | path = EC_F2m; 183 | sourceTree = ""; 184 | }; 185 | 0B6432F02493A7D200A1A965 /* SM2 */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | 0B6432F32493A7D200A1A965 /* O2SSM2Cipher.h */, 189 | 0B6432F22493A7D200A1A965 /* O2SSM2Cipher+Private.h */, 190 | 0B6432F12493A7D200A1A965 /* O2SSM2Cipher.m */, 191 | ); 192 | path = SM2; 193 | sourceTree = ""; 194 | }; 195 | 0B6432F42493A7D200A1A965 /* SM3 */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | 0B6432F52493A7D200A1A965 /* O2SSM3Digest.h */, 199 | 0B6432F62493A7D200A1A965 /* O2SSM3Digest.mm */, 200 | ); 201 | path = SM3; 202 | sourceTree = ""; 203 | }; 204 | 0B6433252493B13500A1A965 /* Frameworks */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | 0B6433262493B13500A1A965 /* libc++.tbd */, 208 | ); 209 | name = Frameworks; 210 | sourceTree = ""; 211 | }; 212 | /* End PBXGroup section */ 213 | 214 | /* Begin PBXHeadersBuildPhase section */ 215 | 0B6432A12493329400A1A965 /* Headers */ = { 216 | isa = PBXHeadersBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | 0B6432F82493A7D200A1A965 /* O2SSM2Cipher+Private.h in Headers */, 220 | 0B6432D12493820600A1A965 /* O2SSMxHelper.h in Headers */, 221 | 0B6432E824939B9E00A1A965 /* O2SSMxUtils.h in Headers */, 222 | 0B6432F92493A7D200A1A965 /* O2SSM2Cipher.h in Headers */, 223 | 0B6432C8249335CB00A1A965 /* O2SBigInt.h in Headers */, 224 | 0B6432E4249389F100A1A965 /* O2SECCurveFp.h in Headers */, 225 | 0B6432E0249389D300A1A965 /* O2SECFieldElementFp.h in Headers */, 226 | 0B6432B72493329400A1A965 /* O2SECCKit.h in Headers */, 227 | 0B6432DC2493899E00A1A965 /* O2SECPointFp.h in Headers */, 228 | 0B6432CC2493669400A1A965 /* O2SCalculator.h in Headers */, 229 | 0B6432FA2493A7D200A1A965 /* O2SSM3Digest.h in Headers */, 230 | ); 231 | runOnlyForDeploymentPostprocessing = 0; 232 | }; 233 | /* End PBXHeadersBuildPhase section */ 234 | 235 | /* Begin PBXNativeTarget section */ 236 | 0B6432A52493329400A1A965 /* O2SECCKit */ = { 237 | isa = PBXNativeTarget; 238 | buildConfigurationList = 0B6432BA2493329400A1A965 /* Build configuration list for PBXNativeTarget "O2SECCKit" */; 239 | buildPhases = ( 240 | 0B6432A12493329400A1A965 /* Headers */, 241 | 0B6432A22493329400A1A965 /* Sources */, 242 | 0B6432A32493329400A1A965 /* Frameworks */, 243 | 0B6432A42493329400A1A965 /* Resources */, 244 | ); 245 | buildRules = ( 246 | ); 247 | dependencies = ( 248 | ); 249 | name = O2SECCKit; 250 | productName = O2SECCKit; 251 | productReference = 0B6432A62493329400A1A965 /* O2SECCKit.framework */; 252 | productType = "com.apple.product-type.framework"; 253 | }; 254 | 0B6432AE2493329400A1A965 /* O2SECCKitTests */ = { 255 | isa = PBXNativeTarget; 256 | buildConfigurationList = 0B6432BD2493329400A1A965 /* Build configuration list for PBXNativeTarget "O2SECCKitTests" */; 257 | buildPhases = ( 258 | 0B6432AB2493329400A1A965 /* Sources */, 259 | 0B6432AC2493329400A1A965 /* Frameworks */, 260 | 0B6432AD2493329400A1A965 /* Resources */, 261 | ); 262 | buildRules = ( 263 | ); 264 | dependencies = ( 265 | 0B6432B22493329400A1A965 /* PBXTargetDependency */, 266 | ); 267 | name = O2SECCKitTests; 268 | productName = O2SECCKitTests; 269 | productReference = 0B6432AF2493329400A1A965 /* O2SECCKitTests.xctest */; 270 | productType = "com.apple.product-type.bundle.unit-test"; 271 | }; 272 | /* End PBXNativeTarget section */ 273 | 274 | /* Begin PBXProject section */ 275 | 0B64329D2493329400A1A965 /* Project object */ = { 276 | isa = PBXProject; 277 | attributes = { 278 | LastUpgradeCheck = 1130; 279 | ORGANIZATIONNAME = O2Space; 280 | TargetAttributes = { 281 | 0B6432A52493329400A1A965 = { 282 | CreatedOnToolsVersion = 11.3.1; 283 | }; 284 | 0B6432AE2493329400A1A965 = { 285 | CreatedOnToolsVersion = 11.3.1; 286 | }; 287 | 0B6432C02493344400A1A965 = { 288 | CreatedOnToolsVersion = 11.3.1; 289 | }; 290 | }; 291 | }; 292 | buildConfigurationList = 0B6432A02493329400A1A965 /* Build configuration list for PBXProject "O2SECCKit" */; 293 | compatibilityVersion = "Xcode 9.3"; 294 | developmentRegion = en; 295 | hasScannedForEncodings = 0; 296 | knownRegions = ( 297 | en, 298 | Base, 299 | ); 300 | mainGroup = 0B64329C2493329400A1A965; 301 | productRefGroup = 0B6432A72493329400A1A965 /* Products */; 302 | projectDirPath = ""; 303 | projectRoot = ""; 304 | targets = ( 305 | 0B6432A52493329400A1A965 /* O2SECCKit */, 306 | 0B6432AE2493329400A1A965 /* O2SECCKitTests */, 307 | 0B6432C02493344400A1A965 /* O2SECCKit_CreatePackage */, 308 | ); 309 | }; 310 | /* End PBXProject section */ 311 | 312 | /* Begin PBXResourcesBuildPhase section */ 313 | 0B6432A42493329400A1A965 /* Resources */ = { 314 | isa = PBXResourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | ); 318 | runOnlyForDeploymentPostprocessing = 0; 319 | }; 320 | 0B6432AD2493329400A1A965 /* Resources */ = { 321 | isa = PBXResourcesBuildPhase; 322 | buildActionMask = 2147483647; 323 | files = ( 324 | ); 325 | runOnlyForDeploymentPostprocessing = 0; 326 | }; 327 | /* End PBXResourcesBuildPhase section */ 328 | 329 | /* Begin PBXShellScriptBuildPhase section */ 330 | 0B6432C42493345F00A1A965 /* ShellScript */ = { 331 | isa = PBXShellScriptBuildPhase; 332 | buildActionMask = 2147483647; 333 | files = ( 334 | ); 335 | inputFileListPaths = ( 336 | ); 337 | inputPaths = ( 338 | ); 339 | outputFileListPaths = ( 340 | ); 341 | outputPaths = ( 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | shellPath = /bin/sh; 345 | shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n#!/bin/sh\n\nFMK_NAME=${PROJECT_NAME}\n\nINSTALL_BASE_DIR=${PROJECT_DIR}/../O2SPACE_SDK/O2SECCSDK\nINSTALL_DIR=${INSTALL_BASE_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework\n\n# Step 1. Build Device and Simulator versions\n\nxcodebuild -target \"${FMK_NAME}\" clean\n\nxcodebuild -target \"${FMK_NAME}\" -configuration \"Release\" -arch \"arm64\" -arch \"armv7\" -arch \"armv7s\" only_active_arch=no defines_module=yes BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS=\"-fembed-bitcode\" -sdk \"iphoneos\" build\nxcodebuild -target \"${FMK_NAME}\" -configuration \"Release\" -arch \"x86_64\" -arch \"i386\" only_active_arch=no defines_module=yes BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS=\"-fembed-bitcode\" -sdk \"iphonesimulator\" build\n\n# Cleaning the oldest.\nif [ -d \"${INSTALL_DIR}\" ]\nthen\nrm -rf \"${INSTALL_DIR}\"\nfi\nmkdir -p \"${INSTALL_DIR}\"\n\ncp -R \"${DEVICE_DIR}/\" \"${INSTALL_DIR}/\"\n\n# swift编写的Framework使用 \n#SIMULATOR_SWIFT_MODULES_DIR=\"${SIMULATOR_DIR}/Modules/${FMK_NAME}.swiftmodule/.\"\n#if [ -d \"${SIMULATOR_SWIFT_MODULES_DIR}\" ]; then\n#cp -R \"${SIMULATOR_SWIFT_MODULES_DIR}\" \"${INSTALL_DIR}/Modules/${FMK_NAME}.swiftmodule\"\n#fi\n\n# Uses the Lipo Tool to merge both binary files into one Universal final product.\nlipo -create \"${DEVICE_DIR}/${FMK_NAME}\" \"${SIMULATOR_DIR}/${FMK_NAME}\" -output \"${INSTALL_DIR}/${FMK_NAME}\"\n\nrm -r \"${WRK_DIR}\"\n\n"; 346 | }; 347 | /* End PBXShellScriptBuildPhase section */ 348 | 349 | /* Begin PBXSourcesBuildPhase section */ 350 | 0B6432A22493329400A1A965 /* Sources */ = { 351 | isa = PBXSourcesBuildPhase; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | 0B6432CD2493669400A1A965 /* O2SCalculator.m in Sources */, 355 | 0B6432C9249335CB00A1A965 /* O2SBigInt.mm in Sources */, 356 | 0B6432FB2493A7D200A1A965 /* O2SSM3Digest.mm in Sources */, 357 | 0B6432F72493A7D200A1A965 /* O2SSM2Cipher.m in Sources */, 358 | 0B6432DD2493899E00A1A965 /* O2SECPointFp.m in Sources */, 359 | 0B6432E1249389D300A1A965 /* O2SECFieldElementFp.m in Sources */, 360 | 0B6432E924939B9E00A1A965 /* O2SSMxUtils.m in Sources */, 361 | 0B6432E5249389F100A1A965 /* O2SECCurveFp.m in Sources */, 362 | 0B6432D22493820600A1A965 /* O2SSMxHelper.m in Sources */, 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | }; 366 | 0B6432AB2493329400A1A965 /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | 0B6432B52493329400A1A965 /* O2SECCKitTests.m in Sources */, 371 | ); 372 | runOnlyForDeploymentPostprocessing = 0; 373 | }; 374 | /* End PBXSourcesBuildPhase section */ 375 | 376 | /* Begin PBXTargetDependency section */ 377 | 0B6432B22493329400A1A965 /* PBXTargetDependency */ = { 378 | isa = PBXTargetDependency; 379 | target = 0B6432A52493329400A1A965 /* O2SECCKit */; 380 | targetProxy = 0B6432B12493329400A1A965 /* PBXContainerItemProxy */; 381 | }; 382 | /* End PBXTargetDependency section */ 383 | 384 | /* Begin XCBuildConfiguration section */ 385 | 0B6432B82493329400A1A965 /* Debug */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | ALWAYS_SEARCH_USER_PATHS = NO; 389 | CLANG_ANALYZER_NONNULL = YES; 390 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 391 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 392 | CLANG_CXX_LIBRARY = "libc++"; 393 | CLANG_ENABLE_MODULES = YES; 394 | CLANG_ENABLE_OBJC_ARC = YES; 395 | CLANG_ENABLE_OBJC_WEAK = YES; 396 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 397 | CLANG_WARN_BOOL_CONVERSION = YES; 398 | CLANG_WARN_COMMA = YES; 399 | CLANG_WARN_CONSTANT_CONVERSION = YES; 400 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 401 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 402 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 403 | CLANG_WARN_EMPTY_BODY = YES; 404 | CLANG_WARN_ENUM_CONVERSION = YES; 405 | CLANG_WARN_INFINITE_RECURSION = YES; 406 | CLANG_WARN_INT_CONVERSION = YES; 407 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 409 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 412 | CLANG_WARN_STRICT_PROTOTYPES = YES; 413 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 414 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 415 | CLANG_WARN_UNREACHABLE_CODE = YES; 416 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 417 | COPY_PHASE_STRIP = NO; 418 | CURRENT_PROJECT_VERSION = 1; 419 | DEBUG_INFORMATION_FORMAT = dwarf; 420 | ENABLE_STRICT_OBJC_MSGSEND = YES; 421 | ENABLE_TESTABILITY = YES; 422 | GCC_C_LANGUAGE_STANDARD = gnu11; 423 | GCC_DYNAMIC_NO_PIC = NO; 424 | GCC_NO_COMMON_BLOCKS = YES; 425 | GCC_OPTIMIZATION_LEVEL = 0; 426 | GCC_PREPROCESSOR_DEFINITIONS = ( 427 | "DEBUG=1", 428 | "$(inherited)", 429 | ); 430 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 431 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 432 | GCC_WARN_UNDECLARED_SELECTOR = YES; 433 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 434 | GCC_WARN_UNUSED_FUNCTION = YES; 435 | GCC_WARN_UNUSED_VARIABLE = YES; 436 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 437 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 438 | MTL_FAST_MATH = YES; 439 | ONLY_ACTIVE_ARCH = YES; 440 | SDKROOT = iphoneos; 441 | VERSIONING_SYSTEM = "apple-generic"; 442 | VERSION_INFO_PREFIX = ""; 443 | }; 444 | name = Debug; 445 | }; 446 | 0B6432B92493329400A1A965 /* Release */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | ALWAYS_SEARCH_USER_PATHS = NO; 450 | CLANG_ANALYZER_NONNULL = YES; 451 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 452 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 453 | CLANG_CXX_LIBRARY = "libc++"; 454 | CLANG_ENABLE_MODULES = YES; 455 | CLANG_ENABLE_OBJC_ARC = YES; 456 | CLANG_ENABLE_OBJC_WEAK = YES; 457 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 458 | CLANG_WARN_BOOL_CONVERSION = YES; 459 | CLANG_WARN_COMMA = YES; 460 | CLANG_WARN_CONSTANT_CONVERSION = YES; 461 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 462 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 463 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 464 | CLANG_WARN_EMPTY_BODY = YES; 465 | CLANG_WARN_ENUM_CONVERSION = YES; 466 | CLANG_WARN_INFINITE_RECURSION = YES; 467 | CLANG_WARN_INT_CONVERSION = YES; 468 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 469 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 470 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 471 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 472 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 473 | CLANG_WARN_STRICT_PROTOTYPES = YES; 474 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 475 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 476 | CLANG_WARN_UNREACHABLE_CODE = YES; 477 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 478 | COPY_PHASE_STRIP = NO; 479 | CURRENT_PROJECT_VERSION = 1; 480 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 481 | ENABLE_NS_ASSERTIONS = NO; 482 | ENABLE_STRICT_OBJC_MSGSEND = YES; 483 | GCC_C_LANGUAGE_STANDARD = gnu11; 484 | GCC_NO_COMMON_BLOCKS = YES; 485 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 486 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 487 | GCC_WARN_UNDECLARED_SELECTOR = YES; 488 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 489 | GCC_WARN_UNUSED_FUNCTION = YES; 490 | GCC_WARN_UNUSED_VARIABLE = YES; 491 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 492 | MTL_ENABLE_DEBUG_INFO = NO; 493 | MTL_FAST_MATH = YES; 494 | SDKROOT = iphoneos; 495 | VALIDATE_PRODUCT = YES; 496 | VERSIONING_SYSTEM = "apple-generic"; 497 | VERSION_INFO_PREFIX = ""; 498 | }; 499 | name = Release; 500 | }; 501 | 0B6432BB2493329400A1A965 /* Debug */ = { 502 | isa = XCBuildConfiguration; 503 | buildSettings = { 504 | CODE_SIGN_STYLE = Automatic; 505 | DEFINES_MODULE = YES; 506 | DYLIB_COMPATIBILITY_VERSION = ""; 507 | DYLIB_CURRENT_VERSION = ""; 508 | DYLIB_INSTALL_NAME_BASE = ""; 509 | INFOPLIST_FILE = O2SECCKit/Info.plist; 510 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 511 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 512 | LD_RUNPATH_SEARCH_PATHS = ""; 513 | MACH_O_TYPE = mh_object; 514 | PRODUCT_BUNDLE_IDENTIFIER = com.O2Space.O2SECCKit; 515 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 516 | SKIP_INSTALL = YES; 517 | SUPPORTS_MACCATALYST = YES; 518 | TARGETED_DEVICE_FAMILY = "1,2"; 519 | }; 520 | name = Debug; 521 | }; 522 | 0B6432BC2493329400A1A965 /* Release */ = { 523 | isa = XCBuildConfiguration; 524 | buildSettings = { 525 | CODE_SIGN_STYLE = Automatic; 526 | DEFINES_MODULE = YES; 527 | DYLIB_COMPATIBILITY_VERSION = ""; 528 | DYLIB_CURRENT_VERSION = ""; 529 | DYLIB_INSTALL_NAME_BASE = ""; 530 | INFOPLIST_FILE = O2SECCKit/Info.plist; 531 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 532 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 533 | LD_RUNPATH_SEARCH_PATHS = ""; 534 | MACH_O_TYPE = mh_object; 535 | PRODUCT_BUNDLE_IDENTIFIER = com.O2Space.O2SECCKit; 536 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 537 | SKIP_INSTALL = YES; 538 | SUPPORTS_MACCATALYST = YES; 539 | TARGETED_DEVICE_FAMILY = "1,2"; 540 | }; 541 | name = Release; 542 | }; 543 | 0B6432BE2493329400A1A965 /* Debug */ = { 544 | isa = XCBuildConfiguration; 545 | buildSettings = { 546 | CODE_SIGN_STYLE = Automatic; 547 | FRAMEWORK_SEARCH_PATHS = ""; 548 | INFOPLIST_FILE = O2SECCKitTests/Info.plist; 549 | LD_RUNPATH_SEARCH_PATHS = ( 550 | "$(inherited)", 551 | "@executable_path/Frameworks", 552 | "@loader_path/Frameworks", 553 | ); 554 | PRODUCT_BUNDLE_IDENTIFIER = com.O2Space.O2SECCKitTests; 555 | PRODUCT_NAME = "$(TARGET_NAME)"; 556 | TARGETED_DEVICE_FAMILY = "1,2"; 557 | }; 558 | name = Debug; 559 | }; 560 | 0B6432BF2493329400A1A965 /* Release */ = { 561 | isa = XCBuildConfiguration; 562 | buildSettings = { 563 | CODE_SIGN_STYLE = Automatic; 564 | FRAMEWORK_SEARCH_PATHS = ""; 565 | INFOPLIST_FILE = O2SECCKitTests/Info.plist; 566 | LD_RUNPATH_SEARCH_PATHS = ( 567 | "$(inherited)", 568 | "@executable_path/Frameworks", 569 | "@loader_path/Frameworks", 570 | ); 571 | PRODUCT_BUNDLE_IDENTIFIER = com.O2Space.O2SECCKitTests; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | TARGETED_DEVICE_FAMILY = "1,2"; 574 | }; 575 | name = Release; 576 | }; 577 | 0B6432C22493344400A1A965 /* Debug */ = { 578 | isa = XCBuildConfiguration; 579 | buildSettings = { 580 | CODE_SIGN_STYLE = Automatic; 581 | PRODUCT_NAME = "$(TARGET_NAME)"; 582 | }; 583 | name = Debug; 584 | }; 585 | 0B6432C32493344400A1A965 /* Release */ = { 586 | isa = XCBuildConfiguration; 587 | buildSettings = { 588 | CODE_SIGN_STYLE = Automatic; 589 | PRODUCT_NAME = "$(TARGET_NAME)"; 590 | }; 591 | name = Release; 592 | }; 593 | /* End XCBuildConfiguration section */ 594 | 595 | /* Begin XCConfigurationList section */ 596 | 0B6432A02493329400A1A965 /* Build configuration list for PBXProject "O2SECCKit" */ = { 597 | isa = XCConfigurationList; 598 | buildConfigurations = ( 599 | 0B6432B82493329400A1A965 /* Debug */, 600 | 0B6432B92493329400A1A965 /* Release */, 601 | ); 602 | defaultConfigurationIsVisible = 0; 603 | defaultConfigurationName = Release; 604 | }; 605 | 0B6432BA2493329400A1A965 /* Build configuration list for PBXNativeTarget "O2SECCKit" */ = { 606 | isa = XCConfigurationList; 607 | buildConfigurations = ( 608 | 0B6432BB2493329400A1A965 /* Debug */, 609 | 0B6432BC2493329400A1A965 /* Release */, 610 | ); 611 | defaultConfigurationIsVisible = 0; 612 | defaultConfigurationName = Release; 613 | }; 614 | 0B6432BD2493329400A1A965 /* Build configuration list for PBXNativeTarget "O2SECCKitTests" */ = { 615 | isa = XCConfigurationList; 616 | buildConfigurations = ( 617 | 0B6432BE2493329400A1A965 /* Debug */, 618 | 0B6432BF2493329400A1A965 /* Release */, 619 | ); 620 | defaultConfigurationIsVisible = 0; 621 | defaultConfigurationName = Release; 622 | }; 623 | 0B6432C12493344400A1A965 /* Build configuration list for PBXAggregateTarget "O2SECCKit_CreatePackage" */ = { 624 | isa = XCConfigurationList; 625 | buildConfigurations = ( 626 | 0B6432C22493344400A1A965 /* Debug */, 627 | 0B6432C32493344400A1A965 /* Release */, 628 | ); 629 | defaultConfigurationIsVisible = 0; 630 | defaultConfigurationName = Release; 631 | }; 632 | /* End XCConfigurationList section */ 633 | }; 634 | rootObject = 0B64329D2493329400A1A965 /* Project object */; 635 | } 636 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit.xcodeproj/project.xcworkspace/xcuserdata/wkx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/O2SECCKit/O2SECCKit.xcodeproj/project.xcworkspace/xcuserdata/wkx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit.xcodeproj/xcshareddata/xcschemes/O2SECCKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit.xcodeproj/xcshareddata/xcschemes/O2SECCKitTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit.xcodeproj/xcuserdata/wkx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | O2SECCKit.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | O2SECCKitTests.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 1 16 | 17 | O2SECCKit_CreatePackage.xcscheme 18 | 19 | orderHint 20 | 2 21 | 22 | O2SECCKit_CreatePackage.xcscheme_^#shared#^_ 23 | 24 | orderHint 25 | 2 26 | 27 | 28 | SuppressBuildableAutocreation 29 | 30 | 0B6432A52493329400A1A965 31 | 32 | primary 33 | 34 | 35 | 0B6432AE2493329400A1A965 36 | 37 | primary 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/BigInt/O2SBigInt.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SBigInt.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface O2SBigInt : NSObject 12 | 13 | #pragma mark - 大数对象 初始化 14 | 15 | /// 初始化大数对象 16 | /// @return 大数对象 17 | - (instancetype)init; 18 | 19 | /// 初始化大数对象 20 | /// @param value 整型数据 21 | /// @return 大数对象 22 | - (instancetype)initWithInt:(NSInteger)value; 23 | 24 | /// 初始化大数对象 25 | /// @param value 大数对象 26 | /// @return 大数对象 27 | - (instancetype)initWithBigInteger:(O2SBigInt *)value; 28 | 29 | /// 初始化大数对象 30 | /// @param valueString 数值字符串 31 | /// @return 大数对象 32 | - (instancetype)initWithString:(NSString *)valueString; 33 | 34 | /// 初始化大数对象 35 | /// @param valueString 数值字符串 36 | /// @param radix 进制 37 | /// @return 大数对象 38 | - (instancetype)initWithString:(NSString *)valueString radix:(int)radix; 39 | 40 | /// 初始化大数对象 41 | /// @param bits 大素数位数 42 | /// @return 大数对象 43 | - (instancetype)initWithRandomPremeBits:(int)bits; 44 | 45 | /// 初始化大数对象 46 | /// @param bits 位数 47 | /// @return 大数对象 48 | - (instancetype)initWithRandomBits:(int)bits; 49 | 50 | /// 初始化大数对象 51 | /// @param bytes 字节流 52 | /// @param size 长度 53 | /// @return 大数对象 54 | - (instancetype)initWithBytes:(const void *)bytes size:(int)size; 55 | 56 | /// 初始化大数对象 57 | /// @param bytes 无符号字节流 58 | /// @param size 长度 59 | /// @return 大数对象 60 | - (instancetype)initWithUnsignedBytes:(const void *)bytes size:(int)size; 61 | 62 | #pragma mark - 特殊大数对象 0,1 63 | 64 | /// 获取 0 65 | /// @return 大数对象 66 | + (O2SBigInt *)zero; 67 | 68 | /// 获取 1 69 | /// @return 大数对象 70 | + (O2SBigInt *)one; 71 | 72 | #pragma mark - 大数运算 73 | 74 | #pragma mark 加: 75 | 76 | /// 大数相加 77 | /// @param value 大数对象 78 | /// @return 大数对象 79 | - (O2SBigInt *)addByBigInt:(O2SBigInt *)value; 80 | 81 | /// 大数相加 82 | /// @param value 整数 83 | /// @return 大数对象 84 | - (O2SBigInt *)addByInt:(NSInteger)value; 85 | 86 | #pragma mark 减: 87 | 88 | /// 大数相减 89 | /// @param value 大数对象 90 | /// @return 大数对象 91 | - (O2SBigInt *)subByBigInt:(O2SBigInt *)value; 92 | 93 | /// 大数相减 94 | /// @param value 整数 95 | /// @return 大数对象 96 | - (O2SBigInt *)subByInt:(NSInteger)value; 97 | 98 | #pragma mark 乘: 99 | 100 | /// 大数相乘 101 | /// @param value 大数对象 102 | /// @return 大数对象 103 | - (O2SBigInt *)multiplyByBigInt:(O2SBigInt *)value; 104 | 105 | /// 大数相乘 106 | /// @param value 整数 107 | /// @return 大数对象 108 | - (O2SBigInt *)multiplyByInt:(NSInteger)value; 109 | 110 | #pragma mark 除: 111 | 112 | /// 大数相除 113 | /// @param value 大数对象 114 | /// @return 大数对象 115 | - (O2SBigInt *)divideByBigInt:(O2SBigInt *)value; 116 | 117 | /// 大数相除 118 | /// @param value 整数 119 | /// @return 大数对象 120 | - (O2SBigInt *)divideByInt:(NSInteger)value; 121 | 122 | #pragma mark 求余: 123 | 124 | /// 大数求余 125 | /// @param value 大数对象 126 | /// @return 大数对象 127 | - (O2SBigInt *)reminderByBigInt:(O2SBigInt *)value; 128 | 129 | /// 大数求余 130 | /// @param value 整数 131 | /// @return 大数对象 132 | - (O2SBigInt *)reminderByInt:(NSInteger)value; 133 | 134 | #pragma mark 幂运算: 135 | 136 | /// 大数幂运算 137 | /// @param exponent 指数 138 | /// @return 大数对象 139 | - (O2SBigInt *)pow:(NSUInteger)exponent; 140 | 141 | #pragma mark 幂运算求余: 142 | 143 | /// 大数幂运算求余 144 | /// @param exponent 指数 145 | /// @param value 模数 146 | /// @return 大数对象 147 | - (O2SBigInt *)pow:(O2SBigInt *)exponent mod:(O2SBigInt *)value; 148 | 149 | #pragma mark 平方: 150 | 151 | /// 大数平方运算 152 | /// @return 大数对象 153 | - (O2SBigInt *)square; 154 | 155 | #pragma mark 平方根: 156 | 157 | /// 大数平方根运算 158 | /// @return 大数对象 159 | - (O2SBigInt *)sqrt; 160 | 161 | #pragma mark 求反: 162 | 163 | /// 大数求反 164 | /// @return 大数对象 165 | - (O2SBigInt *)negate; 166 | 167 | #pragma mark 绝对值: 168 | 169 | /// 大数绝对值 170 | /// @return 大数对象 171 | - (O2SBigInt *)abs; 172 | 173 | #pragma mark 异或: 174 | 175 | /// 大数位异或 176 | /// @param value 大数对象 177 | /// @return 大数对象 178 | - (O2SBigInt *)bitwiseXorByBigInt:(O2SBigInt *)value; 179 | 180 | /// 大数位异或 181 | /// @param value 整数 182 | /// @return 大数对象 183 | - (O2SBigInt *)bitwiseXorByInt:(NSInteger)value; 184 | 185 | #pragma mark 或: 186 | 187 | /// 大数或 188 | /// @param value 大数对象 189 | /// @return 大数对象 190 | - (O2SBigInt *)bitwiseOrByBigInt:(O2SBigInt *)value; 191 | 192 | /// 大数或 193 | /// @param value 整数 194 | /// @return 大数对象 195 | - (O2SBigInt *)bitwiseOrByInt:(NSInteger)value; 196 | 197 | #pragma mark 与: 198 | 199 | /// 大数与 200 | /// @param value 大数对象 201 | /// @return 大数对象 202 | - (O2SBigInt *)bitwiseAndByBigInt:(O2SBigInt *)value; 203 | 204 | /// 大数与 205 | /// @param value 整数 206 | /// @return 大数对象 207 | - (O2SBigInt *)bitwiseAndByInt:(NSInteger)value; 208 | 209 | #pragma mark 左移: 210 | 211 | /// 左移 212 | /// @param num 左移位数 213 | /// @return 大数对象 214 | - (O2SBigInt *)shiftLeft:(int)num; 215 | 216 | #pragma mark 右移: 217 | 218 | /// 右移 219 | /// @param num 右移位数 220 | /// @return 大数对象 221 | - (O2SBigInt *)shiftRight:(int)num; 222 | 223 | #pragma mark 最大公约数: 224 | 225 | /// 最大公约数 226 | /// @param value 大数对象 227 | /// @return 大数对象 228 | - (O2SBigInt *)gcdByBigInt:(O2SBigInt *)value; 229 | 230 | /// 最大公约数 231 | /// @param value 整数 232 | /// @return 大数对象 233 | - (O2SBigInt *)gcdByInt:(NSInteger)value; 234 | 235 | #pragma mark 余逆: 236 | 237 | /// 大数求余逆 238 | /// @param n 阶数 239 | /// @return 大数对象 240 | - (O2SBigInt *)modInverseByBigInt:(O2SBigInt *)n; 241 | 242 | /// 大数求余逆 243 | /// @param n 阶数 244 | /// @return 大数对象 245 | - (O2SBigInt *)modInverseByInt:(NSInteger)n; 246 | 247 | #pragma mark 余: 248 | 249 | /// 大数求余 250 | /// @param n 阶数 251 | /// @return 大数对象 252 | - (O2SBigInt *)modByBigInt:(O2SBigInt *)n; 253 | 254 | /// 大数求余 255 | /// @param n 阶数 256 | /// @return 大数对象 257 | - (O2SBigInt *)modByInt:(NSInteger)n; 258 | 259 | #pragma mark - Other 260 | 261 | /// 比较 262 | /// @param value 大数对象 263 | /// @return 比较结果 264 | - (NSComparisonResult)compare:(O2SBigInt *)value; 265 | 266 | /// 转换为字符串 267 | /// @return 数值字符串 268 | - (NSString *)toString; 269 | 270 | /// 转换为字符串 271 | /// @param radix 进制 272 | /// @return 字符串 273 | - (NSString *)toString:(int)radix; 274 | 275 | /// 获取字节流 276 | /// @param bytes 字节流 277 | /// @param length 长度 278 | - (void)getBytes:(void **)bytes length:(int *)length; 279 | 280 | /// 获取无符号字节流 281 | /// @param bytes 字节流 282 | /// @param length 长度 283 | - (void)getUnsignBytes:(void **)bytes length:(int *)length; 284 | 285 | - (int)signum; 286 | 287 | - (uint64_t)bitLength; 288 | 289 | - (BOOL)testBit:(uint64_t)index; 290 | 291 | @end 292 | 293 | 294 | /// 商数和余数 295 | @interface O2SBigInt_QuotientAndRemainder : NSObject 296 | 297 | /// 商 298 | @property (nonatomic, strong) O2SBigInt *quotient; 299 | 300 | /// 余数 301 | @property (nonatomic, strong) O2SBigInt *reminder; 302 | 303 | - (instancetype)initWithQuotient:(O2SBigInt *)quotient 304 | reminder:(O2SBigInt *)reminder; 305 | 306 | @end 307 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/BigInt/O2SCalculator.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SCalculator.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "O2SBigInt.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface O2SCalculator : NSObject 15 | 16 | @property (nonatomic, strong, readonly) O2SBigInt *bigInt; 17 | 18 | - (instancetype)initWithBigInt:(nonnull O2SBigInt *)bigInt; 19 | 20 | - (instancetype)init NS_UNAVAILABLE; 21 | + (instancetype)new NS_UNAVAILABLE; 22 | 23 | #pragma mark 加: 24 | @property (nonatomic, strong, readonly) O2SCalculator* (^addByBigInt)(O2SBigInt *value); 25 | @property (nonatomic, strong, readonly) O2SCalculator* (^addByInt)(NSInteger value); 26 | 27 | #pragma mark 减: 28 | @property (nonatomic, strong, readonly) O2SCalculator* (^subByBigInt)(O2SBigInt *value); 29 | @property (nonatomic, strong, readonly) O2SCalculator* (^subByInt)(NSInteger value); 30 | 31 | #pragma mark 乘: 32 | @property (nonatomic, strong, readonly) O2SCalculator* (^multiplyByBigInt)(O2SBigInt *value); 33 | @property (nonatomic, strong, readonly) O2SCalculator* (^multiplyByInt)(NSInteger value); 34 | 35 | #pragma mark 除: 36 | @property (nonatomic, strong, readonly) O2SCalculator* (^divideByBigInt)(O2SBigInt *value); 37 | @property (nonatomic, strong, readonly) O2SCalculator* (^divideByInt)(NSInteger value); 38 | 39 | #pragma mark 求余: 40 | @property (nonatomic, strong, readonly) O2SCalculator* (^reminderByBigInt)(O2SBigInt *value); 41 | @property (nonatomic, strong, readonly) O2SCalculator* (^reminderByInt)(NSInteger value); 42 | 43 | #pragma mark 幂运算: 44 | @property (nonatomic, strong, readonly) O2SCalculator* (^pow)(NSUInteger value); 45 | 46 | #pragma mark 幂运算求余: 47 | @property (nonatomic, strong, readonly) O2SCalculator* (^powByMod)(O2SBigInt *exponent, O2SBigInt *value); 48 | 49 | #pragma mark 异或: 50 | @property (nonatomic, strong, readonly) O2SCalculator* (^bitwiseXorByBigInt)(O2SBigInt *value); 51 | @property (nonatomic, strong, readonly) O2SCalculator* (^bitwiseXorByInt)(NSInteger value); 52 | 53 | #pragma mark 或: 54 | @property (nonatomic, strong, readonly) O2SCalculator* (^bitwiseOrByBigInt)(O2SBigInt *value); 55 | @property (nonatomic, strong, readonly) O2SCalculator* (^bitwiseOrByInt)(NSInteger value); 56 | 57 | #pragma mark 与: 58 | @property (nonatomic, strong, readonly) O2SCalculator* (^bitwiseAndByBigInt)(O2SBigInt *value); 59 | @property (nonatomic, strong, readonly) O2SCalculator* (^bitwiseAndByInt)(NSInteger value); 60 | 61 | #pragma mark 左移: 62 | @property (nonatomic, strong, readonly) O2SCalculator* (^shiftLeft)(int value); 63 | 64 | #pragma mark 右移: 65 | @property (nonatomic, strong, readonly) O2SCalculator* (^shiftRight)(int value); 66 | 67 | #pragma mark 最大公约数 68 | @property (nonatomic, strong, readonly) O2SCalculator* (^gcdByBigInt)(O2SBigInt *value); 69 | @property (nonatomic, strong, readonly) O2SCalculator* (^gcdByInt)(NSInteger value); 70 | 71 | #pragma mark 余逆: 72 | @property (nonatomic, strong, readonly) O2SCalculator* (^modInverseByBigInt)(O2SBigInt *value); 73 | @property (nonatomic, strong, readonly) O2SCalculator* (^modInverseByInt)(NSInteger value); 74 | 75 | #pragma mark 余: 76 | @property (nonatomic, strong, readonly) O2SCalculator* (^modByBigInt)(O2SBigInt *value); 77 | @property (nonatomic, strong, readonly) O2SCalculator* (^modByInt)(NSInteger value); 78 | 79 | #pragma mark 平方: 80 | @property (nonatomic, strong, readonly) O2SCalculator* (^square)(void); 81 | 82 | #pragma mark 平方根: 83 | @property (nonatomic, strong, readonly) O2SCalculator* (^sqrt)(void); 84 | 85 | #pragma mark 求反: 86 | @property (nonatomic, strong, readonly) O2SCalculator* (^negate)(void); 87 | 88 | #pragma mark 绝对值: 89 | @property (nonatomic, strong, readonly) O2SCalculator* (^abs)(void); 90 | 91 | @end 92 | 93 | NS_ASSUME_NONNULL_END 94 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/BigInt/O2SCalculator.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SCalculator.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SCalculator.h" 10 | 11 | @interface O2SCalculator() 12 | 13 | @property (nonatomic, strong) O2SBigInt *bigInt; 14 | 15 | @end 16 | 17 | @implementation O2SCalculator 18 | 19 | - (instancetype)initWithBigInt:(O2SBigInt *)bigInt 20 | { 21 | if (self = [super init]) 22 | { 23 | self.bigInt = bigInt; 24 | } 25 | return self; 26 | } 27 | 28 | #define O2SCALCULATOR_IMPLEMENTATION(MethodName, Type) - (O2SCalculator *(^)(Type value))MethodName\ 29 | {\ 30 | return ^O2SCalculator *(Type value){\ 31 | self.bigInt = [self.bigInt MethodName:value];\ 32 | return self;\ 33 | };\ 34 | }\ 35 | 36 | #pragma mark 加: 37 | O2SCALCULATOR_IMPLEMENTATION(addByBigInt, O2SBigInt *) 38 | O2SCALCULATOR_IMPLEMENTATION(addByInt, NSInteger) 39 | // 原始 40 | //- (O2SCalculator *(^)(O2SBigInt *value))addByBigInt 41 | //{ 42 | // return ^O2SCalculator *(O2SBigInt *value){ 43 | // self.bigInt = [self.bigInt addByBigInt:value]; 44 | // return self; 45 | // }; 46 | //} 47 | 48 | //- (O2SCalculator *(^)(NSInteger value))addByInt 49 | //{ 50 | // return ^O2SCalculator *(NSInteger value){ 51 | // self.bigInt = [self.bigInt addByInt:value]; 52 | // return self; 53 | // }; 54 | //} 55 | 56 | #pragma mark 减: 57 | O2SCALCULATOR_IMPLEMENTATION(subByBigInt, O2SBigInt *) 58 | O2SCALCULATOR_IMPLEMENTATION(subByInt, NSInteger) 59 | 60 | #pragma mark 乘: 61 | O2SCALCULATOR_IMPLEMENTATION(multiplyByBigInt, O2SBigInt *) 62 | O2SCALCULATOR_IMPLEMENTATION(multiplyByInt, NSInteger) 63 | 64 | #pragma mark 除: 65 | O2SCALCULATOR_IMPLEMENTATION(divideByBigInt, O2SBigInt *) 66 | O2SCALCULATOR_IMPLEMENTATION(divideByInt, NSInteger) 67 | 68 | 69 | #pragma mark 求余: 70 | O2SCALCULATOR_IMPLEMENTATION(reminderByBigInt, O2SBigInt *) 71 | O2SCALCULATOR_IMPLEMENTATION(reminderByInt, NSInteger) 72 | 73 | //#pragma mark 幂运算: 74 | O2SCALCULATOR_IMPLEMENTATION(pow, NSUInteger) 75 | 76 | #pragma mark 幂运算求余: 77 | - (O2SCalculator *(^)(O2SBigInt *exponent, O2SBigInt *value))powByMod 78 | { 79 | return ^O2SCalculator *(O2SBigInt *exponent, O2SBigInt *value){ 80 | self.bigInt = [self.bigInt pow:exponent mod:value]; 81 | return self; 82 | }; 83 | } 84 | 85 | #pragma mark 异或: 86 | O2SCALCULATOR_IMPLEMENTATION(bitwiseXorByBigInt, O2SBigInt *) 87 | O2SCALCULATOR_IMPLEMENTATION(bitwiseXorByInt, NSInteger) 88 | 89 | #pragma mark 或: 90 | O2SCALCULATOR_IMPLEMENTATION(bitwiseOrByBigInt, O2SBigInt *) 91 | O2SCALCULATOR_IMPLEMENTATION(bitwiseOrByInt, NSInteger) 92 | 93 | #pragma mark 与: 94 | O2SCALCULATOR_IMPLEMENTATION(bitwiseAndByBigInt, O2SBigInt *) 95 | O2SCALCULATOR_IMPLEMENTATION(bitwiseAndByInt, NSInteger) 96 | 97 | #pragma mark 左移: 98 | O2SCALCULATOR_IMPLEMENTATION(shiftLeft, int) 99 | 100 | #pragma mark 右移: 101 | O2SCALCULATOR_IMPLEMENTATION(shiftRight, int) 102 | 103 | #pragma mark 最大公约数 104 | O2SCALCULATOR_IMPLEMENTATION(gcdByBigInt, O2SBigInt *) 105 | O2SCALCULATOR_IMPLEMENTATION(gcdByInt, NSInteger) 106 | 107 | #pragma mark 余逆: 108 | O2SCALCULATOR_IMPLEMENTATION(modInverseByBigInt, O2SBigInt *) 109 | O2SCALCULATOR_IMPLEMENTATION(modInverseByInt, NSInteger) 110 | 111 | #pragma mark 余: 112 | O2SCALCULATOR_IMPLEMENTATION(modByBigInt, O2SBigInt *) 113 | O2SCALCULATOR_IMPLEMENTATION(modByInt, NSInteger) 114 | 115 | #define O2SCALCULATOR_IMPLEMENTATION_NONEARGUMENT(MethodName) - (O2SCalculator *(^)(void))MethodName\ 116 | {\ 117 | return ^O2SCalculator *(void){\ 118 | self.bigInt = [self.bigInt MethodName];\ 119 | return self;\ 120 | };\ 121 | }\ 122 | 123 | #pragma mark 平方: 124 | O2SCALCULATOR_IMPLEMENTATION_NONEARGUMENT(square) 125 | // 原始 126 | //- (O2SCalculator *(^)(void))square 127 | //{ 128 | // return ^O2SCalculator *(void){ 129 | // self.bigInt = [self.bigInt square]; 130 | // return self; 131 | // }; 132 | //} 133 | 134 | #pragma mark 平方根: 135 | O2SCALCULATOR_IMPLEMENTATION_NONEARGUMENT(sqrt) 136 | 137 | #pragma mark 求反: 138 | O2SCALCULATOR_IMPLEMENTATION_NONEARGUMENT(negate) 139 | 140 | #pragma mark 绝对值: 141 | O2SCALCULATOR_IMPLEMENTATION_NONEARGUMENT(abs) 142 | 143 | #undef O2SCALCULATOR_IMPLEMENTATION 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/EC_Fp/O2SECCurveFp.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECCurveFp.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #pragma mark - Fp(素数域)上的椭圆曲线 y^2 = x^3 + ax + b 12 | //椭圆曲线E (Fp )上的点按照下面的加法运算规则,构成一个交换群: 13 | //a) O+O=O; 14 | //b) ∀P = (x,y) ∈ E(Fp)\{O},P+O = O+P = P; 15 | //c) ∀P = (x,y) ∈ E(Fp)\{O},P的逆元素−P = (x,−y),P+(−P) = O; 16 | //d) 两个非互逆的不同点相加的规则: 17 | // 设P1 = (x1,y1) ∈ E(Fp)\{O},P2 = (x2,y2) ∈ E(Fp)\{O},且x1 ≠ x2, 18 | // 设P3 = (x3,y3)=P1+P2,则 19 | // x3 =λ^2 − x1 − x2, 20 | // y3 =λ(x1 − x3) − y1 21 | // 其中 22 | // y2 − y1 23 | // λ = ——————— ; 24 | // x2 − x1 25 | //e) 倍点规则: 26 | // 设P1 = (x1,y1) ∈ E(Fp)\{O},且y1 ≠ 0,P3 = (x3,y3) = P1 +P1,则 27 | // x3 =λ^2−2x1, 28 | // y3 =λ(x1−x3)−y1, 29 | // 其中 30 | // 3x1^2 + a 31 | // λ = ————————— 。 32 | // 2y1 33 | 34 | 35 | @class O2SECFieldElementFp; 36 | @class O2SECPointFp; 37 | @class O2SBigInt; 38 | 39 | NS_ASSUME_NONNULL_BEGIN 40 | 41 | /// 椭圆曲线 y^2 = x^3 + ax + b 42 | @interface O2SECCurveFp : NSObject 43 | 44 | @property (nonatomic, strong, readonly) O2SBigInt *q; 45 | @property (nonatomic, strong, readonly) O2SECPointFp *infinity; 46 | @property (nonatomic, strong, readonly) O2SECFieldElementFp *a; 47 | 48 | @property (nonatomic, assign, readonly) NSUInteger pointLen; 49 | 50 | - (instancetype)init NS_UNAVAILABLE; 51 | - (instancetype)initWithQ:(O2SBigInt *)q 52 | a:(O2SBigInt *)a 53 | b:(O2SBigInt *)b 54 | pointLen:(NSUInteger)len; 55 | 56 | + (O2SBigInt *)Three; 57 | 58 | - (O2SECFieldElementFp *)fromBigInteger:(O2SBigInt *)x; 59 | 60 | - (O2SECPointFp *)decodePointHex:(NSString *)s; 61 | - (NSString *)encodePoint:(O2SECPointFp *)point compressed:(BOOL)compressed; 62 | 63 | - (NSString *)toString; 64 | 65 | @end 66 | 67 | NS_ASSUME_NONNULL_END 68 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/EC_Fp/O2SECCurveFp.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECCurveFp.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SECCurveFp.h" 10 | #import "O2SECPointFp.h" 11 | #import "O2SECFieldElementFp.h" 12 | #import "O2SBigInt.h" 13 | #import "O2SSMxUtils.h" 14 | 15 | @interface O2SECCurveFp() 16 | 17 | @property (nonatomic, strong) O2SBigInt *q; 18 | @property (nonatomic, strong) O2SECFieldElementFp *a; 19 | @property (nonatomic, strong) O2SECFieldElementFp *b; 20 | @property (nonatomic, strong) O2SECPointFp *infinity; 21 | @property (nonatomic, assign) NSUInteger pointLen; 22 | 23 | @end 24 | 25 | @implementation O2SECCurveFp 26 | 27 | + (O2SBigInt *)Three 28 | { 29 | static O2SBigInt *three; 30 | static dispatch_once_t onceToken; 31 | dispatch_once(&onceToken, ^{ 32 | three = [[O2SBigInt alloc] initWithInt:3]; 33 | }); 34 | return three; 35 | } 36 | 37 | - (instancetype)initWithQ:(O2SBigInt *)q 38 | a:(O2SBigInt *)a 39 | b:(O2SBigInt *)b 40 | pointLen:(NSUInteger)len 41 | { 42 | if (self = [super init]) 43 | { 44 | self.q = q; 45 | self.a = [self fromBigInteger:a]; 46 | self.b = [self fromBigInteger:b]; 47 | 48 | self.infinity = [[O2SECPointFp alloc] initWithCurve:self 49 | x:nil 50 | y:nil 51 | z:nil]; 52 | 53 | self.pointLen = len; 54 | } 55 | return self; 56 | } 57 | 58 | /// 判断两个椭圆曲线是否相等 59 | /// @param other . 60 | - (BOOL)equals:(O2SECCurveFp *) other 61 | { 62 | @autoreleasepool { 63 | if (self == other) 64 | { 65 | return YES; 66 | } 67 | 68 | return [self.q compare:other.q] == NSOrderedSame && [self.a equals:other.a] && [self.b equals:other.b]; 69 | } 70 | } 71 | 72 | /// 生成椭圆曲线域元素 73 | /// @param x . 74 | - (O2SECFieldElementFp *)fromBigInteger:(O2SBigInt *)x 75 | { 76 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:x]; 77 | } 78 | 79 | #pragma mark - 椭圆曲线点的压缩与解压缩 80 | 81 | /// 解析 16 进制串为椭圆曲线点 坐标点压缩 压缩格式:若公钥y坐标最后一位为0,则首字节为0x02,否则为0x03。非压缩格式:公钥首字节为0x04 82 | /// @param s . 83 | - (O2SECPointFp *)decodePointHex:(NSString *)s 84 | { 85 | if (s.length < 2) 86 | { 87 | return nil; 88 | } 89 | NSRange range = (NSRange){0,2}; 90 | unsigned long outVal = strtoul([[s substringWithRange:range] UTF8String], 0, 16); 91 | switch (outVal) { 92 | case 0: 93 | return self.infinity; 94 | break; 95 | case 2: 96 | case 3: 97 | { 98 | // 已知椭圆方程式y^2 = x^3 + ax + b,和已知的点的坐标x值,求点的坐标y值 99 | NSUInteger len = ([s length] - 2 ); 100 | if (len != self.pointLen/2) 101 | { 102 | // NSAssert(NO, @"decode point error"); 103 | return nil; 104 | } 105 | NSRange range = (NSRange){2,len}; 106 | NSString *xHex = [s substringWithRange:range]; 107 | O2SBigInt *x = [[O2SBigInt alloc] initWithString:xHex radix:16]; 108 | 109 | O2SECFieldElementFp *x_fe = [self fromBigInteger:x]; 110 | O2SECFieldElementFp *rhs = [[x_fe square] multiply:x_fe]; 111 | rhs = [rhs add:[self.a multiply:x_fe]]; 112 | rhs = [rhs add:self.b]; 113 | 114 | O2SECFieldElementFp *y_fe = [rhs modsqrt];//modsqrt(),这里是[y^2 mod q = (x^3 + ax + b) mod q]求y(模平方根) 115 | unsigned long yp = outVal & 1; 116 | 117 | if ([[[y_fe toBigInteger] bitwiseAndByInt:1] compare:[[O2SBigInt alloc] initWithInt:yp]] == NSOrderedSame) 118 | { 119 | return [[O2SECPointFp alloc] initWithCurve:self x:x_fe y:y_fe z:nil]; 120 | } 121 | else 122 | { 123 | O2SECFieldElementFp *field = [[O2SECFieldElementFp alloc] initWithQ:self.q x:self.q]; 124 | y_fe = [field subtract:y_fe]; 125 | return [[O2SECPointFp alloc] initWithCurve:self x:x_fe y:y_fe z:nil]; 126 | } 127 | 128 | // NSAssert(NO, @"decode point error"); 129 | return nil; 130 | } 131 | break; 132 | case 4: 133 | case 6: 134 | case 7: 135 | { 136 | NSUInteger len = ([s length] - 2 ) / 2; 137 | if (len != self.pointLen/2) 138 | { 139 | // NSAssert(NO, @"decode point error"); 140 | return nil; 141 | } 142 | 143 | NSRange range = (NSRange){2,len}; 144 | NSString *xHex = [s substringWithRange:range]; 145 | O2SBigInt *x = [[O2SBigInt alloc] initWithString:xHex radix:16]; 146 | O2SECFieldElementFp *x_fe = [self fromBigInteger:x]; 147 | 148 | range.location = len + 2; 149 | NSString *yHex = [s substringWithRange:range]; 150 | O2SBigInt *y = [[O2SBigInt alloc] initWithString:yHex radix:16]; 151 | O2SECFieldElementFp *y_fe = [self fromBigInteger:y]; 152 | 153 | return [[O2SECPointFp alloc] initWithCurve:self x:x_fe y:y_fe z:nil]; 154 | } 155 | break; 156 | default: 157 | return nil; 158 | break; 159 | } 160 | return nil; 161 | } 162 | 163 | - (NSString *)encodePoint:(O2SECPointFp *)point compressed:(BOOL)compressed 164 | { 165 | if (compressed == NO) 166 | { 167 | //04 168 | NSString *pointX = [O2SSMxUtils leftPad:[[[point getX] toBigInteger] toString:16] num:self.pointLen/2]; 169 | NSString *pointY = [O2SSMxUtils leftPad:[[[point getY] toBigInteger] toString:16] num:self.pointLen/2]; 170 | NSString *pointHex = [NSString stringWithFormat:@"04%@%@", pointX, pointY]; 171 | return pointHex; 172 | } 173 | else 174 | { 175 | //02 03 176 | NSString *pointX = [O2SSMxUtils leftPad:[[[point getX] toBigInteger] toString:16] num:self.pointLen/2]; 177 | 178 | O2SBigInt *y = [[point getY] toBigInteger]; 179 | O2SBigInt *py = [y bitwiseAndByInt:1]; 180 | O2SBigInt *pc = [py bitwiseOrByInt:0x02]; 181 | NSString *pcStr = [O2SSMxUtils leftPad:[pc toString:16] num:2]; 182 | NSRange range = (NSRange){pcStr.length - 2, 2}; 183 | pcStr = [pcStr substringWithRange:range]; 184 | 185 | NSString *pointHex = [NSString stringWithFormat:@"%@%@", pcStr, pointX]; 186 | return pointHex; 187 | } 188 | } 189 | 190 | - (NSString *)toString 191 | { 192 | return [NSString stringWithFormat:@"\"Fp\": y^2 = x^3 + %@*x + %@ over %@",[self.a.toBigInteger toString:10],[self.b.toBigInteger toString:10],[self.q toString:10]]; 193 | } 194 | 195 | @end 196 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/EC_Fp/O2SECFieldElementFp.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECFieldElementFp.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class O2SBigInt; 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | /// 椭圆曲线域元素 16 | @interface O2SECFieldElementFp : NSObject 17 | 18 | - (instancetype)init NS_UNAVAILABLE; 19 | - (instancetype)initWithQ:(O2SBigInt *)q 20 | x:(O2SBigInt *)x; 21 | 22 | /// 判断相等 23 | /// @param other . 24 | - (BOOL)equals:(O2SECFieldElementFp *)other; 25 | 26 | /// 返回具体数值 27 | - (O2SBigInt *)toBigInteger; 28 | 29 | /// 取反 30 | - (O2SECFieldElementFp *)negate; 31 | 32 | /// 相加 33 | /// @param b 16进制字符串如: 0A477E 34 | - (O2SECFieldElementFp *)add:(O2SECFieldElementFp *)b; 35 | 36 | /// 相减 37 | /// @param b . 38 | - (O2SECFieldElementFp *)subtract:(O2SECFieldElementFp *)b; 39 | 40 | /// 相乘 41 | /// @param b . 42 | - (O2SECFieldElementFp *)multiply:(O2SECFieldElementFp *)b; 43 | 44 | /// 相除 45 | /// @param b . 46 | - (O2SECFieldElementFp *)divide:(O2SECFieldElementFp *)b; 47 | 48 | /// 平方 49 | - (O2SECFieldElementFp *)square; 50 | 51 | #pragma mark - 点压缩 (y^2) mod n = a mod n,求y 52 | ///平方根 53 | - (O2SECFieldElementFp *)modsqrt; 54 | 55 | @end 56 | 57 | NS_ASSUME_NONNULL_END 58 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/EC_Fp/O2SECFieldElementFp.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECFieldElementFp.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SECFieldElementFp.h" 10 | #import "O2SECCurveFp.h" 11 | #import "O2SECPointFp.h" 12 | #import "O2SBigInt.h" 13 | 14 | @interface O2SECFieldElementFp () 15 | 16 | @property (nonatomic, weak) O2SBigInt *q; 17 | @property (nonatomic, strong) O2SBigInt *x; 18 | 19 | @end 20 | 21 | @implementation O2SECFieldElementFp 22 | 23 | 24 | - (instancetype)initWithQ:(O2SBigInt *)q x:(O2SBigInt *)x 25 | { 26 | if (self = [super init]) 27 | { 28 | self.q = q; 29 | self.x = x; 30 | } 31 | return self; 32 | } 33 | 34 | /// 判断相等 35 | /// @param other . 36 | - (BOOL)equals:(O2SECFieldElementFp *)other 37 | { 38 | @autoreleasepool { 39 | if (self == other) 40 | { 41 | return YES; 42 | } 43 | 44 | return ([self.q compare:other.q] == NSOrderedSame && 45 | [self.x compare:other.x] == NSOrderedSame); 46 | } 47 | 48 | } 49 | 50 | /// 返回具体数值 51 | - (O2SBigInt *)toBigInteger 52 | { 53 | return self.x; 54 | } 55 | 56 | /// 取反 57 | - (O2SECFieldElementFp *)negate 58 | { 59 | @autoreleasepool { 60 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[[self.x negate] modByBigInt:self.q]]; 61 | } 62 | } 63 | 64 | /// 相加 65 | /// @param b . 66 | - (O2SECFieldElementFp *)add:(O2SECFieldElementFp *)b 67 | { 68 | @autoreleasepool { 69 | O2SBigInt *tmp = [b toBigInteger]; 70 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[[self.x addByBigInt:tmp] modByBigInt:self.q]]; 71 | } 72 | } 73 | 74 | /// 相减 75 | /// @param b . 76 | - (O2SECFieldElementFp *)subtract:(O2SECFieldElementFp *)b 77 | { 78 | @autoreleasepool { 79 | O2SBigInt *tmp = [b toBigInteger]; 80 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[[self.x subByBigInt:tmp] modByBigInt:self.q]]; 81 | } 82 | } 83 | 84 | 85 | /// 相乘 86 | /// @param b . 87 | - (O2SECFieldElementFp *)multiply:(O2SECFieldElementFp *)b 88 | { 89 | @autoreleasepool { 90 | O2SBigInt *tmp = [b toBigInteger]; 91 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[[self.x multiplyByBigInt:tmp] modByBigInt:self.q]]; 92 | } 93 | } 94 | 95 | /// 相除 96 | /// @param b . 97 | - (O2SECFieldElementFp *)divide:(O2SECFieldElementFp *)b 98 | { 99 | @autoreleasepool { 100 | O2SBigInt *tmp = [[b toBigInteger] modInverseByBigInt:self.q]; 101 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[[self.x multiplyByBigInt:tmp] modByBigInt:self.q]]; 102 | } 103 | } 104 | 105 | /// 平方 106 | - (O2SECFieldElementFp *)square 107 | { 108 | @autoreleasepool { 109 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[[self.x square] modByBigInt:self.q]]; 110 | } 111 | } 112 | 113 | 114 | #pragma mark - 点压缩 (y^2) mod n = a mod n,求y 115 | // https://blog.csdn.net/qq_41746268/article/details/98730749 116 | //对于给定的奇质数p,和正整数x,存在y满足1≤y≤p−1,且x≡y^2(mod p)x,则称y为x的模平方根 117 | //对于正整数m,若同余式,若同余式x^2≡a(mod m)有解,则称a为模m的平方剩余,否则称为模m平方非剩余。 118 | //是否存在模平方根 119 | //根据欧拉判别条件: 120 | //设p是奇质数,对于x^2≡a(mod p) 121 | //a是模p的平方剩余的充要条件是(a^((p−1)/2)) % p = 1 122 | //a是模p的平方非剩余的充要条件是(a^((p−1)/2)) % p = -1 123 | //给定a,na,na,n(n是质数),求x^2≡a(mod n)的最小整数解x 124 | //代码复杂度O(log2(n)) 125 | 126 | ///平方根 127 | - (O2SECFieldElementFp *)modsqrt 128 | { 129 | @autoreleasepool { 130 | O2SBigInt *b,*i,*k,*y; 131 | 132 | O2SBigInt *n = _q; 133 | O2SBigInt *a = _x; 134 | //n==2 135 | if ([n compare:[[O2SBigInt alloc] initWithInt:2]] == NSOrderedSame) 136 | { 137 | //a%n 138 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[a modByBigInt:n]]; 139 | } 140 | //qpow(a,(n-1)/2,n) == 1 141 | if ([[self _qpow:a b:[[n subByInt:1] divideByInt:2] p:n] compare:O2SBigInt.one] == NSOrderedSame) 142 | { 143 | //n%4 == 3 144 | if ([[n modByInt:4] compare:[[O2SBigInt alloc] initWithInt:3]] == NSOrderedSame) 145 | { 146 | //y=qpow(a,(n+1)/4,n) 147 | y = [self _qpow:a b:[[n addByInt:1] divideByInt:4] p:n]; 148 | } 149 | else 150 | { 151 | //for(b=1,qpow(b,(n-1)/2,n) == 1,b++) 152 | for (b = O2SBigInt.one; [[self _qpow:b b:[[n subByInt:1] divideByInt:2] p:n] compare:O2SBigInt.one] == NSOrderedSame;) 153 | { 154 | b = [b addByInt:1]; 155 | } 156 | //i=(n-1)/2 157 | i = [[n subByInt:1] divideByInt:2]; 158 | //k=0 159 | k = O2SBigInt.zero; 160 | //while(i%2==0) 161 | while ([[i modByInt:2] compare:O2SBigInt.zero] == NSOrderedSame) 162 | { 163 | //i /= 2 164 | i = [i divideByInt:2]; 165 | //k /= 2 166 | k = [k divideByInt:2]; 167 | //t1=qpow(a,i,n) 168 | O2SBigInt *t1 = [self _qpow:a b:i p:n]; 169 | //t2=qpow(b,k,n) 170 | O2SBigInt *t2 = [self _qpow:b b:k p:n]; 171 | //(t1*t2+1)%n == 0 172 | if ([[[[t1 multiplyByBigInt:t2] addByInt:1] modByBigInt:n] compare:O2SBigInt.zero] == NSOrderedSame) 173 | { 174 | //k+=(n-1)/2 175 | k = [k addByBigInt:[[n subByInt:1] divideByInt:2]]; 176 | } 177 | } 178 | //tt1=qpow(a,(i+1)/2,n) 179 | O2SBigInt *tt1 = [self _qpow:a b:[[i addByInt:1] divideByInt:2] p:n]; 180 | //tt2=qpow(b,k/2,n) 181 | O2SBigInt *tt2 = [self _qpow:b b:[k divideByInt:2] p:n]; 182 | //y=tt1*tt2%n 183 | y = [[tt1 multiplyByBigInt:tt2] modByBigInt:n]; 184 | } 185 | //y*2>n 186 | if ([[y multiplyByInt:2] compare:n] == NSOrderedDescending) 187 | { 188 | //y = n - y 189 | y = [n subByBigInt:y]; 190 | } 191 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:y]; 192 | } 193 | return [[O2SECFieldElementFp alloc] initWithQ:self.q x:[[O2SBigInt alloc] initWithInt:-1]]; 194 | } 195 | } 196 | 197 | - (O2SBigInt *)_qpow:(O2SBigInt *)a b:(O2SBigInt *)b p:(O2SBigInt *)p 198 | { 199 | @autoreleasepool { 200 | O2SBigInt *ans = O2SBigInt.one; 201 | //b != 0 202 | while ([b compare:O2SBigInt.zero] != NSOrderedSame) 203 | { 204 | //b&1 205 | if ([[b bitwiseAndByBigInt:O2SBigInt.one] compare:O2SBigInt.zero] != NSOrderedSame) 206 | { 207 | //ans = ans*a%p 208 | ans = [[ans multiplyByBigInt:a] modByBigInt:p]; 209 | } 210 | //a=a*a%p 211 | a = [[a multiplyByBigInt:a] modByBigInt:p]; 212 | //b>>=1 213 | b = [b shiftRight:1]; 214 | } 215 | return ans; 216 | } 217 | } 218 | 219 | @end 220 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/EC_Fp/O2SECPointFp.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECPointFp.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class O2SECCurveFp; 12 | @class O2SECFieldElementFp; 13 | @class O2SBigInt; 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | 17 | /// 椭圆曲线上点 18 | @interface O2SECPointFp : NSObject 19 | 20 | - (instancetype)init NS_UNAVAILABLE; 21 | 22 | - (instancetype)initWithCurve:(O2SECCurveFp *)curve 23 | x:(nullable O2SECFieldElementFp *)x 24 | y:(nullable O2SECFieldElementFp *)y 25 | z:(nullable O2SBigInt *)z; 26 | 27 | 28 | // 椭圆曲线上的X坐标值(逻辑) 29 | - (O2SECFieldElementFp *)getX; 30 | 31 | // 椭圆曲线上的Y坐标值(逻辑) 32 | - (O2SECFieldElementFp *)getY; 33 | 34 | // Point在椭圆上的对称点 35 | - (O2SECPointFp *)negate; 36 | 37 | // 相同点(twice) 不同点:两点连成线与椭圆相交另一点的对称点 38 | - (O2SECPointFp *)add:(O2SECPointFp *)b; 39 | 40 | // Point切线与椭圆相交另一点的对称点 41 | - (O2SECPointFp *)twice; 42 | 43 | // k*Point 44 | - (O2SECPointFp *)multiply:(O2SBigInt *)k; 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/EC_Fp/O2SECPointFp.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECPointFp.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SECPointFp.h" 10 | #import "O2SECCurveFp.h" 11 | #import "O2SECFieldElementFp.h" 12 | #import "O2SBigInt.h" 13 | 14 | @interface O2SECPointFp () 15 | 16 | @property (nonatomic, weak) O2SECCurveFp *curve; 17 | @property (nonatomic, strong) O2SECFieldElementFp *x; 18 | @property (nonatomic, strong) O2SECFieldElementFp *y; 19 | @property (nonatomic, strong) O2SBigInt *z; 20 | @property (nonatomic, strong) O2SBigInt *zinv; 21 | 22 | @end 23 | 24 | @implementation O2SECPointFp 25 | 26 | - (instancetype)initWithCurve:(O2SECCurveFp *)curve 27 | x:(O2SECFieldElementFp *)x 28 | y:(O2SECFieldElementFp *)y 29 | z:(O2SBigInt *)z 30 | { 31 | if (self = [super init]) 32 | { 33 | self.curve = curve; 34 | self.x = x; 35 | self.y = y; 36 | // 标准射影坐标系:zinv == null 或 z * zinv == 1 37 | self.z = z == nil ? O2SBigInt.one : z; 38 | 39 | self.zinv = nil; 40 | } 41 | return self; 42 | } 43 | 44 | - (O2SECFieldElementFp *)getX 45 | { 46 | @autoreleasepool { 47 | if (self.zinv == nil) 48 | { 49 | self.zinv = [self.z modInverseByBigInt:self.curve.q]; 50 | } 51 | O2SBigInt *tmp = [[[self.x toBigInteger] multiplyByBigInt:self.zinv] modByBigInt:self.curve.q]; 52 | return [self.curve fromBigInteger:tmp]; 53 | } 54 | } 55 | 56 | - (O2SECFieldElementFp *)getY 57 | { 58 | @autoreleasepool { 59 | if (self.zinv == nil) 60 | { 61 | self.zinv = [self.z modInverseByBigInt:self.curve.q]; 62 | } 63 | O2SBigInt *tmp = [[[self.y toBigInteger] multiplyByBigInt:self.zinv] modByBigInt:self.curve.q]; 64 | return [self.curve fromBigInteger:tmp]; 65 | } 66 | } 67 | 68 | /// 判断相等 69 | /// @param other . 70 | - (BOOL)equals:(O2SECPointFp *) other 71 | { 72 | @autoreleasepool { 73 | if (self == other) 74 | { 75 | return true; 76 | } 77 | 78 | if ([self isInfinity]) 79 | { 80 | return [other isInfinity]; 81 | } 82 | if ([other isInfinity]) 83 | { 84 | return [self isInfinity]; 85 | } 86 | 87 | // u = y2 * z1 - y1 * z2 88 | O2SBigInt *u = [[[[other.y toBigInteger] multiplyByBigInt:self.z] subByBigInt:([[self.y toBigInteger] multiplyByBigInt:other.z])] modByBigInt:self.curve.q]; 89 | if ([u compare:O2SBigInt.zero] != NSOrderedSame) 90 | { 91 | return NO; 92 | } 93 | // v = x2 * z1 - x1 * z2 94 | O2SBigInt *v = [[[[other.x toBigInteger] multiplyByBigInt:self.z] subByBigInt:([[self.x toBigInteger] multiplyByBigInt:other.z])] modByBigInt:self.curve.q]; 95 | return [v compare:O2SBigInt.zero] == NSOrderedSame; 96 | } 97 | } 98 | 99 | /// 是否是无穷远点 100 | - (BOOL)isInfinity 101 | { 102 | @autoreleasepool { 103 | if (self.x == nil && self.y == nil) 104 | { 105 | return true; 106 | } 107 | 108 | return [self.z compare:O2SBigInt.zero] == NSOrderedSame && !([[self.y toBigInteger] compare:O2SBigInt.zero]); 109 | } 110 | } 111 | 112 | /// 取反,x 轴对称点 113 | - (O2SECPointFp *)negate 114 | { 115 | @autoreleasepool { 116 | return [[O2SECPointFp alloc] initWithCurve:self.curve x:self.x y:[self.y negate] z:self.z]; 117 | } 118 | } 119 | 120 | 121 | /// 相加 122 | /// 标准射影坐标系 123 | /// λ1 = x1 * z2 124 | /// λ2 = x2 * z1 125 | /// λ3 = λ1 − λ2 126 | /// λ4 = y1 * z2 127 | /// λ5 = y2 * z1 128 | /// λ6 = λ4 − λ5 129 | /// λ7 = λ1 + λ2 130 | /// λ8 = z1 * z2 131 | /// λ9 = λ3^2 132 | /// λ10 = λ3 * λ9 133 | /// λ11 = λ8 * λ6^2 − λ7 * λ9 134 | /// x3 = λ3 * λ11 135 | /// y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10 136 | /// z3 = λ10 * λ8 137 | /// @param b . 138 | - (O2SECPointFp *)add:(O2SECPointFp *)b 139 | { 140 | @autoreleasepool { 141 | if ([self isInfinity]) 142 | { 143 | return b; 144 | } 145 | 146 | if ([b isInfinity]) { 147 | return self; 148 | } 149 | 150 | O2SBigInt *x1 = [self.x toBigInteger]; 151 | O2SBigInt *y1 = [self.y toBigInteger]; 152 | O2SBigInt *z1 = self.z; 153 | O2SBigInt *x2 = [b.x toBigInteger]; 154 | O2SBigInt *y2 = [b.y toBigInteger]; 155 | O2SBigInt *z2 = b.z; 156 | O2SBigInt *q = self.curve.q; 157 | 158 | O2SBigInt *w1 = [[x1 multiplyByBigInt:z2] modByBigInt:q]; 159 | O2SBigInt *w2 = [[x2 multiplyByBigInt:z1] modByBigInt:q]; 160 | O2SBigInt *w3 = [w1 subByBigInt:w2]; 161 | O2SBigInt *w4 = [[y1 multiplyByBigInt:z2] modByBigInt:q]; 162 | O2SBigInt *w5 = [[y2 multiplyByBigInt:z1] modByBigInt:q]; 163 | O2SBigInt *w6 = [w4 subByBigInt:w5]; 164 | 165 | if ([O2SBigInt.zero compare:w3] == NSOrderedSame) 166 | { 167 | if ([O2SBigInt.zero compare:w6] == NSOrderedSame) 168 | { 169 | return [self twice]; 170 | } 171 | return self.curve.infinity; 172 | } 173 | 174 | O2SBigInt *w7 = [w1 addByBigInt:w2]; 175 | O2SBigInt *w8 = [[z1 multiplyByBigInt:z2] modByBigInt:q]; 176 | O2SBigInt *w9 = [[w3 square] modByBigInt:q]; 177 | O2SBigInt *w10 = [[w3 multiplyByBigInt:w9] modByBigInt:q]; 178 | O2SBigInt *w11 = [[[w8 multiplyByBigInt:[w6 square]] subByBigInt:[w7 multiplyByBigInt:w9]] modByBigInt:q]; 179 | 180 | O2SBigInt *x3 = [[w3 multiplyByBigInt:w11] modByBigInt:q]; 181 | O2SBigInt *y3 = [[[w6 multiplyByBigInt:[[w9 multiplyByBigInt:w1] subByBigInt:w11]] subByBigInt:[w4 multiplyByBigInt:w10]] modByBigInt:q]; 182 | O2SBigInt *z3 = [[w10 multiplyByBigInt:w8] modByBigInt:q]; 183 | 184 | return [[O2SECPointFp alloc] initWithCurve:self.curve x:[self.curve fromBigInteger:x3] y:[self.curve fromBigInteger:y3] z:z3]; 185 | } 186 | 187 | } 188 | 189 | 190 | 191 | /// 自加 192 | /// 标准射影坐标系: 193 | /// λ1 = 3 * x1^2 + a * z1^2 194 | /// λ2 = 2 * y1 * z1 195 | /// λ3 = y1^2 196 | /// λ4 = λ3 * x1 * z1 197 | /// λ5 = λ2^2 198 | /// λ6 = λ1^2 − 8 * λ4 199 | /// x3 = λ2 * λ6 200 | /// y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3 201 | /// z3 = λ2 * λ5 202 | /// 203 | - (O2SECPointFp *)twice 204 | { 205 | @autoreleasepool { 206 | if ([self isInfinity]) 207 | { 208 | return self; 209 | } 210 | if (![[self.y toBigInteger] signum]) { 211 | return self.curve.infinity; 212 | } 213 | 214 | O2SBigInt *x1 = [self.x toBigInteger]; 215 | O2SBigInt *y1 = [self.y toBigInteger]; 216 | O2SBigInt *z1 = self.z; 217 | O2SBigInt *q = self.curve.q; 218 | O2SBigInt *a = [self.curve.a toBigInteger]; 219 | 220 | O2SBigInt *w1 = [[[[x1 square] multiplyByBigInt:O2SECCurveFp.Three] addByBigInt:[a multiplyByBigInt:[z1 square]]] modByBigInt:q]; 221 | O2SBigInt *w2 = [[[y1 shiftLeft:1] multiplyByBigInt:z1] modByBigInt:q]; 222 | O2SBigInt *w3 = [[y1 square] modByBigInt:q]; 223 | O2SBigInt *w4 = [[[w3 multiplyByBigInt:x1] multiplyByBigInt:z1] modByBigInt:q]; 224 | O2SBigInt *w5 = [[w2 square] modByBigInt:q]; 225 | O2SBigInt *w6 = [[[w1 square] subByBigInt:[w4 shiftLeft:3]] modByBigInt:q]; 226 | 227 | O2SBigInt *x3 = [[w2 multiplyByBigInt:w6] modByBigInt:q]; 228 | O2SBigInt *y3 = [[[w1 multiplyByBigInt:[[w4 shiftLeft:2] subByBigInt:w6]] subByBigInt:[[w5 shiftLeft:1] multiplyByBigInt:w3]] modByBigInt:q]; 229 | O2SBigInt *z3 = [[w2 multiplyByBigInt:w5] modByBigInt:q]; 230 | 231 | return [[O2SECPointFp alloc] initWithCurve:self.curve x:[self.curve fromBigInteger:x3] y:[self.curve fromBigInteger:y3] z:z3]; 232 | } 233 | } 234 | 235 | 236 | /// 倍点计算 kG 237 | /// @param k . 238 | - (O2SECPointFp *)multiply:(O2SBigInt *)k 239 | { 240 | @autoreleasepool { 241 | if ([self isInfinity]) 242 | { 243 | return self; 244 | } 245 | if (![k signum]) { 246 | return self.curve.infinity; 247 | } 248 | 249 | O2SBigInt *k3 = [k multiplyByBigInt:O2SECCurveFp.Three]; 250 | O2SECPointFp *neg = [self negate]; 251 | O2SECPointFp *Q = self; 252 | for (uint64_t i = [k3 bitLength] - 2; i > 0; i--) 253 | { 254 | Q = [Q twice]; 255 | 256 | BOOL k3Bit = [k3 testBit:i]; 257 | BOOL kBit = [k testBit:i]; 258 | 259 | if (k3Bit != kBit) 260 | { 261 | Q = [Q add:(k3Bit? self : neg)]; 262 | } 263 | } 264 | 265 | return Q; 266 | } 267 | } 268 | 269 | @end 270 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/O2SECCKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECCKit.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | #import 13 | #import 14 | 15 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/O2SSMxHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSMxHelper.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class O2SSM2Cipher; 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | typedef NS_ENUM(NSInteger, O2SSM2CipherMode) { 16 | O2SSM2CipherModeC1C3C2 = 0, 17 | O2SSM2CipherModeC1C2C3 = 1, 18 | }; 19 | 20 | @interface O2SSMxHelper : NSObject 21 | 22 | #pragma mark - SM2 23 | 24 | /// sm2加密 25 | /// @param plainData 明文 26 | /// @param publicKey 公钥 是私钥k*G的值 这里传点x和点y的拼接无需带04 ,非der, der文件可通过asn.1解码获得 https://aks.jd.com/tools/sec/ 27 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 28 | /// @param cipherMode c1+c2+c3或c1+c3+c2 29 | + (NSData *)sm2DoEncrypt:(NSData *)plainData 30 | publicKey:(NSString *)publicKey 31 | cipher:(O2SSM2Cipher *)cipher 32 | cipherMode:(O2SSM2CipherMode)cipherMode; 33 | 34 | 35 | /// sm2解密 36 | /// @param cipherData 密文 37 | /// @param privateKey 私钥 非der ,der文件可通过asn.1解码获得 https://aks.jd.com/tools/sec/ 38 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 39 | /// @param cipherMode c1+c2+c3或c1+c3+c2 40 | + (NSData *)sm2DoDecrypt:(NSData *)cipherData 41 | privateKey:(NSString *)privateKey 42 | cipher:(O2SSM2Cipher *)cipher 43 | cipherMode:(O2SSM2CipherMode)cipherMode; 44 | 45 | 46 | /// sm2签名 47 | /// @param userId 用户身份标识 48 | /// @param srcData 待签名内容 49 | /// @param privateKey 私钥 50 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 51 | + (NSData *)sm2DoSignUserId:(NSString *)userId 52 | srcData:(NSData *)srcData 53 | privateKey:(NSString *)privateKey 54 | cipher:(O2SSM2Cipher *)cipher; 55 | 56 | 57 | /// sm2验签 58 | /// @param userId 用户身份标识 59 | /// @param srcData 待签名内容 60 | /// @param publicKey 公钥 61 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 62 | /// @param sign 签名数据用于校验 63 | + (BOOL)sm2DoVerifyUserId:(NSString *)userId 64 | srcData:(NSData *)srcData 65 | publicKey:(NSString *)publicKey 66 | cipher:(O2SSM2Cipher *)cipher 67 | sign:(NSData *)sign; 68 | 69 | #pragma mark - SM3 70 | 71 | /// sm3 摘要 72 | /// @param msg String类型原始值 73 | + (NSData *)sm3DoHashWithString:(NSString *)msg; 74 | 75 | /// sm3 摘要 76 | /// @param msg Data类型原始值 77 | + (NSData *)sm3DoHashWithData:(NSData *)msg; 78 | 79 | @end 80 | 81 | NS_ASSUME_NONNULL_END 82 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/O2SSMxHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSMxHelper.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SSMxHelper.h" 10 | #import "O2SBigInt.h" 11 | #import "O2SSM2Cipher.h" 12 | #import "O2SECPointFp.h" 13 | #import "O2SSM2Cipher+Private.h" 14 | #import "O2SSMxUtils.h" 15 | #import "O2SECFieldElementFp.h" 16 | #import "O2SSM3Digest.h" 17 | 18 | //无论RSA还是SM2,加解密问题,一切都归于数学问题,涉及“大数“运算,字符串可以用“大数”表示,加解密无非就是 ”大数“变成另一个”大数“ 19 | //一个字符串NSString(如"hello world") 转成 NSData,NSData转换成 16进制的字符串(如"68656C6C6F20776F726C64"),这个l6进制字符串就是一个16进制”大数“ 20 | //大数运算 如:"C8" + "A3" = "016B" 21 | // 22 | //SM2 加解密 23 | //备注:椭圆曲线坐标点运算 详情EC_Fp 24 | //注:这里的坐标点如G点,Q点及椭圆曲线生成的点当作大数处理 如:规定每个点为16进制4位{"00ff","f840"}那么值就是“00fff840”,之后通过位数重新切分成点 25 | //1、选定一条椭圆曲线Ep(a,b) 并取椭圆曲线上一点,作为基点G 26 | //2、选择一个大数k作为私钥,并生成公钥 Q = kG 27 | //3、Ep(a,b)和n、G点、Q点提供给客户端这几个参数经过ASN.1编码生成der即为"公钥" 备注:der不一定明确的含Ep(a,b)和G点的值,Q值一定有,根据内部类型值也可确定椭圆曲线 28 | //4、Ep(a,b)和n、G点、k值提供给服务端这几个参数经过ASN.1编码生成der即为"私钥" 备注:der不一定明确的含Ep(a,b)和G点及Q点的值,k值一定有,根据内部类型值也可确定椭圆曲线,"私钥"信息包含“公钥”,Q = kG 计算得到, 29 | // 一般提供的der文件密钥可通过https://aks.jd.com/tools/sec/ ASN.1在线解析工具获取相关的p、a、b、G点、n的值以及Q点或k 30 | //5、加解密原理解释例子: 31 | // M为明文,r是随机一个“大数” C1 = rG,C1为随机点,Q为公钥点,C2 = M⊕rQ (实际为 C2 = M⊕KDF(rQ,ml) 看:♦️), r∈[1,n-1] 32 | // 公钥加密:密文C是C1,C2,C3组合的字节流 C = C1+C2+C3, 33 | // 私钥解码:求M ∵ 已知 C1 = rG,C2 = M⊕rQ,Q = kG, C1 = rG 34 | // ∵ 椭圆曲线特性(Fp域内运算满足交换律、结合律、分配律) rQ = r(kG) = k(rG) = kC1 35 | // ∴ 结果:rQ = kC1 36 | // ∵ M = (M⊕rQ)⊕rQ = (C2)⊕kC1, 一般是使用⊕(异或)处理,原因(a⊕b)⊕b == a 37 | // ∴ 结果:M = (C2)⊕kC1(实际为M = C2⊕KDF(kC1,ml)看:♦️),C2(密文C获取 已知),k(服务器私钥 已知)和C1(密文C获取 已知) 38 | // 39 | // ♦️注意:上方 C2 = M⊕rQ 改成 C2 = M⊕KDF(rQ,ml),M = (C2)⊕kC1 改成 M = C2⊕KDF(kC1,ml) ,C2.len == M.len【别名ml】 == KDF(rQ,ml).len == KDF(kC1,ml).len,长度值相等 40 | // 上方 C1 = rG 一般情况下前面还要加上0x04表示未压缩形式(C1 = 0x04+rG) 41 | // C3 = HASH_SM3(rQx+M+rQy) 42 | // 43 | // |--- 64 byte C1 ---||--- M(len) C2---||------ 32 byte C3 ------| 44 | // | || || | 45 | // |----x1----|----y1----|| || | 46 | // | | || || | 47 | // C = F0...................0802..............C9A1......................B8 48 | // 注意C1的长度与坐标点长度相等 49 | // 50 | // 以上"+"基本是字符串拼接 51 | 52 | //假设在加密过程中,有一个第三者H,H只能知道椭圆曲线 Ep(a,b)、公钥Q、基点G、密文C,而通过公钥Q、基点G求私钥k或者通过密文点C、基点P求随机数r都是非常困难的,因此得以保证数据传输的安全 53 | // 54 | //下面的加解密使用的是Fp上的椭圆曲线(p是大于3的素数,y^2 = x^3 + ax + b, a,b∈Fp,且(4a^3 + 27b^2) mod p = 0),非F2m上的椭圆曲线(y^2 + xy = x^3 + ax^2 + b, a,b∈F2m,且b=0)。 55 | // 56 | // asn.1解码 03 42 00 57 | // 03是bit string的tag 58 | // 42是bit string的length 59 | // 00是bit string的unused bit 60 | // 04说明是没有压缩的 61 | // 剩下为公钥point值 62 | 63 | @implementation O2SSMxHelper 64 | 65 | #pragma mark - SM2 66 | 67 | /// sm2加密 68 | /// @param plainData 明文 69 | /// @param publicKey 公钥Q 非der 可通过asn.1解码获得 70 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 71 | /// @param cipherMode c1+c2+c3或c1+c3+c2 72 | + (NSData *)sm2DoEncrypt:(NSData *)plainData 73 | publicKey:(NSString *)publicKey 74 | cipher:(O2SSM2Cipher *)cipher 75 | cipherMode:(O2SSM2CipherMode)cipherMode 76 | { 77 | BOOL repeat = NO; 78 | NSString *C1, *C2, *C3; 79 | 80 | do { 81 | repeat = NO; 82 | 83 | // 随机一个r 84 | O2SBigInt *r = [cipher randomBigIntegerK]; 85 | 86 | //NSLog(@"%@",cipher.curve.toString); 87 | 88 | //🌟 C1 = 04 || rG (rG即点{x1,y1}) 89 | O2SECPointFp *rGPoint = [cipher kG:r]; 90 | NSUInteger pointLen = cipher.getPointLen; 91 | //x1 92 | NSString *rGPointX = [O2SSMxUtils leftPad:[[[rGPoint getX] toBigInteger] toString:16] num:pointLen/2]; 93 | //y1 94 | NSString *rGPointY = [O2SSMxUtils leftPad:[[[rGPoint getY] toBigInteger] toString:16] num:pointLen/2]; 95 | NSString *rG = [NSString stringWithFormat:@"%@%@", rGPointX, rGPointY]; 96 | C1 = [NSString stringWithFormat:@"04%@", rG]; 97 | 98 | //压缩 99 | //C1 = [cipher.curve encodePoint:rGPoint compressed:YES]; 100 | 101 | 102 | //rQ (rQ即点{x2,y2}) 103 | O2SECPointFp *rQPoint = [cipher kP:r PPointHex:publicKey]; 104 | if (rQPoint == nil) 105 | { 106 | return nil; 107 | } 108 | //x2 109 | NSString *rQPointX = [O2SSMxUtils leftPad:[[[rQPoint getX] toBigInteger] toString:16] num:pointLen/2]; 110 | //y2 111 | NSString *rQPointY = [O2SSMxUtils leftPad:[[[rQPoint getY] toBigInteger] toString:16] num:pointLen/2]; 112 | //NSString *rQ = [NSString stringWithFormat:@"%@%@", rQPointX, rQPointY]; 113 | //NSLog(@"rQ:%@",rQ); 114 | 115 | NSData *rQPointXData = [O2SSMxUtils dataByHexString:rQPointX]; 116 | NSData *rQPointYData = [O2SSMxUtils dataByHexString:rQPointY]; 117 | 118 | //t = KDF(x2y2,M_LEN) 119 | //🌟 C2 = M⊕t 120 | NSUInteger ml = plainData.length; 121 | NSMutableData *x2_y2 = [NSMutableData data]; 122 | [x2_y2 appendData:rQPointXData]; 123 | [x2_y2 appendData:rQPointYData]; 124 | NSData *t = [O2SSM3Digest KDF:x2_y2 keylen:(int)ml]; 125 | NSString *tHex = [O2SSMxUtils hexStringByData:t]; 126 | O2SBigInt *tBigInt = [[O2SBigInt alloc] initWithString:tHex radix:16]; 127 | if ([tBigInt compare:O2SBigInt.zero] == NSOrderedSame) 128 | { 129 | repeat = YES; 130 | continue; 131 | } 132 | O2SBigInt *plainBigInt = [[O2SBigInt alloc] initWithString:[O2SSMxUtils hexStringByData:plainData] radix:16]; 133 | C2 = [[plainBigInt bitwiseXorByBigInt:tBigInt] toString:16]; 134 | C2 = [O2SSMxUtils leftPad:C2 num:ml*2]; 135 | 136 | //🌟 C3 = Hash(rQPointX+M+rQPointY) 137 | NSMutableData *x2_M_y2 = [NSMutableData data]; 138 | [x2_M_y2 appendData:rQPointXData]; 139 | [x2_M_y2 appendData:plainData]; 140 | [x2_M_y2 appendData:rQPointYData]; 141 | NSData *hash_sm3 = [O2SSM3Digest hashData:x2_M_y2]; 142 | C3 = [O2SSMxUtils hexStringByData:hash_sm3]; 143 | } while (repeat); 144 | 145 | 146 | NSString *C; 147 | if (cipherMode == O2SSM2CipherModeC1C2C3) 148 | { 149 | C = [NSString stringWithFormat:@"%@%@%@",C1,C2,C3]; 150 | } 151 | else 152 | { 153 | C = [NSString stringWithFormat:@"%@%@%@",C1,C3,C2]; 154 | } 155 | // NSLog(@"encrypt:%@",[C lowercaseString]); 156 | return [O2SSMxUtils dataByHexString:C]; 157 | 158 | } 159 | 160 | /// sm2解密 161 | /// @param cipherData 密文 162 | /// @param privateKey 私钥k 非der 可通过asn.1解码获得 163 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 164 | /// @param cipherMode c1+c2+c3或c1+c3+c2 165 | + (NSData *)sm2DoDecrypt:(NSData *)cipherData 166 | privateKey:(NSString *)privateKey 167 | cipher:(O2SSM2Cipher *)cipher 168 | cipherMode:(O2SSM2CipherMode)cipherMode 169 | { 170 | 171 | NSUInteger pointLen = cipher.getPointLen; 172 | 173 | O2SBigInt *k = [[O2SBigInt alloc] initWithString:privateKey radix:16]; 174 | if (cipherData.length <= 1) 175 | { 176 | return nil; 177 | } 178 | 179 | NSRange range_head = {0,1}; 180 | NSData *headData = [cipherData subdataWithRange:range_head]; 181 | 182 | //提取rG,不能直接拿C1当做rG,因为可能被压缩过 183 | NSUInteger C1_len = 0; 184 | O2SECPointFp *rGPoint; 185 | int8_t head; 186 | memcpy(&head, [headData bytes], 1); 187 | switch (head) { 188 | case 2: 189 | case 3: 190 | { 191 | C1_len = 1 + pointLen/4; 192 | NSRange rangeC1 = {0, C1_len}; 193 | NSData *C1 = [cipherData subdataWithRange:rangeC1]; 194 | rGPoint = [cipher.curve decodePointHex:[O2SSMxUtils hexStringByData:C1]]; 195 | } 196 | break; 197 | case 4: 198 | case 6: 199 | case 7: 200 | { 201 | C1_len = 1 + pointLen/2; 202 | NSRange rangeC1 = {0, C1_len}; 203 | NSData *C1 = [cipherData subdataWithRange:rangeC1]; 204 | rGPoint = [cipher.curve decodePointHex:[O2SSMxUtils hexStringByData:C1]]; 205 | } 206 | break; 207 | default: 208 | return nil; 209 | break; 210 | } 211 | 212 | if (rGPoint == nil) 213 | { 214 | return nil; 215 | } 216 | 217 | NSUInteger cipherLen = cipherData.length; 218 | if (cipherLen < C1_len + 32) 219 | { 220 | return nil; 221 | } 222 | 223 | NSData *C2,*C3; 224 | NSRange rangeC2,rangeC3; 225 | if (cipherMode == O2SSM2CipherModeC1C2C3) 226 | { 227 | rangeC3.location = cipherLen - 32; 228 | rangeC3.length = 32; 229 | 230 | rangeC2.location = C1_len; 231 | rangeC2.length = cipherLen - C1_len - 32; 232 | } 233 | else 234 | { 235 | rangeC3.location = C1_len; 236 | rangeC3.length = 32; 237 | 238 | rangeC2.location = C1_len + 32; 239 | rangeC2.length = cipherLen - C1_len - 32; 240 | 241 | } 242 | C2 = [cipherData subdataWithRange:rangeC2]; 243 | NSString *C2Hex = [O2SSMxUtils hexStringByData:C2]; 244 | C3 = [cipherData subdataWithRange:rangeC3]; 245 | NSString *C3Hex = [O2SSMxUtils hexStringByData:C3]; 246 | 247 | //kC1 248 | O2SECPointFp *kC1Point = [cipher kP:k PPoint:rGPoint]; 249 | //x2 250 | NSString *kC1PointX = [O2SSMxUtils leftPad:[[[kC1Point getX] toBigInteger] toString:16] num:pointLen/2]; 251 | //y2 252 | NSString *kC1PointY = [O2SSMxUtils leftPad:[[[kC1Point getY] toBigInteger] toString:16] num:pointLen/2]; 253 | NSString *kC1 = [NSString stringWithFormat:@"%@%@", kC1PointX, kC1PointY]; 254 | // NSLog(@"kC1:%@",kC1); 255 | 256 | NSData *kC1PointXData = [O2SSMxUtils dataByHexString:kC1PointX]; 257 | NSData *kC1PointYData = [O2SSMxUtils dataByHexString:kC1PointY]; 258 | NSData *kC1Data = [O2SSMxUtils dataByHexString:kC1]; 259 | 260 | 261 | //M = (C2)⊕KDF(kC1,ml) 262 | //t = KDF(kC1,ml) 263 | NSUInteger ml = C2.length; 264 | NSData *kdf = [O2SSM3Digest KDF:kC1Data keylen:(int)ml]; 265 | NSString *kdfHex = [O2SSMxUtils hexStringByData:kdf]; 266 | O2SBigInt *t = [[O2SBigInt alloc] initWithString:kdfHex radix:16]; 267 | if ([t compare:O2SBigInt.zero] == NSOrderedSame) 268 | { 269 | return nil; 270 | } 271 | O2SBigInt *C2BigInt = [[O2SBigInt alloc] initWithString:C2Hex radix:16]; 272 | //M = (C2)^t 273 | O2SBigInt *plainBigInt = [C2BigInt bitwiseXorByBigInt:t]; 274 | NSString *plainHex = [O2SSMxUtils leftPad:[plainBigInt toString:16] num:ml*2]; 275 | NSData *plainData = [O2SSMxUtils dataByHexString:plainHex]; 276 | 277 | //🌟 C3‘ = Hash(rQPointX+M+rQPointY) 278 | NSMutableData *x2_M_y2 = [NSMutableData data]; 279 | [x2_M_y2 appendData:kC1PointXData]; 280 | [x2_M_y2 appendData:plainData]; 281 | [x2_M_y2 appendData:kC1PointYData]; 282 | NSData *C3_t = [O2SSM3Digest hashData:x2_M_y2]; 283 | NSString *C3Hex_t = [O2SSMxUtils hexStringByData:C3_t]; 284 | 285 | //校验 C3 == C3‘ ? 286 | if ([C3Hex.lowercaseString isEqualToString:C3Hex_t.lowercaseString]) 287 | { 288 | return plainData; 289 | } 290 | else 291 | { 292 | return nil; 293 | } 294 | } 295 | 296 | /// sm2 数字签名 297 | /// @param userId 用户身份 298 | /// @param srcData 被签名内容 299 | /// @param privateKey 私钥k 300 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 301 | + (NSData *)sm2DoSignUserId:(NSString *)userId srcData:(NSData *)srcData privateKey:(NSString *)privateKey cipher:(O2SSM2Cipher *)cipher 302 | { 303 | NSString *rHex; 304 | NSString *sHex; 305 | @autoreleasepool { 306 | NSData *userIdData = [userId dataUsingEncoding: NSUTF8StringEncoding]; 307 | NSString * userIdHex = [O2SSMxUtils hexStringByData:userIdData]; 308 | NSString *ENTL_A = [NSString stringWithFormat:@"%lx",userIdData.length * 8]; 309 | ENTL_A = [O2SSMxUtils leftPad:ENTL_A num:4]; 310 | 311 | // 公钥 = 私钥*G点 312 | O2SBigInt *dA = [[O2SBigInt alloc] initWithString:privateKey radix:16];//私钥 313 | O2SECPointFp *PPoint = [cipher kG:dA];//公钥 314 | NSString *Px = [PPoint.getX.toBigInteger toString:16]; 315 | Px = [O2SSMxUtils leftPad:Px num:cipher.getPointLen/2]; 316 | NSString *Py = [PPoint.getY.toBigInteger toString:16]; 317 | Py = [O2SSMxUtils leftPad:Py num:cipher.getPointLen/2]; 318 | 319 | // Z_A = H256(ENTL_A || userId || a || b || Gx || Gy || Qx || Qy) 320 | NSMutableString *Z_A = [NSMutableString string]; 321 | [Z_A appendString:ENTL_A]; 322 | [Z_A appendString:userIdHex]; 323 | [Z_A appendString:cipher.aHex]; 324 | [Z_A appendString:cipher.bHex]; 325 | [Z_A appendString:cipher.gxHex]; 326 | [Z_A appendString:cipher.gyHex]; 327 | [Z_A appendString:Px]; 328 | [Z_A appendString:Py]; 329 | NSData *Z_A_HashData = [O2SSMxHelper sm3DoHashWithData:[O2SSMxUtils dataByHexString:Z_A]]; 330 | 331 | // M = Z_A || srcData 332 | NSMutableData *M = [NSMutableData data]; 333 | [M appendData:Z_A_HashData]; 334 | [M appendData:srcData]; 335 | // e = H256(M) 336 | NSData *eData = [O2SSMxHelper sm3DoHashWithData:M]; 337 | NSString *eHex = [O2SSMxUtils hexStringByData:eData]; 338 | O2SBigInt *e = [[O2SBigInt alloc] initWithString:eHex radix:16]; 339 | 340 | 341 | BOOL repeat = NO; 342 | do{ 343 | repeat = NO; 344 | 345 | O2SBigInt *K = cipher.randomBigIntegerK;//[[O2SBigInt alloc] initWithString:@"6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F" radix:16];;// 346 | O2SECPointFp *KPoint = [cipher kG:K];//随机一个点 347 | NSString *KxHex = [KPoint.getX.toBigInteger toString:16]; 348 | KxHex = [O2SSMxUtils leftPad:KxHex num:cipher.getPointLen/2]; 349 | O2SBigInt *Kx = [[O2SBigInt alloc] initWithString:KxHex radix:16]; 350 | 351 | // r = (e+Kx) mod n 352 | O2SBigInt *r = [[e addByBigInt:Kx] modByBigInt:cipher.n]; 353 | if ([r compare:O2SBigInt.zero] == NSOrderedSame || [[r addByBigInt:K] compare:cipher.n] == NSOrderedSame) 354 | { 355 | repeat = YES; 356 | continue; 357 | } 358 | rHex = [r toString:16]; 359 | rHex = [O2SSMxUtils leftPad:rHex num:cipher.getPointLen/2]; 360 | 361 | // s = ((1+dA)^-1 * (K-r*dA)) mod n 362 | O2SBigInt *t1 = [[O2SBigInt.one addByBigInt: dA] pow:[[O2SBigInt alloc] initWithInt:-1] mod:cipher.n]; 363 | O2SBigInt *t2 = [K subByBigInt:[r multiplyByBigInt:dA]]; 364 | O2SBigInt *s = [[t1 multiplyByBigInt:t2] modByBigInt:cipher.n]; 365 | if ([s compare:O2SBigInt.zero] == NSOrderedSame) 366 | { 367 | repeat = YES; 368 | continue; 369 | } 370 | sHex = [s toString:16]; 371 | sHex = [O2SSMxUtils leftPad:sHex num:cipher.getPointLen/2]; 372 | }while (repeat); 373 | } 374 | return [O2SSMxUtils dataByHexString:[NSString stringWithFormat:@"%@%@",rHex,sHex]]; 375 | } 376 | 377 | 378 | /// sm2 数字签名验签 379 | /// @param userId 用户身份 380 | /// @param srcData 被签名的内容 381 | /// @param publicKey 公钥Q 382 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 383 | /// @param sign 签名校验值 384 | + (BOOL)sm2DoVerifyUserId:(NSString *)userId srcData:(NSData *)srcData publicKey:(NSString *)publicKey cipher:(O2SSM2Cipher *)cipher sign:(NSData *)sign 385 | { 386 | @autoreleasepool { 387 | NSData *userIdData = [userId dataUsingEncoding: NSUTF8StringEncoding]; 388 | NSString * userIdHex = [O2SSMxUtils hexStringByData:userIdData]; 389 | NSString *ENTL_A = [NSString stringWithFormat:@"%lx",userIdData.length * 8]; 390 | ENTL_A = [O2SSMxUtils leftPad:ENTL_A num:4]; 391 | 392 | // 公钥 393 | NSUInteger len = publicKey.length / 2; 394 | NSString *Px = [publicKey substringWithRange:NSMakeRange(0, len)]; 395 | Px = [O2SSMxUtils leftPad:Px num:cipher.getPointLen/2]; 396 | NSString *Py = [publicKey substringWithRange:NSMakeRange(len,len)]; 397 | Py = [O2SSMxUtils leftPad:Py num:cipher.getPointLen/2]; 398 | 399 | // Z_A = H256(ENTL_A || userId || a || b || Gx || Gy || Qx || Qy) 400 | NSMutableString *Z_A = [NSMutableString string]; 401 | [Z_A appendString:ENTL_A]; 402 | [Z_A appendString:userIdHex]; 403 | [Z_A appendString:cipher.aHex]; 404 | [Z_A appendString:cipher.bHex]; 405 | [Z_A appendString:cipher.gxHex]; 406 | [Z_A appendString:cipher.gyHex]; 407 | [Z_A appendString:Px]; 408 | [Z_A appendString:Py]; 409 | NSData *Z_A_HashData = [O2SSMxHelper sm3DoHashWithData:[O2SSMxUtils dataByHexString:Z_A]]; 410 | 411 | // M = Z_A || srcData 412 | NSMutableData *M = [NSMutableData data]; 413 | [M appendData:Z_A_HashData]; 414 | [M appendData:srcData]; 415 | // e = H256(M) 416 | NSData *eData = [O2SSMxHelper sm3DoHashWithData:M]; 417 | NSString *eHex = [O2SSMxUtils hexStringByData:eData]; 418 | O2SBigInt *e = [[O2SBigInt alloc] initWithString:eHex radix:16]; 419 | 420 | // t = (r + s) mod n 421 | NSString *signHex = [O2SSMxUtils hexStringByData:sign]; 422 | len = signHex.length / 2; 423 | NSString *rHex = [signHex substringWithRange:NSMakeRange(0, len)]; 424 | O2SBigInt *r = [[O2SBigInt alloc] initWithString:rHex radix:16]; 425 | 426 | O2SBigInt *n_1 = [cipher.n subByBigInt:O2SBigInt.one]; 427 | 428 | // r ∈ [1,n-1]; 429 | if ([r compare:O2SBigInt.one] == NSOrderedDescending || [r compare:n_1] == NSOrderedAscending) 430 | { 431 | return NO; 432 | } 433 | 434 | NSString *sHex = [signHex substringWithRange:NSMakeRange(len, len)]; 435 | O2SBigInt *s = [[O2SBigInt alloc] initWithString:sHex radix:16]; 436 | 437 | //s ∈ [1,n-1]; 438 | if ([s compare:O2SBigInt.one] == NSOrderedDescending || [s compare:n_1] == NSOrderedAscending) 439 | { 440 | return NO; 441 | } 442 | O2SBigInt *t = [[r addByBigInt:s] modByBigInt:cipher.n]; 443 | // t != 0 444 | if ([t compare:O2SBigInt.zero] == NSOrderedSame) 445 | { 446 | return NO; 447 | } 448 | 449 | //(x,y) = [s]G + [t]P 450 | O2SECPointFp *sGPoint = [cipher kG:s]; 451 | O2SECPointFp *tPPoint = [cipher kP:t PPointHex:publicKey]; 452 | O2SECPointFp *point = [sGPoint add:tPPoint]; 453 | O2SBigInt *x = point.getX.toBigInteger; 454 | 455 | //R = (e + x) mod n 456 | O2SBigInt *R = [[e addByBigInt:x] modByBigInt:cipher.n]; 457 | if ([r compare:R] == NSOrderedSame) 458 | { 459 | return YES; 460 | } 461 | return NO; 462 | } 463 | } 464 | 465 | #pragma mark - SM3 466 | 467 | + (NSData *)sm3DoHashWithString:(NSString *)msg 468 | { 469 | return [O2SSM3Digest hash:msg]; 470 | } 471 | 472 | + (NSData *)sm3DoHashWithData:(NSData *)msg 473 | { 474 | return [O2SSM3Digest hashData:msg]; 475 | } 476 | 477 | #pragma mark - SM4 478 | 479 | @end 480 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/O2SSMxUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSMxUtils.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface O2SSMxUtils : NSObject 12 | 13 | /// 转换16进制字符串为NSData 14 | /// @param string 二进制流的16进制字符串 15 | /// @return 二进制数据对象 16 | + (NSData *)dataByHexString:(NSString *)string; 17 | 18 | /// 将数据转换成16进制字符串 19 | /// @param data data 原始数据 20 | /// @return 字符串 21 | + (NSString *)hexStringByData:(NSData *)data; 22 | 23 | 24 | /// 将 NSData 进行 Base64编码 25 | /// @param data 原始数据 26 | /// @return Base64编码后结果 27 | + (NSString *)stringByBase64EncodeData:(NSData *)data; 28 | 29 | 30 | /// 将Base64编码的值 进行解码 31 | /// @param string Base64编码的值 32 | /// @return Base64解码结果 Data类型 33 | + (NSData *)dataByBase64DecodeString:(NSString *)string; 34 | 35 | 36 | /// 将Base64编码的值 进行解码 37 | /// @param string Base64编码的值 38 | /// @return Base64解码结果 Data类型在转成原始String类型 39 | + (NSString *)stringByBase64DecodeString:(NSString *)string; 40 | 41 | /// 16进制字符串根据长度补齐,不够左边0补齐 42 | /// @param input 16进制字符串 43 | /// @param num 总长度 44 | + (NSString *)leftPad:(NSString *)input num:(NSUInteger)num; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/O2SSMxUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSMxUtils.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SSMxUtils.h" 10 | 11 | @implementation O2SSMxUtils 12 | 13 | + (NSData *)dataByHexString:(NSString *)string 14 | { 15 | if (![string isKindOfClass:[NSString class]]) 16 | { 17 | return nil; 18 | } 19 | 20 | char byte = 0; 21 | 22 | NSString *upperString = [string uppercaseString]; 23 | NSMutableData *data = [NSMutableData data]; 24 | for (int i = 0; i < [upperString length]; i++) 25 | { 26 | NSInteger value = (NSInteger)[upperString characterAtIndex:i]; 27 | if (value >= '0' && value <= '9') 28 | { 29 | if (i % 2 == 0) 30 | { 31 | byte = ((value - '0') << 4) & 0xf0; 32 | 33 | if (i == [upperString length] - 1) 34 | { 35 | [data appendBytes:(const void *)&byte length:1]; 36 | } 37 | } 38 | else 39 | { 40 | byte |= (value - '0') & 0x0f; 41 | [data appendBytes:(const void *)&byte length:1]; 42 | } 43 | } 44 | else if (value >= 'A' && value <= 'F') 45 | { 46 | if (i % 2 == 0) 47 | { 48 | byte = ((value - 'A' + 10) << 4) & 0xf0; 49 | 50 | if (i == [upperString length] - 1) 51 | { 52 | [data appendBytes:(const void *)&byte length:1]; 53 | } 54 | } 55 | else 56 | { 57 | byte |= (value - 'A' + 10) & 0x0f; 58 | [data appendBytes:(const void *)&byte length:1]; 59 | } 60 | } 61 | else 62 | { 63 | data = nil; 64 | break; 65 | } 66 | } 67 | 68 | return data; 69 | } 70 | 71 | + (NSString *)hexStringByData:(NSData *)data 72 | { 73 | if (![data isKindOfClass:[NSData class]]) 74 | { 75 | return nil; 76 | } 77 | 78 | NSMutableString *hexStr = [NSMutableString string]; 79 | const char *buf = [data bytes]; 80 | for (int i = 0; i < [data length]; i++) 81 | { 82 | [hexStr appendFormat:@"%02X", buf[i] & 0xff]; 83 | } 84 | return hexStr; 85 | } 86 | 87 | + (NSString *)stringByBase64EncodeData:(NSData *)data 88 | { 89 | if (![data isKindOfClass:[NSData class]]) 90 | { 91 | return nil; 92 | } 93 | 94 | if (@available(iOS 7.0, *)) 95 | { 96 | return [data base64EncodedStringWithOptions:0]; 97 | } 98 | else 99 | { 100 | return [data base64Encoding]; 101 | } 102 | } 103 | 104 | + (NSData *)dataByBase64DecodeString:(NSString *)string 105 | { 106 | if (![string isKindOfClass:[NSString class]]) 107 | { 108 | return nil; 109 | } 110 | 111 | if (@available(iOS 7.0, *)) 112 | { 113 | return [[NSData alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters]; 114 | } 115 | else 116 | { 117 | return [[NSData alloc] initWithBase64Encoding:string]; 118 | } 119 | } 120 | 121 | + (NSString *)stringByBase64DecodeString:(NSString *)string 122 | { 123 | NSData *data = [self dataByBase64DecodeString:string]; 124 | if(data) 125 | { 126 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 127 | } 128 | return @""; 129 | } 130 | 131 | + (NSString *)leftPad:(NSString *)input num:(NSUInteger)num 132 | { 133 | @autoreleasepool { 134 | if (input.length >= num) 135 | { 136 | return input; 137 | } 138 | 139 | NSMutableString *s = [NSMutableString string]; 140 | NSUInteger len = num - input.length; 141 | for (int i = 0; i < len;) 142 | { 143 | if (i + 4 < len) 144 | { 145 | [s appendFormat:@"0000"]; 146 | i += 4; 147 | continue; 148 | } 149 | else if (i + 3 < len) 150 | { 151 | [s appendFormat:@"000"]; 152 | i += 3; 153 | continue; 154 | } 155 | else if (i + 2 < len) 156 | { 157 | [s appendFormat:@"00"]; 158 | i += 2; 159 | continue; 160 | } 161 | else 162 | { 163 | [s appendFormat:@"0"]; 164 | i += 1; 165 | continue; 166 | } 167 | } 168 | 169 | return [s stringByAppendingString:input]; 170 | } 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/SM2/O2SSM2Cipher+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSM2Cipher+Private.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SSM2Cipher.h" 10 | #import "O2SECCurveFp.h" 11 | 12 | @class O2SBigInt; 13 | @class O2SECPointFp; 14 | 15 | @interface O2SSM2Cipher () 16 | 17 | @property(nonatomic, copy) NSString *pHex; 18 | @property(nonatomic, copy) NSString *aHex; 19 | @property(nonatomic, copy) NSString *bHex; 20 | @property(nonatomic, copy) NSString *gxHex; 21 | @property(nonatomic, copy) NSString *gyHex; 22 | @property(nonatomic, copy) NSString *nHex; 23 | 24 | @property(nonatomic, strong) O2SECCurveFp *curve; 25 | @property(nonatomic, strong) O2SBigInt *n; 26 | 27 | - (O2SBigInt *)randomBigIntegerK; 28 | 29 | - (O2SECPointFp *)kG:(O2SBigInt *)k; 30 | 31 | //pPointHex 非压缩点 32 | - (O2SECPointFp *)kP:(O2SBigInt *)k PPointHex:(NSString *)pPointHex; 33 | - (O2SECPointFp *)kP:(O2SBigInt *)k PPoint:(O2SECPointFp *)pPoint; 34 | 35 | - (NSUInteger)getPointLen; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/SM2/O2SSM2Cipher.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSM2Cipher.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | 14 | typedef NS_ENUM(NSInteger, O2SECCMode) { 15 | //目前仅支持素数域椭圆曲线 16 | O2SECCModeFp = 0, //Fp(素数域)椭圆曲线 y^2 = x^3 + ax + b 17 | //O2SECCModeF2m = 1, //F2m(二元扩域)椭圆曲线 y^2 + xy = x^3 + ax^2 + b 18 | }; 19 | 20 | 21 | @interface O2SSM2Cipher : NSObject 22 | 23 | - (instancetype)init NS_UNAVAILABLE; 24 | 25 | // 自定义素数域椭圆曲线 26 | - (instancetype)initWithFpParamPHex:(NSString *)pHex 27 | aHex:(NSString *)aHex 28 | bHex:(NSString *)bHex 29 | gxHex:(NSString *)gxHex 30 | gyHex:(NSString *)gyHex 31 | nHex:(NSString *)nHex; 32 | 33 | + (O2SSM2Cipher *)EC_Fp_SM2_256V1; 34 | 35 | + (O2SSM2Cipher *)EC_Fp_X9_62_256V1; 36 | 37 | + (O2SSM2Cipher *)EC_Fp_SECG_256K1; 38 | 39 | + (O2SSM2Cipher *)EC_Fp_192; 40 | 41 | + (O2SSM2Cipher *)EC_Fp_256; 42 | 43 | /// 随机生成公私钥,公钥前缀04,代表未压缩 44 | /// return @{@"publicKey": publicKeyValue, @"privateKey": privateKeyValue} 45 | - (NSDictionary *)generateKeyPairHex; 46 | 47 | @end 48 | 49 | NS_ASSUME_NONNULL_END 50 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/SM2/O2SSM2Cipher.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSM2Cipher.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SSM2Cipher.h" 10 | #import "O2SECPointFp.h" 11 | #import "O2SECCurveFp.h" 12 | #import "O2SECFieldElementFp.h" 13 | #import "O2SBigInt.h" 14 | #import "O2SSMxUtils.h" 15 | #import "O2SSM2Cipher+Private.h" 16 | 17 | @interface O2SSM2Cipher () 18 | 19 | @property(nonatomic, strong) O2SECPointFp *g; 20 | 21 | @property(nonatomic, assign) O2SECCMode eccMode; 22 | 23 | @end 24 | 25 | @implementation O2SSM2Cipher 26 | 27 | - (instancetype)initWithFpParamPHex:(NSString *)pHex 28 | aHex:(NSString *)aHex 29 | bHex:(NSString *)bHex 30 | gxHex:(NSString *)gxHex 31 | gyHex:(NSString *)gyHex 32 | nHex:(NSString *)nHex 33 | { 34 | if (self = [super init]) 35 | { 36 | self.pHex = pHex; 37 | self.aHex = aHex; 38 | self.bHex = bHex; 39 | self.gxHex = gxHex; 40 | self.gyHex = gyHex; 41 | self.nHex = nHex; 42 | 43 | O2SBigInt *p = [[O2SBigInt alloc] initWithString:pHex radix:16]; 44 | O2SBigInt *a = [[O2SBigInt alloc] initWithString:aHex radix:16]; 45 | O2SBigInt *b = [[O2SBigInt alloc] initWithString:bHex radix:16]; 46 | if ((gxHex.length != gyHex.length) || gyHex.length % 2 != 0) 47 | { 48 | NSAssert(NO, @"decode point error"); 49 | } 50 | self.curve = [[O2SECCurveFp alloc] initWithQ:p a:a b:b pointLen:gxHex.length * 2]; 51 | self.g = [self.curve decodePointHex:[NSString stringWithFormat:@"04%@%@", gxHex, gyHex]]; 52 | self.n = [[O2SBigInt alloc] initWithString:nHex radix:16]; 53 | 54 | self.eccMode = O2SECCModeFp; 55 | } 56 | return self; 57 | } 58 | 59 | #pragma mark - Fp(素数域)椭圆曲线 y^2 = x^3 + ax + b 60 | 61 | + (O2SSM2Cipher *)EC_Fp_SM2_256V1 62 | { 63 | static O2SSM2Cipher *param; 64 | static dispatch_once_t onceToken; 65 | dispatch_once(&onceToken, ^{ 66 | 67 | NSString *pHex = @"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"; 68 | NSString *aHex = @"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"; 69 | NSString *bHex = @"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"; 70 | 71 | NSString *gxHex = @"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"; 72 | NSString *gyHex = @"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"; 73 | NSString *nHex = @"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"; 74 | 75 | param = [[O2SSM2Cipher alloc] initWithFpParamPHex:pHex 76 | aHex:aHex 77 | bHex:bHex 78 | gxHex:gxHex 79 | gyHex:gyHex 80 | nHex:nHex]; 81 | 82 | }); 83 | return param; 84 | } 85 | 86 | + (O2SSM2Cipher *)EC_Fp_X9_62_256V1 87 | { 88 | static O2SSM2Cipher *param; 89 | static dispatch_once_t onceToken; 90 | dispatch_once(&onceToken, ^{ 91 | 92 | NSString *pHex = @"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"; 93 | NSString *aHex = @"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"; 94 | NSString *bHex = @"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"; 95 | 96 | NSString *gxHex = @"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; 97 | NSString *gyHex = @"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"; 98 | NSString *nHex = @"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"; 99 | 100 | param = [[O2SSM2Cipher alloc] initWithFpParamPHex:pHex 101 | aHex:aHex 102 | bHex:bHex 103 | gxHex:gxHex 104 | gyHex:gyHex 105 | nHex:nHex]; 106 | 107 | }); 108 | return param; 109 | } 110 | 111 | + (O2SSM2Cipher *)EC_Fp_SECG_256K1 112 | { 113 | static O2SSM2Cipher *param; 114 | static dispatch_once_t onceToken; 115 | dispatch_once(&onceToken, ^{ 116 | 117 | NSString *pHex = @"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"; 118 | NSString *aHex = @"0000000000000000000000000000000000000000000000000000000000000000"; 119 | NSString *bHex = @"0000000000000000000000000000000000000000000000000000000000000007"; 120 | 121 | NSString *gxHex = @"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"; 122 | NSString *gyHex = @"483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"; 123 | NSString *nHex = @"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"; 124 | 125 | param = [[O2SSM2Cipher alloc] initWithFpParamPHex:pHex 126 | aHex:aHex 127 | bHex:bHex 128 | gxHex:gxHex 129 | gyHex:gyHex 130 | nHex:nHex]; 131 | 132 | }); 133 | return param; 134 | } 135 | 136 | + (O2SSM2Cipher *)EC_Fp_192 137 | { 138 | static O2SSM2Cipher *param; 139 | static dispatch_once_t onceToken; 140 | dispatch_once(&onceToken, ^{ 141 | 142 | NSString *pHex = @"BDB6F4FE3E8B1D9E0DA8C0D46F4C318CEFE4AFE3B6B8551F"; 143 | NSString *aHex = @"BB8E5E8FBC115E139FE6A814FE48AAA6F0ADA1AA5DF91985"; 144 | NSString *bHex = @"1854BEBDC31B21B7AEFC80AB0ECD10D5B1B3308E6DBF11C1"; 145 | 146 | NSString *gxHex = @"4AD5F7048DE709AD51236DE65E4D4B482C836DC6E4106640"; 147 | NSString *gyHex = @"02BB3A02D4AAADACAE24817A4CA3A1B014B5270432DB27D2"; 148 | NSString *nHex = @"BDB6F4FE3E8B1D9E0DA8C0D40FC962195DFAE76F56564677"; 149 | 150 | param = [[O2SSM2Cipher alloc] initWithFpParamPHex:pHex 151 | aHex:aHex 152 | bHex:bHex 153 | gxHex:gxHex 154 | gyHex:gyHex 155 | nHex:nHex]; 156 | 157 | }); 158 | return param; 159 | } 160 | 161 | + (O2SSM2Cipher *)EC_Fp_256 162 | { 163 | static O2SSM2Cipher *param; 164 | static dispatch_once_t onceToken; 165 | dispatch_once(&onceToken, ^{ 166 | 167 | NSString *pHex = @"8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3"; 168 | NSString *aHex = @"787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498"; 169 | NSString *bHex = @"63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A"; 170 | 171 | NSString *gxHex = @"421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D"; 172 | NSString *gyHex = @"0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"; 173 | NSString *nHex = @"8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7"; 174 | 175 | param = [[O2SSM2Cipher alloc] initWithFpParamPHex:pHex 176 | aHex:aHex 177 | bHex:bHex 178 | gxHex:gxHex 179 | gyHex:gyHex 180 | nHex:nHex]; 181 | 182 | }); 183 | return param; 184 | } 185 | 186 | 187 | //#pragma mark - F2m(二元扩域)椭圆曲线 y^2 + xy = x^3 + ax^2 + b 188 | //+ (O2SSM2Cipher *)EC_F2m_193 189 | //{ 190 | // //F2m-193曲线 191 | // //基域生成多项式:x^193+x^15+1 192 | // static O2SSM2Cipher *param; 193 | // static dispatch_once_t onceToken; 194 | // dispatch_once(&onceToken, ^{ 195 | // NSString *pHex = @"2000000000000000000000000000000000000000000008001"; 196 | // NSString *aHex = @"00"; 197 | // NSString *bHex = @"002FE22037B624DBEBC4C618E13FD998B1A18E1EE0D05C46FB"; 198 | // 199 | // NSString *gxHex = @"00D78D47E85C93644071BC1C212CF994E4D21293AAD8060A84"; 200 | // NSString *gyHex = @"00615B9E98A31B7B2FDDEEECB76B5D875586293725F9D2FC0C"; 201 | // NSString *nHex = @"80000000000000000000000043E9885C46BF45D8C5EBF3A1"; 202 | // 203 | // param = [[O2SSM2Cipher alloc] initWithP2mParamPHex:pHex 204 | // aHex:aHex 205 | // bHex:bHex 206 | // gxHex:gxHex 207 | // gyHex:gyHex 208 | // nHex:nHex]; 209 | // }); 210 | // return param; 211 | //} 212 | // 213 | //+ (O2SSM2Cipher *)EC_F2m_257 214 | //{ 215 | // //F2m-257曲线 216 | // //基域生成多项式:x^257+x^12+1 217 | // static O2SSM2Cipher *param; 218 | // static dispatch_once_t onceToken; 219 | // dispatch_once(&onceToken, ^{ 220 | // NSString *pHex = @"20000000000000000000000000000000000000000000000000000000000001001"; 221 | // NSString *aHex = @"00"; 222 | // NSString *bHex = @"00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B"; 223 | // 224 | // NSString *gxHex = @"00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD"; 225 | // NSString *gyHex = @"013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E"; 226 | // NSString *nHex = @"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D"; 227 | // 228 | // param = [[O2SSM2Cipher alloc] initWithP2mParamPHex:pHex 229 | // aHex:aHex 230 | // bHex:bHex 231 | // gxHex:gxHex 232 | // gyHex:gyHex 233 | // nHex:nHex]; 234 | // }); 235 | // return param; 236 | //} 237 | 238 | #pragma mark - Public 239 | 240 | - (NSDictionary *)generateKeyPairHex 241 | { 242 | @autoreleasepool { 243 | O2SBigInt *rng = [[O2SBigInt alloc] initWithRandomBits:(int)[_n bitLength]]; 244 | O2SBigInt *d = [[rng modByBigInt:[_n subByBigInt:O2SBigInt.one]] addByBigInt:O2SBigInt.one]; 245 | 246 | NSString *privateKey = [O2SSMxUtils leftPad:[d toString:16] num:64]; 247 | 248 | O2SECPointFp *p = [_g multiply:d]; 249 | NSString *px = [O2SSMxUtils leftPad:[[[p getX] toBigInteger] toString:16] num:64]; 250 | NSString *py = [O2SSMxUtils leftPad:[[[p getY] toBigInteger] toString:16] num:64]; 251 | NSString *publicKey = [NSString stringWithFormat:@"04%@%@", px, py]; 252 | 253 | return @{@"publicKey": publicKey, @"privateKey": privateKey}; 254 | } 255 | } 256 | 257 | #pragma mark - Private 258 | 259 | - (NSUInteger)getPointLen 260 | { 261 | return self.curve.pointLen; 262 | } 263 | 264 | - (O2SBigInt *)randomBigIntegerK 265 | { 266 | @autoreleasepool { 267 | O2SBigInt *rng = [[O2SBigInt alloc] initWithRandomBits:(int)[_n bitLength]]; 268 | O2SBigInt *d = [[rng modByBigInt:[_n subByBigInt:O2SBigInt.one]] addByBigInt:O2SBigInt.one]; 269 | return d; 270 | } 271 | } 272 | 273 | - (O2SECPointFp *)kG:(O2SBigInt *)k 274 | { 275 | @autoreleasepool { 276 | O2SECPointFp *kGPoint = [_g multiply:k]; 277 | return kGPoint; 278 | } 279 | } 280 | 281 | - (O2SECPointFp *)kP:(O2SBigInt *)k PPointHex:(NSString *)pPointHex 282 | { 283 | @autoreleasepool { 284 | O2SECPointFp *pPoint = [self.curve decodePointHex:[NSString stringWithFormat:@"04%@", pPointHex]]; 285 | O2SECPointFp *kPPoint = [pPoint multiply:k]; 286 | return kPPoint; 287 | } 288 | } 289 | 290 | - (O2SECPointFp *)kP:(O2SBigInt *)k PPoint:(O2SECPointFp *)pPoint 291 | { 292 | @autoreleasepool { 293 | O2SECPointFp *kPPoint = [pPoint multiply:k]; 294 | return kPPoint; 295 | } 296 | } 297 | 298 | @end 299 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/SM3/O2SSM3Digest.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSM3Digest.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface O2SSM3Digest : NSObject 12 | 13 | + (NSData *)KDF:(NSData *)z keylen:(int)keylen; 14 | 15 | + (NSData *)hash:(NSString *)message; 16 | 17 | + (NSData *)hashData:(NSData *)data; 18 | 19 | @end 20 | 21 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKit/SM3/O2SSM3Digest.mm: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSM3Digest.m 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "O2SSM3Digest.h" 10 | 11 | namespace com 12 | { 13 | namespace o2space 14 | { 15 | namespace sm3 16 | { 17 | /* 18 | * SM3算法产生的哈希值大小(单位:字节) 19 | */ 20 | #define SM3_HASH_SIZE 32 21 | 22 | typedef struct SM3Context 23 | { 24 | unsigned int intermediateHash[SM3_HASH_SIZE / 4]; 25 | unsigned char messageBlock[64]; 26 | } SM3Context; 27 | #pragma mark - 方法定义 28 | 29 | /* 30 | * SM3计算函数 31 | */ 32 | unsigned char *hash_sm3(const unsigned char *message, unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]); 33 | 34 | /* 35 | * 国密SM2加解密算法中的密钥派生函数kdf 36 | */ 37 | int KDF_sm3(const unsigned char *cdata, unsigned int datalen, int keylen, unsigned char *retdata); 38 | 39 | #pragma mark - Private 40 | /* 41 | * 判断运行环境是否为小端 42 | */ 43 | static const int endianTest = 1; 44 | #define IsLittleEndian() (*(char *)&endianTest == 1) 45 | 46 | /* 47 | * 向左循环移位 48 | */ 49 | #define LeftRotate(word, bits) ( (word) << (bits) | (word) >> (32 - (bits)) ) 50 | 51 | /* 52 | * 反转四字节整型字节序 53 | */ 54 | unsigned int *ReverseWord(unsigned int *word) 55 | { 56 | unsigned char *byte, temp; 57 | 58 | byte = (unsigned char *)word; 59 | temp = byte[0]; 60 | byte[0] = byte[3]; 61 | byte[3] = temp; 62 | 63 | temp = byte[1]; 64 | byte[1] = byte[2]; 65 | byte[2] = temp; 66 | return word; 67 | } 68 | 69 | /* 70 | * T 71 | */ 72 | unsigned int T(int i) 73 | { 74 | if (i >= 0 && i <= 15) 75 | return 0x79CC4519; 76 | else if (i >= 16 && i <= 63) 77 | return 0x7A879D8A; 78 | else 79 | return 0; 80 | } 81 | 82 | 83 | /* 84 | * FF 85 | */ 86 | unsigned int FF(unsigned int X, unsigned int Y, unsigned int Z, int i) 87 | { 88 | if (i >= 0 && i <= 15) 89 | return X ^ Y ^ Z; 90 | else if (i >= 16 && i <= 63) 91 | return (X & Y) | (X & Z) | (Y & Z); 92 | else 93 | return 0; 94 | } 95 | 96 | /* 97 | * GG 98 | */ 99 | unsigned int GG(unsigned int X, unsigned int Y, unsigned int Z, int i) 100 | { 101 | if (i >= 0 && i <= 15) 102 | return X ^ Y ^ Z; 103 | else if (i >= 16 && i <= 63) 104 | return (X & Y) | (~X & Z); 105 | else 106 | return 0; 107 | } 108 | 109 | /* 110 | * P0 置换 111 | */ 112 | unsigned int P0(unsigned int X) 113 | { 114 | return X ^ LeftRotate(X, 9) ^ LeftRotate(X, 17); 115 | } 116 | 117 | /* 118 | * P1 置换 119 | */ 120 | unsigned int P1(unsigned int X) 121 | { 122 | return X ^ LeftRotate(X, 15) ^ LeftRotate(X, 23); 123 | } 124 | 125 | /* 126 | * 初始化函数 127 | */ 128 | void SM3Init(SM3Context *context) 129 | { 130 | context->intermediateHash[0] = 0x7380166F; 131 | context->intermediateHash[1] = 0x4914B2B9; 132 | context->intermediateHash[2] = 0x172442D7; 133 | context->intermediateHash[3] = 0xDA8A0600; 134 | context->intermediateHash[4] = 0xA96F30BC; 135 | context->intermediateHash[5] = 0x163138AA; 136 | context->intermediateHash[6] = 0xE38DEE4D; 137 | context->intermediateHash[7] = 0xB0FB0E4E; 138 | } 139 | 140 | /* 141 | * 处理消息块 压缩 142 | */ 143 | void CF(SM3Context *context) 144 | { 145 | int i; 146 | unsigned int W[68]; 147 | unsigned int W_[64]; 148 | unsigned int A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2; 149 | 150 | /* 消息扩展 */ 151 | for (i = 0; i < 16; i++) 152 | { 153 | W[i] = *(unsigned int *)(context->messageBlock + i * 4); 154 | if (IsLittleEndian()) 155 | ReverseWord(W + i); 156 | //printf("%d: %x\n", i, W[i]); 157 | } 158 | for (i = 16; i < 68; i++) 159 | { 160 | W[i] = P1(W[i - 16] ^ W[i - 9] ^ LeftRotate(W[i - 3], 15)) 161 | ^ LeftRotate(W[i - 13], 7) 162 | ^ W[i - 6]; 163 | //printf("%d: %x\n", i, W[i]); 164 | } 165 | for (i = 0; i < 64; i++) 166 | { 167 | W_[i] = W[i] ^ W[i + 4]; 168 | //printf("%d: %x\n", i, W_[i]); 169 | } 170 | 171 | /* 消息压缩 */ 172 | A = context->intermediateHash[0]; 173 | B = context->intermediateHash[1]; 174 | C = context->intermediateHash[2]; 175 | D = context->intermediateHash[3]; 176 | E = context->intermediateHash[4]; 177 | F = context->intermediateHash[5]; 178 | G = context->intermediateHash[6]; 179 | H = context->intermediateHash[7]; 180 | for (i = 0; i < 64; i++) 181 | { 182 | SS1 = LeftRotate((LeftRotate(A, 12) + E + LeftRotate(T(i), i)), 7); 183 | SS2 = SS1 ^ LeftRotate(A, 12); 184 | TT1 = FF(A, B, C, i) + D + SS2 + W_[i]; 185 | TT2 = GG(E, F, G, i) + H + SS1 + W[i]; 186 | D = C; 187 | C = LeftRotate(B, 9); 188 | B = A; 189 | A = TT1; 190 | H = G; 191 | G = LeftRotate(F, 19); 192 | F = E; 193 | E = P0(TT2); 194 | } 195 | context->intermediateHash[0] ^= A; 196 | context->intermediateHash[1] ^= B; 197 | context->intermediateHash[2] ^= C; 198 | context->intermediateHash[3] ^= D; 199 | context->intermediateHash[4] ^= E; 200 | context->intermediateHash[5] ^= F; 201 | context->intermediateHash[6] ^= G; 202 | context->intermediateHash[7] ^= H; 203 | } 204 | 205 | #pragma mark - Public 206 | 207 | /* 208 | * SM3算法主函数 209 | */ 210 | unsigned char *SM3HashMsg(const unsigned char *message, unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]) 211 | { 212 | SM3Context context; 213 | unsigned int i, remainder, bitLen; 214 | 215 | /* 初始化上下文 */ 216 | SM3Init(&context); 217 | 218 | /* 对前面的消息分组进行处理 */ 219 | for (i = 0; i < messageLen / 64; i++) 220 | { 221 | memcpy(context.messageBlock, message + i * 64, 64); 222 | CF(&context); 223 | } 224 | 225 | /* 填充消息分组,并处理 */ 226 | bitLen = messageLen * 8; 227 | if (IsLittleEndian()) 228 | ReverseWord(&bitLen); 229 | remainder = messageLen % 64; 230 | memcpy(context.messageBlock, message + i * 64, remainder); 231 | context.messageBlock[remainder] = 0x80; 232 | if (remainder <= 55) 233 | { 234 | /* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况, 235 | * 故将高 4 个字节赋为 0 。*/ 236 | memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1 - 8 + 4); 237 | memcpy(context.messageBlock + 64 - 4, &bitLen, 4); 238 | CF(&context); 239 | } 240 | else 241 | { 242 | memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1); 243 | CF(&context); 244 | /* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况, 245 | * 故将高 4 个字节赋为 0 。*/ 246 | memset(context.messageBlock, 0, 64 - 4); 247 | memcpy(context.messageBlock + 64 - 4, &bitLen, 4); 248 | CF(&context); 249 | } 250 | 251 | /* 返回结果 */ 252 | if (IsLittleEndian()) 253 | for (i = 0; i < 8; i++) 254 | ReverseWord(context.intermediateHash + i); 255 | memcpy(digest, context.intermediateHash, SM3_HASH_SIZE); 256 | 257 | return digest; 258 | } 259 | 260 | int KDF_sm3(const unsigned char *cdata, unsigned int datalen, int keylen, unsigned char *retdata) 261 | { 262 | 263 | int nRet = -1; 264 | unsigned char *pRet = nullptr; 265 | unsigned char *pData = nullptr; 266 | 267 | if(cdata==NULL || datalen<=0 || keylen<=0) 268 | { 269 | if(pRet) 270 | free(pRet); 271 | if(pData) 272 | free(pData); 273 | 274 | return nRet; 275 | } 276 | 277 | if(NULL == (pRet=(unsigned char *)malloc(keylen))) 278 | { 279 | if(pRet) 280 | free(pRet); 281 | if(pData) 282 | free(pData); 283 | 284 | return nRet; 285 | } 286 | 287 | if(NULL == (pData=(unsigned char *)malloc(datalen+4))) 288 | { 289 | if(pRet) 290 | free(pRet); 291 | if(pData) 292 | free(pData); 293 | 294 | return nRet; 295 | } 296 | 297 | memset(pRet, 0, keylen); 298 | memset(pData, 0, datalen+4); 299 | 300 | unsigned char cdgst[32]={0}; //摘要 301 | unsigned char cCnt[4] = {0}; //计数器的内存表示值 302 | int nCnt = 1; //计数器 303 | int nDgst = 32; //摘要长度 304 | 305 | int nTimes = (keylen+31)/32; //需要计算的次数 306 | int i=0; 307 | memcpy(pData, cdata, datalen); 308 | for(i=0; i>24) & 0xFF; 313 | cCnt[1] = (nCnt>>16) & 0xFF; 314 | cCnt[2] = (nCnt>> 8) & 0xFF; 315 | cCnt[3] = (nCnt ) & 0xFF; 316 | } 317 | memcpy(pData+datalen, cCnt, 4); 318 | SM3HashMsg(pData, datalen+4, cdgst); 319 | 320 | if(i == nTimes-1) //最后一次计算,根据keylen/32是否整除,截取摘要的值 321 | { 322 | if(keylen%32 != 0) 323 | { 324 | nDgst = keylen%32; 325 | } 326 | } 327 | memcpy(pRet+32*i, cdgst, nDgst); 328 | 329 | i++; // 330 | nCnt ++; // 331 | } 332 | 333 | if(retdata != NULL) 334 | { 335 | memcpy(retdata, pRet, keylen); 336 | } 337 | 338 | nRet = 0; 339 | return nRet; 340 | } 341 | } 342 | } 343 | } 344 | 345 | using namespace com::o2space::sm3; 346 | 347 | @implementation O2SSM3Digest 348 | 349 | + (NSData *)KDF:(NSData *)z keylen:(int)keylen 350 | { 351 | Byte *byte = (Byte *)[z bytes]; 352 | 353 | unsigned char output [keylen]; 354 | memset(&output, 0, keylen); 355 | int nRet = KDF_sm3(byte, z.length, keylen, output); 356 | if (nRet == 0) 357 | { 358 | return [NSData dataWithBytes:output length:keylen]; 359 | } 360 | return nil; 361 | } 362 | 363 | + (NSData *)hash:(NSString *)message 364 | { 365 | NSData *aData = [message dataUsingEncoding: NSUTF8StringEncoding]; 366 | return [O2SSM3Digest hashData:aData]; 367 | } 368 | 369 | + (NSData *)hashData:(NSData *)data 370 | { 371 | Byte *byte = (Byte *)[data bytes]; 372 | //const char *input = message.UTF8String; 373 | unsigned char output [32]; 374 | memset(&output, 0, 32); 375 | SM3HashMsg(byte, data.length, output); 376 | return [NSData dataWithBytes:output length:32]; 377 | // return [NSString stringWithCString:(const char *)output encoding:NSUTF8StringEncoding]; 378 | } 379 | 380 | @end 381 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKitTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /O2SECCKit/O2SECCKitTests/O2SECCKitTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECCKitTests.m 3 | // O2SECCKitTests 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface O2SECCKitTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation O2SECCKitTests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | } 20 | 21 | - (void)tearDown { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | // Use XCTAssert and related functions to verify your tests produce the correct results. 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0B64330A2493AFC700A1A965 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B6433092493AFC700A1A965 /* AppDelegate.m */; }; 11 | 0B64330D2493AFC700A1A965 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B64330C2493AFC700A1A965 /* SceneDelegate.m */; }; 12 | 0B6433102493AFC700A1A965 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B64330F2493AFC700A1A965 /* ViewController.m */; }; 13 | 0B6433132493AFC700A1A965 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B6433112493AFC700A1A965 /* Main.storyboard */; }; 14 | 0B6433152493AFCA00A1A965 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0B6433142493AFCA00A1A965 /* Assets.xcassets */; }; 15 | 0B6433182493AFCA00A1A965 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B6433162493AFCA00A1A965 /* LaunchScreen.storyboard */; }; 16 | 0B64331B2493AFCA00A1A965 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B64331A2493AFCA00A1A965 /* main.m */; }; 17 | 0B6433242493B00E00A1A965 /* O2SECCKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6433232493B00E00A1A965 /* O2SECCKit.framework */; }; 18 | 0B64332A2493B14100A1A965 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6433292493B14100A1A965 /* libc++.tbd */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 0B6433052493AFC700A1A965 /* O2SECCKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = O2SECCKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 0B6433082493AFC700A1A965 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | 0B6433092493AFC700A1A965 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | 0B64330B2493AFC700A1A965 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; 26 | 0B64330C2493AFC700A1A965 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; }; 27 | 0B64330E2493AFC700A1A965 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 0B64330F2493AFC700A1A965 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | 0B6433122493AFC700A1A965 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 0B6433142493AFCA00A1A965 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 0B6433172493AFCA00A1A965 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 0B6433192493AFCA00A1A965 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 0B64331A2493AFCA00A1A965 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 0B6433232493B00E00A1A965 /* O2SECCKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = O2SECCKit.framework; sourceTree = ""; }; 35 | 0B6433292493B14100A1A965 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | 0B6433022493AFC700A1A965 /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | 0B64332A2493B14100A1A965 /* libc++.tbd in Frameworks */, 44 | 0B6433242493B00E00A1A965 /* O2SECCKit.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 0B6432FC2493AFC700A1A965 = { 52 | isa = PBXGroup; 53 | children = ( 54 | 0B6433072493AFC700A1A965 /* O2SECCKitDemo */, 55 | 0B6433062493AFC700A1A965 /* Products */, 56 | 0B6433282493B14100A1A965 /* Frameworks */, 57 | ); 58 | sourceTree = ""; 59 | }; 60 | 0B6433062493AFC700A1A965 /* Products */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 0B6433052493AFC700A1A965 /* O2SECCKitDemo.app */, 64 | ); 65 | name = Products; 66 | sourceTree = ""; 67 | }; 68 | 0B6433072493AFC700A1A965 /* O2SECCKitDemo */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 0B6433212493B00E00A1A965 /* O2SPACE_SDK */, 72 | 0B6433082493AFC700A1A965 /* AppDelegate.h */, 73 | 0B6433092493AFC700A1A965 /* AppDelegate.m */, 74 | 0B64330B2493AFC700A1A965 /* SceneDelegate.h */, 75 | 0B64330C2493AFC700A1A965 /* SceneDelegate.m */, 76 | 0B64330E2493AFC700A1A965 /* ViewController.h */, 77 | 0B64330F2493AFC700A1A965 /* ViewController.m */, 78 | 0B6433112493AFC700A1A965 /* Main.storyboard */, 79 | 0B6433142493AFCA00A1A965 /* Assets.xcassets */, 80 | 0B6433162493AFCA00A1A965 /* LaunchScreen.storyboard */, 81 | 0B6433192493AFCA00A1A965 /* Info.plist */, 82 | 0B64331A2493AFCA00A1A965 /* main.m */, 83 | ); 84 | path = O2SECCKitDemo; 85 | sourceTree = ""; 86 | }; 87 | 0B6433212493B00E00A1A965 /* O2SPACE_SDK */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 0B6433222493B00E00A1A965 /* O2SECCSDK */, 91 | ); 92 | name = O2SPACE_SDK; 93 | path = ../../O2SPACE_SDK; 94 | sourceTree = ""; 95 | }; 96 | 0B6433222493B00E00A1A965 /* O2SECCSDK */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 0B6433232493B00E00A1A965 /* O2SECCKit.framework */, 100 | ); 101 | path = O2SECCSDK; 102 | sourceTree = ""; 103 | }; 104 | 0B6433282493B14100A1A965 /* Frameworks */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 0B6433292493B14100A1A965 /* libc++.tbd */, 108 | ); 109 | name = Frameworks; 110 | sourceTree = ""; 111 | }; 112 | /* End PBXGroup section */ 113 | 114 | /* Begin PBXNativeTarget section */ 115 | 0B6433042493AFC700A1A965 /* O2SECCKitDemo */ = { 116 | isa = PBXNativeTarget; 117 | buildConfigurationList = 0B64331E2493AFCA00A1A965 /* Build configuration list for PBXNativeTarget "O2SECCKitDemo" */; 118 | buildPhases = ( 119 | 0B6433012493AFC700A1A965 /* Sources */, 120 | 0B6433022493AFC700A1A965 /* Frameworks */, 121 | 0B6433032493AFC700A1A965 /* Resources */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = O2SECCKitDemo; 128 | productName = O2SECCKitDemo; 129 | productReference = 0B6433052493AFC700A1A965 /* O2SECCKitDemo.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | 0B6432FD2493AFC700A1A965 /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastUpgradeCheck = 1130; 139 | ORGANIZATIONNAME = O2Space; 140 | TargetAttributes = { 141 | 0B6433042493AFC700A1A965 = { 142 | CreatedOnToolsVersion = 11.3.1; 143 | }; 144 | }; 145 | }; 146 | buildConfigurationList = 0B6433002493AFC700A1A965 /* Build configuration list for PBXProject "O2SECCKitDemo" */; 147 | compatibilityVersion = "Xcode 9.3"; 148 | developmentRegion = en; 149 | hasScannedForEncodings = 0; 150 | knownRegions = ( 151 | en, 152 | Base, 153 | ); 154 | mainGroup = 0B6432FC2493AFC700A1A965; 155 | productRefGroup = 0B6433062493AFC700A1A965 /* Products */; 156 | projectDirPath = ""; 157 | projectRoot = ""; 158 | targets = ( 159 | 0B6433042493AFC700A1A965 /* O2SECCKitDemo */, 160 | ); 161 | }; 162 | /* End PBXProject section */ 163 | 164 | /* Begin PBXResourcesBuildPhase section */ 165 | 0B6433032493AFC700A1A965 /* Resources */ = { 166 | isa = PBXResourcesBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | 0B6433182493AFCA00A1A965 /* LaunchScreen.storyboard in Resources */, 170 | 0B6433152493AFCA00A1A965 /* Assets.xcassets in Resources */, 171 | 0B6433132493AFC700A1A965 /* Main.storyboard in Resources */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXResourcesBuildPhase section */ 176 | 177 | /* Begin PBXSourcesBuildPhase section */ 178 | 0B6433012493AFC700A1A965 /* Sources */ = { 179 | isa = PBXSourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 0B6433102493AFC700A1A965 /* ViewController.m in Sources */, 183 | 0B64330A2493AFC700A1A965 /* AppDelegate.m in Sources */, 184 | 0B64331B2493AFCA00A1A965 /* main.m in Sources */, 185 | 0B64330D2493AFC700A1A965 /* SceneDelegate.m in Sources */, 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | /* End PBXSourcesBuildPhase section */ 190 | 191 | /* Begin PBXVariantGroup section */ 192 | 0B6433112493AFC700A1A965 /* Main.storyboard */ = { 193 | isa = PBXVariantGroup; 194 | children = ( 195 | 0B6433122493AFC700A1A965 /* Base */, 196 | ); 197 | name = Main.storyboard; 198 | sourceTree = ""; 199 | }; 200 | 0B6433162493AFCA00A1A965 /* LaunchScreen.storyboard */ = { 201 | isa = PBXVariantGroup; 202 | children = ( 203 | 0B6433172493AFCA00A1A965 /* Base */, 204 | ); 205 | name = LaunchScreen.storyboard; 206 | sourceTree = ""; 207 | }; 208 | /* End PBXVariantGroup section */ 209 | 210 | /* Begin XCBuildConfiguration section */ 211 | 0B64331C2493AFCA00A1A965 /* Debug */ = { 212 | isa = XCBuildConfiguration; 213 | buildSettings = { 214 | ALWAYS_SEARCH_USER_PATHS = NO; 215 | CLANG_ANALYZER_NONNULL = YES; 216 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 217 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 218 | CLANG_CXX_LIBRARY = "libc++"; 219 | CLANG_ENABLE_MODULES = YES; 220 | CLANG_ENABLE_OBJC_ARC = YES; 221 | CLANG_ENABLE_OBJC_WEAK = YES; 222 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 223 | CLANG_WARN_BOOL_CONVERSION = YES; 224 | CLANG_WARN_COMMA = YES; 225 | CLANG_WARN_CONSTANT_CONVERSION = YES; 226 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 227 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 228 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 229 | CLANG_WARN_EMPTY_BODY = YES; 230 | CLANG_WARN_ENUM_CONVERSION = YES; 231 | CLANG_WARN_INFINITE_RECURSION = YES; 232 | CLANG_WARN_INT_CONVERSION = YES; 233 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 234 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 235 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 236 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 237 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 238 | CLANG_WARN_STRICT_PROTOTYPES = YES; 239 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 240 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 241 | CLANG_WARN_UNREACHABLE_CODE = YES; 242 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 243 | COPY_PHASE_STRIP = NO; 244 | DEBUG_INFORMATION_FORMAT = dwarf; 245 | ENABLE_STRICT_OBJC_MSGSEND = YES; 246 | ENABLE_TESTABILITY = YES; 247 | GCC_C_LANGUAGE_STANDARD = gnu11; 248 | GCC_DYNAMIC_NO_PIC = NO; 249 | GCC_NO_COMMON_BLOCKS = YES; 250 | GCC_OPTIMIZATION_LEVEL = 0; 251 | GCC_PREPROCESSOR_DEFINITIONS = ( 252 | "DEBUG=1", 253 | "$(inherited)", 254 | ); 255 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 256 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 257 | GCC_WARN_UNDECLARED_SELECTOR = YES; 258 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 259 | GCC_WARN_UNUSED_FUNCTION = YES; 260 | GCC_WARN_UNUSED_VARIABLE = YES; 261 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 262 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 263 | MTL_FAST_MATH = YES; 264 | ONLY_ACTIVE_ARCH = YES; 265 | SDKROOT = iphoneos; 266 | }; 267 | name = Debug; 268 | }; 269 | 0B64331D2493AFCA00A1A965 /* Release */ = { 270 | isa = XCBuildConfiguration; 271 | buildSettings = { 272 | ALWAYS_SEARCH_USER_PATHS = NO; 273 | CLANG_ANALYZER_NONNULL = YES; 274 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 275 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 276 | CLANG_CXX_LIBRARY = "libc++"; 277 | CLANG_ENABLE_MODULES = YES; 278 | CLANG_ENABLE_OBJC_ARC = YES; 279 | CLANG_ENABLE_OBJC_WEAK = YES; 280 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 281 | CLANG_WARN_BOOL_CONVERSION = YES; 282 | CLANG_WARN_COMMA = YES; 283 | CLANG_WARN_CONSTANT_CONVERSION = YES; 284 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 285 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 286 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 287 | CLANG_WARN_EMPTY_BODY = YES; 288 | CLANG_WARN_ENUM_CONVERSION = YES; 289 | CLANG_WARN_INFINITE_RECURSION = YES; 290 | CLANG_WARN_INT_CONVERSION = YES; 291 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 292 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 293 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 294 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 295 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 296 | CLANG_WARN_STRICT_PROTOTYPES = YES; 297 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 298 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 299 | CLANG_WARN_UNREACHABLE_CODE = YES; 300 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 301 | COPY_PHASE_STRIP = NO; 302 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 303 | ENABLE_NS_ASSERTIONS = NO; 304 | ENABLE_STRICT_OBJC_MSGSEND = YES; 305 | GCC_C_LANGUAGE_STANDARD = gnu11; 306 | GCC_NO_COMMON_BLOCKS = YES; 307 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 308 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 309 | GCC_WARN_UNDECLARED_SELECTOR = YES; 310 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 311 | GCC_WARN_UNUSED_FUNCTION = YES; 312 | GCC_WARN_UNUSED_VARIABLE = YES; 313 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 314 | MTL_ENABLE_DEBUG_INFO = NO; 315 | MTL_FAST_MATH = YES; 316 | SDKROOT = iphoneos; 317 | VALIDATE_PRODUCT = YES; 318 | }; 319 | name = Release; 320 | }; 321 | 0B64331F2493AFCA00A1A965 /* Debug */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 325 | CODE_SIGN_IDENTITY = "iPhone Developer"; 326 | CODE_SIGN_STYLE = Automatic; 327 | DEVELOPMENT_TEAM = ""; 328 | FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../O2SPACE_SDK\"/**"; 329 | INFOPLIST_FILE = O2SECCKitDemo/Info.plist; 330 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 331 | LD_RUNPATH_SEARCH_PATHS = ( 332 | "$(inherited)", 333 | "@executable_path/Frameworks", 334 | ); 335 | PRODUCT_BUNDLE_IDENTIFIER = com.O2Space.O2SECCKitDemo; 336 | PRODUCT_NAME = "$(TARGET_NAME)"; 337 | PROVISIONING_PROFILE_SPECIFIER = ""; 338 | TARGETED_DEVICE_FAMILY = "1,2"; 339 | }; 340 | name = Debug; 341 | }; 342 | 0B6433202493AFCA00A1A965 /* Release */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 346 | CODE_SIGN_IDENTITY = "iPhone Developer"; 347 | CODE_SIGN_STYLE = Automatic; 348 | DEVELOPMENT_TEAM = ""; 349 | FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../O2SPACE_SDK\"/**"; 350 | INFOPLIST_FILE = O2SECCKitDemo/Info.plist; 351 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 352 | LD_RUNPATH_SEARCH_PATHS = ( 353 | "$(inherited)", 354 | "@executable_path/Frameworks", 355 | ); 356 | PRODUCT_BUNDLE_IDENTIFIER = com.O2Space.O2SECCKitDemo; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | PROVISIONING_PROFILE_SPECIFIER = ""; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | }; 361 | name = Release; 362 | }; 363 | /* End XCBuildConfiguration section */ 364 | 365 | /* Begin XCConfigurationList section */ 366 | 0B6433002493AFC700A1A965 /* Build configuration list for PBXProject "O2SECCKitDemo" */ = { 367 | isa = XCConfigurationList; 368 | buildConfigurations = ( 369 | 0B64331C2493AFCA00A1A965 /* Debug */, 370 | 0B64331D2493AFCA00A1A965 /* Release */, 371 | ); 372 | defaultConfigurationIsVisible = 0; 373 | defaultConfigurationName = Release; 374 | }; 375 | 0B64331E2493AFCA00A1A965 /* Build configuration list for PBXNativeTarget "O2SECCKitDemo" */ = { 376 | isa = XCConfigurationList; 377 | buildConfigurations = ( 378 | 0B64331F2493AFCA00A1A965 /* Debug */, 379 | 0B6433202493AFCA00A1A965 /* Release */, 380 | ); 381 | defaultConfigurationIsVisible = 0; 382 | defaultConfigurationName = Release; 383 | }; 384 | /* End XCConfigurationList section */ 385 | }; 386 | rootObject = 0B6432FD2493AFC700A1A965 /* Project object */; 387 | } 388 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo.xcodeproj/project.xcworkspace/xcuserdata/wkx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/O2SECCKitDemo/O2SECCKitDemo.xcodeproj/project.xcworkspace/xcuserdata/wkx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo.xcodeproj/xcuserdata/wkx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | O2SECCKitDemo.xcscheme 8 | 9 | orderHint 10 | 3 11 | 12 | O2SECCKitDemo.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 3 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // O2SECCKitDemo 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // O2SECCKitDemo 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | #pragma mark - UISceneSession lifecycle 25 | 26 | 27 | - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { 28 | // Called when a new scene session is being created. 29 | // Use this method to select a configuration to create the new scene with. 30 | return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; 31 | } 32 | 33 | 34 | - (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { 35 | // Called when the user discards a scene session. 36 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 37 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 30 | 41 | 52 | 63 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // O2SECCKitDemo 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SceneDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | #import "SceneDelegate.h" 2 | 3 | @interface SceneDelegate () 4 | 5 | @end 6 | 7 | @implementation SceneDelegate 8 | 9 | 10 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { 11 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 12 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 13 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 14 | } 15 | 16 | 17 | - (void)sceneDidDisconnect:(UIScene *)scene { 18 | // Called as the scene is being released by the system. 19 | // This occurs shortly after the scene enters the background, or when its session is discarded. 20 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 21 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 22 | } 23 | 24 | 25 | - (void)sceneDidBecomeActive:(UIScene *)scene { 26 | // Called when the scene has moved from an inactive state to an active state. 27 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 28 | } 29 | 30 | 31 | - (void)sceneWillResignActive:(UIScene *)scene { 32 | // Called when the scene will move from an active state to an inactive state. 33 | // This may occur due to temporary interruptions (ex. an incoming phone call). 34 | } 35 | 36 | 37 | - (void)sceneWillEnterForeground:(UIScene *)scene { 38 | // Called as the scene transitions from the background to the foreground. 39 | // Use this method to undo the changes made on entering the background. 40 | } 41 | 42 | 43 | - (void)sceneDidEnterBackground:(UIScene *)scene { 44 | // Called as the scene transitions from the foreground to the background. 45 | // Use this method to save data, release shared resources, and store enough scene-specific state information 46 | // to restore the scene back to its current state. 47 | } 48 | 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // O2SECCKitDemo 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // O2SECCKitDemo 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | 12 | @interface ViewController () 13 | 14 | @property (nonatomic, copy) NSData *signData; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view. 23 | NSString *str = @"ALICE123@YAHOO.COM"; 24 | NSData *plainData = [str dataUsingEncoding: NSUTF8StringEncoding]; 25 | NSString * str16 = [O2SSMxUtils hexStringByData:plainData]; 26 | } 27 | 28 | - (IBAction)onGenerateKeyPair:(id)sender 29 | { 30 | NSDictionary *keyPair = [O2SSM2Cipher EC_Fp_SM2_256V1].generateKeyPairHex; 31 | NSLog(@"publicKey:%@",keyPair[@"publicKey"]); 32 | NSLog(@"privateKey:%@",keyPair[@"privateKey"]); 33 | } 34 | 35 | - (IBAction)onStartSM2Crypt:(id)sender 36 | { 37 | for (int i = 0; i < 100; i++) { 38 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 39 | @autoreleasepool { 40 | NSString *plainText = [NSString stringWithFormat:@"hello world 哈哈 i=%04d",i]; 41 | NSData *plainData = [plainText dataUsingEncoding: NSUTF8StringEncoding]; 42 | 43 | NSString *publicKey = @"34B3C792B462041066F697B1018C4A96E615EE889A33FFDF8F870BC1662A4234091F5D6D4220AFDAF0041B9CA7DD880016A90F246C26F173DD61BA371D376E26"; 44 | O2SSM2Cipher *cipher = [O2SSM2Cipher EC_Fp_X9_62_256V1]; 45 | NSData *cipherData = [O2SSMxHelper sm2DoEncrypt:plainData publicKey:publicKey cipher:cipher cipherMode:O2SSM2CipherModeC1C2C3]; 46 | if (cipherData == nil) 47 | { 48 | NSLog(@"加密失败"); 49 | return; 50 | } 51 | else 52 | { 53 | NSLog(@"加密结果16进制字符串:%@",[O2SSMxUtils hexStringByData:cipherData]); 54 | NSLog(@"加密结果Base64编码字符串:%@",[O2SSMxUtils stringByBase64EncodeData:cipherData]); 55 | } 56 | NSString *privateKey = @"EFA93286160DFDE76C876A6A994DD334624044270BB27C218AE9272A597BE5DA"; 57 | NSData *m = [O2SSMxHelper sm2DoDecrypt:cipherData privateKey:privateKey cipher:cipher cipherMode:O2SSM2CipherModeC1C2C3]; 58 | if (m) 59 | { 60 | NSLog(@"解密成功:%@",[[NSString alloc] initWithData:m encoding:NSUTF8StringEncoding]); 61 | 62 | } 63 | else 64 | { 65 | NSLog(@"解密失败%04d", i); 66 | } 67 | } 68 | }); 69 | } 70 | } 71 | 72 | - (IBAction)onSM2Sign:(id)sender 73 | { 74 | NSString *p = @"8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3"; 75 | NSString *a = @"787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498"; 76 | NSString *b = @"63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A"; 77 | NSString *Gx = @"421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D"; 78 | NSString *Gy = @"0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"; 79 | NSString *n = @"8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7"; 80 | O2SSM2Cipher *cipher = [[O2SSM2Cipher alloc] initWithFpParamPHex:p aHex:a bHex:b gxHex:Gx gyHex:Gy nHex:n]; 81 | NSString *privateKey = @"128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263"; //私钥 82 | 83 | NSString *userId = @"o2space@163.com"; 84 | NSString *srcStr = @"ABCDEFG1234566 Hello world, 哈哈"; 85 | NSData *srcData = [srcStr dataUsingEncoding: NSUTF8StringEncoding]; 86 | 87 | NSData *signData = [O2SSMxHelper sm2DoSignUserId:userId srcData:srcData privateKey:privateKey cipher:cipher]; 88 | self.signData = signData; 89 | NSLog(@"sign:%@",[O2SSMxUtils hexStringByData:signData]); 90 | } 91 | 92 | - (IBAction)onSM2Verify:(id)sender 93 | { 94 | if (self.signData == nil) 95 | { 96 | NSLog(@"请先进行签名"); 97 | return; 98 | } 99 | NSString *p = @"8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3"; 100 | NSString *a = @"787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498"; 101 | NSString *b = @"63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A"; 102 | NSString *Gx = @"421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D"; 103 | NSString *Gy = @"0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"; 104 | NSString *n = @"8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7"; 105 | O2SSM2Cipher *cipher = [[O2SSM2Cipher alloc] initWithFpParamPHex:p aHex:a bHex:b gxHex:Gx gyHex:Gy nHex:n]; 106 | NSString *publicKey = @"0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857"; //公钥 107 | 108 | NSString *userId = @"o2space@163.com"; 109 | NSString *srcStr = @"ABCDEFG1234566 Hello world, 哈哈"; 110 | NSData *srcData = [srcStr dataUsingEncoding: NSUTF8StringEncoding]; 111 | 112 | BOOL verify = [O2SSMxHelper sm2DoVerifyUserId:userId srcData:srcData publicKey:publicKey cipher:cipher sign:self.signData]; 113 | NSLog(@"%@",verify?@"验签成功":@"验签失败"); 114 | } 115 | 116 | - (IBAction)onSM3Hash:(id)sender 117 | { 118 | NSString *sourceStr = @"哈哈哈"; 119 | NSData *data = [O2SSMxHelper sm3DoHashWithString:sourceStr]; 120 | NSLog(@"SM3 HASH:%@",[O2SSMxUtils hexStringByData:data]); 121 | } 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /O2SECCKitDemo/O2SECCKitDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // O2SECCKitDemo 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /O2SECCKitProject.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /O2SECCKitProject.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /O2SECCKitProject.xcworkspace/xcuserdata/wkx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/O2SECCKitProject.xcworkspace/xcuserdata/wkx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /O2SECCKitProject.xcworkspace/xcuserdata/wkx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/Headers/O2SECCKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SECCKit.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | #import 13 | #import 14 | 15 | -------------------------------------------------------------------------------- /O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/Headers/O2SSM2Cipher.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSM2Cipher.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | 14 | typedef NS_ENUM(NSInteger, O2SECCMode) { 15 | //目前仅支持素数域椭圆曲线 16 | O2SECCModeFp = 0, //Fp(素数域)椭圆曲线 y^2 = x^3 + ax + b 17 | //O2SECCModeF2m = 1, //F2m(二元扩域)椭圆曲线 y^2 + xy = x^3 + ax^2 + b 18 | }; 19 | 20 | 21 | @interface O2SSM2Cipher : NSObject 22 | 23 | - (instancetype)init NS_UNAVAILABLE; 24 | 25 | // 自定义素数域椭圆曲线 26 | - (instancetype)initWithFpParamPHex:(NSString *)pHex 27 | aHex:(NSString *)aHex 28 | bHex:(NSString *)bHex 29 | gxHex:(NSString *)gxHex 30 | gyHex:(NSString *)gyHex 31 | nHex:(NSString *)nHex; 32 | 33 | + (O2SSM2Cipher *)EC_Fp_SM2_256V1; 34 | 35 | + (O2SSM2Cipher *)EC_Fp_X9_62_256V1; 36 | 37 | + (O2SSM2Cipher *)EC_Fp_SECG_256K1; 38 | 39 | + (O2SSM2Cipher *)EC_Fp_192; 40 | 41 | + (O2SSM2Cipher *)EC_Fp_256; 42 | 43 | /// 随机生成公私钥,公钥前缀04,代表未压缩 44 | /// return @{@"publicKey": publicKeyValue, @"privateKey": privateKeyValue} 45 | - (NSDictionary *)generateKeyPairHex; 46 | 47 | @end 48 | 49 | NS_ASSUME_NONNULL_END 50 | -------------------------------------------------------------------------------- /O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/Headers/O2SSMxHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSMxHelper.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class O2SSM2Cipher; 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | typedef NS_ENUM(NSInteger, O2SSM2CipherMode) { 16 | O2SSM2CipherModeC1C3C2 = 0, 17 | O2SSM2CipherModeC1C2C3 = 1, 18 | }; 19 | 20 | @interface O2SSMxHelper : NSObject 21 | 22 | #pragma mark - SM2 23 | 24 | /// sm2加密 25 | /// @param plainData 明文 26 | /// @param publicKey 公钥 是私钥k*G的值 这里传点x和点y的拼接无需带04 ,非der, der文件可通过asn.1解码获得 https://aks.jd.com/tools/sec/ 27 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 28 | /// @param cipherMode c1+c2+c3或c1+c3+c2 29 | + (NSData *)sm2DoEncrypt:(NSData *)plainData 30 | publicKey:(NSString *)publicKey 31 | cipher:(O2SSM2Cipher *)cipher 32 | cipherMode:(O2SSM2CipherMode)cipherMode; 33 | 34 | 35 | /// sm2解密 36 | /// @param cipherData 密文 37 | /// @param privateKey 私钥 非der ,der文件可通过asn.1解码获得 https://aks.jd.com/tools/sec/ 38 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 39 | /// @param cipherMode c1+c2+c3或c1+c3+c2 40 | + (NSData *)sm2DoDecrypt:(NSData *)cipherData 41 | privateKey:(NSString *)privateKey 42 | cipher:(O2SSM2Cipher *)cipher 43 | cipherMode:(O2SSM2CipherMode)cipherMode; 44 | 45 | 46 | /// sm2签名 47 | /// @param userId 用户身份标识 48 | /// @param srcData 待签名内容 49 | /// @param privateKey 私钥 50 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 51 | + (NSData *)sm2DoSignUserId:(NSString *)userId 52 | srcData:(NSData *)srcData 53 | privateKey:(NSString *)privateKey 54 | cipher:(O2SSM2Cipher *)cipher; 55 | 56 | 57 | /// sm2验签 58 | /// @param userId 用户身份标识 59 | /// @param srcData 待签名内容 60 | /// @param publicKey 公钥 61 | /// @param cipher 椭圆曲线相关系数(p,a,b,Gx,Gy,n) 62 | /// @param sign 签名数据用于校验 63 | + (BOOL)sm2DoVerifyUserId:(NSString *)userId 64 | srcData:(NSData *)srcData 65 | publicKey:(NSString *)publicKey 66 | cipher:(O2SSM2Cipher *)cipher 67 | sign:(NSData *)sign; 68 | 69 | #pragma mark - SM3 70 | 71 | /// sm3 摘要 72 | /// @param msg String类型原始值 73 | + (NSData *)sm3DoHashWithString:(NSString *)msg; 74 | 75 | /// sm3 摘要 76 | /// @param msg Data类型原始值 77 | + (NSData *)sm3DoHashWithData:(NSData *)msg; 78 | 79 | @end 80 | 81 | NS_ASSUME_NONNULL_END 82 | -------------------------------------------------------------------------------- /O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/Headers/O2SSMxUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // O2SSMxUtils.h 3 | // O2SECCKit 4 | // 5 | // Created by wkx on 2020/6/12. 6 | // Copyright © 2020 O2Space. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface O2SSMxUtils : NSObject 12 | 13 | /// 转换16进制字符串为NSData 14 | /// @param string 二进制流的16进制字符串 15 | /// @return 二进制数据对象 16 | + (NSData *)dataByHexString:(NSString *)string; 17 | 18 | /// 将数据转换成16进制字符串 19 | /// @param data data 原始数据 20 | /// @return 字符串 21 | + (NSString *)hexStringByData:(NSData *)data; 22 | 23 | 24 | /// 将 NSData 进行 Base64编码 25 | /// @param data 原始数据 26 | /// @return Base64编码后结果 27 | + (NSString *)stringByBase64EncodeData:(NSData *)data; 28 | 29 | 30 | /// 将Base64编码的值 进行解码 31 | /// @param string Base64编码的值 32 | /// @return Base64解码结果 Data类型 33 | + (NSData *)dataByBase64DecodeString:(NSString *)string; 34 | 35 | 36 | /// 将Base64编码的值 进行解码 37 | /// @param string Base64编码的值 38 | /// @return Base64解码结果 Data类型在转成原始String类型 39 | + (NSString *)stringByBase64DecodeString:(NSString *)string; 40 | 41 | /// 16进制字符串根据长度补齐,不够左边0补齐 42 | /// @param input 16进制字符串 43 | /// @param num 总长度 44 | + (NSString *)leftPad:(NSString *)input num:(NSUInteger)num; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/Info.plist -------------------------------------------------------------------------------- /O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module O2SECCKit { 2 | umbrella header "O2SECCKit.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/O2SECCKit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/O2SPACE_SDK/O2SECCSDK/O2SECCKit.framework/O2SECCKit -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 椭圆曲线加解密(国密):SM2,不依赖第三方库OpenSSL实现(O2SECCKit) 2 | 3 | > 目前只实现了素数域椭圆曲线(y^2 = x^3 + ax + b)的SM2加解密、签名和验签及SM3的Hash摘要 4 | > 椭圆曲线分为: 5 | > 6 | > * Fp(素数域)椭圆曲线 y^2 = x^3 + ax + b,素数域曲线应该已经够用了 7 | > * F2m(二元扩域)椭圆曲线 y^2 + xy = x^3 + ax^2 + b 8 | > 9 | >二元扩域曲线及SM4对称加密,后续抽空实现 10 | > 11 | 12 | 开源此组件**O2SECCKit** [github](https://github.com/o2space/O2SECCKit) 13 | 14 | #### 一、集成步骤 15 | 16 | 通过Cocoapods集成 17 | 18 | ``` 19 | //在 Podfile 文件中添加命令: 20 | pod 'O2SECCKit' 21 | ``` 22 | 23 | #### 二、使用说明 24 | 25 | ``` 26 | // 引入SDK 27 | #import 28 | //对外开放功能类O2SSMxHelper 29 | ``` 30 | **加解密** 31 | 32 | ``` 33 | //sm2 加密 34 | NSString *plainText = [NSString stringWithFormat:@"hello world 哈哈"]; 35 | NSData *plainData = [plainText dataUsingEncoding: NSUTF8StringEncoding]; 36 | //公钥 37 | NSString *publicKey = @"34B3C792B462041066F697B1018C4A96E615EE889A33FFDF8F870BC1662A4234091F5D6D4220AFDAF0041B9CA7DD880016A90F246C26F173DD61BA371D376E26"; 38 | O2SSM2Cipher *cipher = [O2SSM2Cipher EC_Fp_X9_62_256V1];//这里是Fp通用曲线,可自定义椭圆曲线系统 39 | NSData *cipherData = [O2SSMxHelper sm2DoEncrypt:plainData publicKey:publicKey cipher:cipher cipherMode:O2SSM2CipherModeC1C2C3];//加密 40 | 41 | //sm2 解密 42 | //私钥 43 | NSString *privateKey = @"EFA93286160DFDE76C876A6A994DD334624044270BB27C218AE9272A597BE5DA"; 44 | //使用跟加密相同的椭圆曲线及系数 45 | NSData *m = [O2SSMxHelper sm2DoDecrypt:cipherData privateKey:privateKey cipher:cipher cipherMode:O2SSM2CipherModeC1C2C3];//解密 46 | 47 | ``` 48 | 49 | **签名、验签** 50 | 51 | ``` 52 | NSString *userId = @"o2space@163.com"; 53 | NSString *srcStr = @"ABCDEFG1234566 Hello world, 中文"; 54 | NSData *srcData = [srcStr dataUsingEncoding: NSUTF8StringEncoding]; 55 | 56 | //sm2 签名 57 | NSString *p = @"8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3"; 58 | NSString *a = @"787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498"; 59 | NSString *b = @"63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A"; 60 | NSString *Gx = @"421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D"; 61 | NSString *Gy = @"0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"; 62 | NSString *n = @"8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7"; 63 | //自定义Fp椭圆曲线系数 64 | O2SSM2Cipher *cipher = [[O2SSM2Cipher alloc] initWithFpParamPHex:p aHex:a bHex:b gxHex:Gx gyHex:Gy nHex:n]; 65 | //私钥 66 | NSString *privateKey = @"128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263"; 67 | NSData *signData = [O2SSMxHelper sm2DoSignUserId:userId srcData:srcData privateKey:privateKey cipher:cipher]; 68 | 69 | //sm2 验签 70 | //cipher与签名时的椭圆曲线及系数相同 71 | //公钥 72 | NSString *publicKey = @"0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857"; 73 | BOOL verify = [O2SSMxHelper sm2DoVerifyUserId:userId srcData:srcData publicKey:publicKey cipher:cipher sign: signData]; 74 | NSLog(@"%@",verify?@"验签成功":@"验签失败"); 75 | ``` 76 | 77 | **sm2随机生成公私钥** 78 | 79 | ``` 80 | //O2SSM2Cipher类 81 | //在Fp椭圆对应系数的曲线下 随机生成一对公私钥 82 | NSDictionary *keyPair = [O2SSM2Cipher EC_Fp_SM2_256V1].generateKeyPairHex; 83 | NSLog(@"publicKey:%@",keyPair[@"publicKey"]); 84 | NSLog(@"privateKey:%@",keyPair[@"privateKey"]); 85 | ``` 86 | 87 | **sm3 HASH摘要** 88 | 89 | ``` 90 | NSString *sourceStr = @"中文"; 91 | NSData *data = [O2SSMxHelper sm3DoHashWithString:sourceStr]; 92 | NSLog(@"SM3 HASH:%@",[O2SSMxUtils hexStringByData:data]); 93 | ``` 94 | 95 | #### 三、注意事项 96 | 1、提供公钥der文件,内部包含公钥值、椭圆曲线及椭圆曲线相关系数(p,a,b,Gx,Gy,n),可通过[在线工具](https://aks.jd.com/tools/sec/)ASN.1在线解析,**"O2SECCKit"**内部没有ASN.1,请自行解析。 97 | 98 | **公钥文件或Base64:** 99 | 100 | ![](README_FILE/sm2_publickey_min.jpg) 101 | 102 | **私钥文件或Base64:** 103 | > 私钥文件中,可能含有公钥 104 | 105 | ![](README_FILE/sm2_privatekey_min.jpg) 106 | 107 | 108 | #### 四、相关备注和总结 109 | 110 | **sm2 公式:** 111 | 112 | ``` 113 | //无论RSA还是SM2,加解密问题,一切都归于数学问题,涉及“大数“运算,字符串可以用“大数”表示,加解密无非就是 ”大数“变成另一个”大数“ 114 | //一个字符串NSString(如"hello world") 转成 NSData,NSData转换成 16进制的字符串(如"68656C6C6F20776F726C64"),这个l6进制字符串就是一个16进制”大数“ 115 | //大数运算 如:"C8" + "A3" = "016B" 116 | // 117 | //SM2 加解密 118 | //备注:椭圆曲线坐标点运算 详情EC_Fp 119 | //注:这里的坐标点如G点,Q点及椭圆曲线生成的点当作大数处理 如:规定每个点为16进制4位{"00ff","f840"}那么值就是“00fff840”,之后通过位数重新切分成点 120 | //1、选定一条椭圆曲线Ep(a,b) 并取椭圆曲线上一点,作为基点G 121 | //2、选择一个大数k作为私钥,并生成公钥 Q = kG 122 | //3、Ep(a,b)和n、G点、Q点提供给客户端这几个参数经过ASN.1编码生成der即为"公钥" 备注:der不一定明确的含Ep(a,b)和G点的值,Q值一定有,根据内部类型值也可确定椭圆曲线 123 | //4、Ep(a,b)和n、G点、k值提供给服务端这几个参数经过ASN.1编码生成der即为"私钥" 备注:der不一定明确的含Ep(a,b)和G点及Q点的值,k值一定有,根据内部类型值也可确定椭圆曲线,"私钥"信息包含“公钥”,Q = kG 计算得到, 124 | // 一般提供的der文件密钥可通过https://aks.jd.com/tools/sec/ ASN.1在线解析工具获取相关的p、a、b、G点、n的值以及Q点或k 125 | //5、加解密原理解释例子: 126 | // M为明文,r是随机一个“大数” C1 = rG,C1为随机点,Q为公钥点,C2 = M⊕rQ (实际为 C2 = M⊕KDF(rQ,ml) 看:♦️), r∈[1,n-1] 127 | // 公钥加密:密文C是C1,C2,C3组合的字节流 C = C1+C2+C3, 128 | // 私钥解码:求M ∵ 已知 C1 = rG,C2 = M⊕rQ,Q = kG, C1 = rG 129 | // ∵ 椭圆曲线特性(Fp域内运算满足交换律、结合律、分配律) rQ = r(kG) = k(rG) = kC1 130 | // ∴ 结果:rQ = kC1 131 | // ∵ M = (M⊕rQ)⊕rQ = (C2)⊕kC1, 一般是使用⊕(异或)处理,原因(a⊕b)⊕b == a 132 | // ∴ 结果:M = (C2)⊕kC1(实际为M = C2⊕KDF(kC1,ml)看:♦️),C2(密文C获取 已知),k(服务器私钥 已知)和C1(密文C获取 已知) 133 | // 134 | // ♦️注意:上方 C2 = M⊕rQ 改成 C2 = M⊕KDF(rQ,ml),M = (C2)⊕kC1 改成 M = C2⊕KDF(kC1,ml) ,C2.len == M.len【别名ml】 == KDF(rQ,ml).len == KDF(kC1,ml).len,长度值相等 135 | // 上方 C1 = rG 一般情况下前面还要加上0x04表示未压缩形式(C1 = 0x04+rG) 136 | // C3 = HASH_SM3(rQx+M+rQy) 137 | // 138 | // |--- 64 byte C1 ---||--- M(len) C2---||------ 32 byte C3 ------| 139 | // | || || | 140 | // |----x1----|----y1----|| || | 141 | // | | || || | 142 | // C = F0...................0802..............C9A1......................B8 143 | // 注意C1的长度与坐标点长度相等 144 | // 145 | // 以上"+"基本是字符串拼接 146 | 147 | //假设在加密过程中,有一个第三者H,H只能知道椭圆曲线 Ep(a,b)、公钥Q、基点G、密文C,而通过公钥Q、基点G求私钥k或者通过密文点C、基点P求随机数r都是非常困难的,因此得以保证数据传输的安全 148 | // 149 | //下面的加解密使用的是Fp上的椭圆曲线(p是大于3的素数,y^2 = x^3 + ax + b, a,b∈Fp,且(4a^3 + 27b^2) mod p = 0),非F2m上的椭圆曲线(y^2 + xy = x^3 + ax^2 + b, a,b∈F2m,且b=0)。 150 | // 151 | // asn.1解码 03 42 00 152 | // 03是bit string的tag 153 | // 42是bit string的length 154 | // 00是bit string的unused bit 155 | // 04说明是没有压缩的 156 | // 剩下为公钥point值 157 | ``` 158 | **Fp(素数域)上的椭圆曲线 y^2 = x^3 + ax + b :** 159 | 160 | ``` 161 | //Fp(素数域)上的椭圆曲线 y^2 = x^3 + ax + b 162 | //椭圆曲线E (Fp )上的点按照下面的加法运算规则,构成一个交换群: 163 | //a) O+O=O; 164 | //b) ∀P = (x,y) ∈ E(Fp)\{O},P+O = O+P = P; 165 | //c) ∀P = (x,y) ∈ E(Fp)\{O},P的逆元素−P = (x,−y),P+(−P) = O; 166 | //d) 两个非互逆的不同点相加的规则: 167 | // 设P1 = (x1,y1) ∈ E(Fp)\{O},P2 = (x2,y2) ∈ E(Fp)\{O},且x1 ≠ x2, 168 | // 设P3 = (x3,y3)=P1+P2,则 169 | // x3 =λ^2 − x1 − x2, 170 | // y3 =λ(x1 − x3) − y1 171 | // 其中 172 | // y2 − y1 173 | // λ = ——————— ; 174 | // x2 − x1 175 | //e) 倍点规则: 176 | // 设P1 = (x1,y1) ∈ E(Fp)\{O},且y1 ≠ 0,P3 = (x3,y3) = P1 +P1,则 177 | // x3 =λ^2−2x1, 178 | // y3 =λ(x1−x3)−y1, 179 | // 其中 180 | // 3x1^2 + a 181 | // λ = ————————— 。 182 | // 2y1 183 | 184 | ``` 185 | 186 | **点压缩 (y^2) mod n = a mod n 需要使用到模平方根运算:** 187 | 188 | >所谓点压缩就是,已知椭圆曲线及系数、点x值,求y。 189 | >(y^2) mod p = (x^3 + ax + b) mod p,其中p、x、a、b求y 190 | 191 | ``` 192 | // 参考的轮子:https://blog.csdn.net/qq_41746268/article/details/98730749 193 | //对于给定的奇质数p,和正整数x,存在y满足1≤y≤p−1,且x≡y^2(mod p)x,则称y为x的模平方根 194 | //对于正整数m,若同余式,若同余式x^2≡a(mod m)有解,则称a为模m的平方剩余,否则称为模m平方非剩余。 195 | //是否存在模平方根 196 | //根据欧拉判别条件: 197 | //设p是奇质数,对于x^2≡a(mod p) 198 | //a是模p的平方剩余的充要条件是(a^((p−1)/2)) % p = 1 199 | //a是模p的平方非剩余的充要条件是(a^((p−1)/2)) % p = -1 200 | //给定a,na,na,n(n是质数),求x^2≡a(mod n)的最小整数解x 201 | //代码复杂度O(log2(n)) 202 | ``` 203 | 204 | #### 五、参考文献 205 | 1、[https://aks.jd.com/tools/sec/](https://aks.jd.com/tools/sec/),在线加密工具及ASN.1解析 206 | 2、[C大数运算](https://github.com/libtom/libtommath) 207 | 3、[nodejs miniprogram-sm-crypto](https://github.com/wechat-miniprogram/sm-crypto) 基本参考此项目转成OC 208 | 4、[收集的github下的关于椭圆曲线文档](https://github.com/o2space/O2SECCKit/参考文献) 209 | 5、SM3 C实现的HASH摘要,链接地址未找到,用了别人造的轮子。 210 | 6、[点压缩 涉及模平方根](https://blog.csdn.net/qq_41746268/article/details/98730749) -------------------------------------------------------------------------------- /README_FILE/sm2_privatekey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/README_FILE/sm2_privatekey.jpg -------------------------------------------------------------------------------- /README_FILE/sm2_privatekey_min.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/README_FILE/sm2_privatekey_min.jpg -------------------------------------------------------------------------------- /README_FILE/sm2_publickey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/README_FILE/sm2_publickey.jpg -------------------------------------------------------------------------------- /README_FILE/sm2_publickey_min.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/README_FILE/sm2_publickey_min.jpg -------------------------------------------------------------------------------- /参考文献/SM2公钥密码加密.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/参考文献/SM2公钥密码加密.pdf -------------------------------------------------------------------------------- /参考文献/SM2椭圆曲线公钥密码算法推荐曲线参数.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/参考文献/SM2椭圆曲线公钥密码算法推荐曲线参数.pdf -------------------------------------------------------------------------------- /参考文献/sm2官网pdf里面包含4部分每部分有单独目录.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/参考文献/sm2官网pdf里面包含4部分每部分有单独目录.pdf -------------------------------------------------------------------------------- /参考文献/二元域椭圆曲线加密算法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2space/O2SECCKit/8c2e62dc284b34b6b8405eb5aa064addf5527d50/参考文献/二元域椭圆曲线加密算法.pdf --------------------------------------------------------------------------------