GMObjC 3.3.7

GMObjC 3.3.7

lifei维护。



GMObjC 3.3.7

  • 作者
  • lifei

GMObjC

Build Status Pod Version Pod Platform Pod License Carthage compatible SwiftPM compatible codecov

简体中文Readme文档

OpenSSL 1.1.1及以上版本增加了对中文SM2/SM3/SM4加密算法的支持,基于OpenSSL,使用SM2非对称加密、SM2签名验证、ECDH密钥交换、SM3摘要算法和SM4对称加密进行OC封装。

入门

在终端中运行以下命令

git clone https://github.com/muzipiao/GMObjC.git

cd GMObjC

pod install

open GMObjC.xcworkspace

要求

依赖于OpenSSL 1.1.1或更高版本,已打包为Framework,并上传到cocoapods,可以直接拖入项目中安装,或使用cocoapods配置Podfile文件pod GMOpenSSL安装;并导入系统框架Security.framework。

安装

在项目中使用GMObjC的方法如下

  • 使用CocoaPods
  • 使用Carthage
  • 编译为Framework/XCFramework
  • 使用Swift Package Manager
  • 拖入项目源代码

CocoaPods

CocoaPods 是最简单、最便捷的集成方式。编辑 Podfile,添加

pod'GMObjC'

然后执行 pod install。GMObjC 依赖于 OpenSSL 1.1.1 及其以上版本。CocoaPods 不支持同一静态库的不同版本。如果您遇到与第三方库(如百度 MapKit 依赖于较低版本的 OpenSSL 静态库)的 OpenSSL 冲突,将发生依赖冲突。

OpenSSL 冲突的常见解决方案

方法 1:使用 OpenSSL 升级第三方库至 1.1.1 或更高版。GMObjC 直接共享此 OpenSSL 库。您无需为 GMObjC 分别添加 OpenSSL 依赖库,只需手动集成 GMObjC;

方法 2:将 GMObjC 编译成动态库可以解决此类冲突。您可以通过 Carthage 自动将 GMObjC 编译成动态库。请查看下一步的具体操作。

Carthage

Carthage 可以自动将第三方框架编译成动态框架(Dynamic framework)。如果尚未安装,则执行 brew updatebrew install carthage 进行安装,然后创建一个名为 Cartfile(类似 Podfile)的文件,编辑并添加编译后的第三方库的名称,例如 github "muzipiao/GMObjC",然后执行 carthage update --use-xcframeworks

# Install carthage
brew update && brew install carthage
# Create Cartfile file and write it to github "muzipiao/GMObjC"
touch Cartfile && echo'github "muzipiao/GMObjC"' >> Cartfile
# Pull and compile into a dynamic library, and you can find GMObjC.framework in Carthage/Build/iOS/ under the current command directory
carthage update --use-xcframeworks

编译成功后,打开 Carthage 查看生成的文件目录。Carthage/Build/iOS/GMObjC.xcframework 是编译后的动态库。只需将动态库拖入项目即可。

注意:GMObjC.xcframework 是动态库,您需要选择 Embed & Sign 模式,并且无需单独导入 openssl.framework 库。如果 Carthage 编译失败,请下载项目源代码,在 GMObjCFramework 文件夹中打开项目文件,并执行 command + b 手动编译。

Swift Package Manager

GMObjC 从版本 3.3.0 开始支持 SwiftPM。要使用 SwiftPM,您应使用 Xcode 11 打开您的项目。单击 File -> Swift Packages -> Add Package Dependency,输入 GMObjC 仓库的 URL。或者您可以使用 GitHub 账户登录 Xcode,然后只需键入 GMObjC 进行搜索。

选择包之后,您可以选择依赖类型(标记版本、分支或提交)。然后 Xcode 会为您设置所有内容。

如果您是框架作者并使用GMObjC作为依赖项,请更新您的Package.swift文件

dependencies: [
    .package(url: "https://github.com/muzipiao/GMObjC.git", from: "3.3.0")
],

直接集成

从Git下载最新代码,找到与README相同的目录下的GMObjC文件夹,将GMObjC文件夹拖入项目,并在需要SM2、SM4加密解密和签名验证的地方导入头文件GMObjC.h。签名、计算SM3摘要等。

集成OpenSSL时的注意事项

  1. 工具依赖于OpenSSL。您可以通过pod GMOpenSSL安装OpenSSL,或者下载 openssl.framework,找到GMOpenSSL/openssl.framework,并将其拖入项目中。
  2. 如果您需要自编译OpenSSL,GMOpenSSL项目目录中有OpenSSL_BUILD文件夹,在终端cd切换到此目录,首先执行./build -libssl.sh命令编译并生成.a文件,等待后,执行./create-openssl-framework.sh命令将其打包为框架,然后在目录中会出现openssl.framework。
  3. 打包的静态库没有暴露国家秘密头文件。打开下载的源代码,并将crypto/include/internal路径下的sm2.h、sm3.h和sm4.h拖到openssl.framework/Headers文件中,剪切即可。

集成过程中可能遇到的Xcode编译错误

错误1:

Building for iOS, but the linked and embedded framework 'GMObjC.framework' was built for iOS + iOS Simulator.

解决方案是选择项目路径Build Settings-Build Options-Validate Workspace,将其更改为YES/NO,并修改一次。

错误2:

building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

解决方案是选择项目路径Build Settings-Architectures-Excluded Architecture,选择Any iOS Simulator SDK以添加arm64,请参阅Stackoverflow解决方案

如何使用

SM2加密解密

SM2加密和解密非常简单,将待加密的明文和公钥进行加密,然后将接收到的密文和私钥进行解密。代码

// public key
NSString *pubKey = @"0408E3FFF9505BCFAF9307E665E9229F4E1B3936437A870407EA3D97886BAFBC9"
                    "C624537215DE9507BC0E2DD276CF74695C99DF42424F28E9004CDE4678F63D698";
// private key
NSString *prikey = @"90F3A42B9FE24AB196305FD92EC82E647616C3A3694441FB3422E7838E24DEAE";

// plaintext
NSString *plaintext = @"123456"; // ordinary plaintext
NSString *plainHex = @"313233343536"; // Hex format character plain text (The Hex code of 123456 is 313233343536)
NSData *plainData = [NSData dataWithBytes:"123456" length:6]; // NSData format plain text

// sm2 encryption
NSString *enResult1 = [GMSm2Utils encryptText:plaintext publicKey:pubKey]; // encrypt ordinary string
NSString *enResult2 = [GMSm2Utils encryptHex:plainHex publicKey:pubKey]; // Encrypted Hex encoding format string
NSData *enResult3 = [GMSm2Utils encryptData:plainData publicKey:pubKey]; // Encrypt NSData type data

// sm2 decrypt
NSString *deResult1 = [GMSm2Utils decryptToText:enResult1 privateKey:priKey]; // Decrypt to plain text of ordinary string
NSString *deResult2 = [GMSm2Utils decryptToHex:enResult2 privateKey:priKey]; // Decrypt to plain text in Hex format
NSData *deResult3 = [GMSm2Utils decryptToData:enResult3 privateKey:priKey]; // Decrypt to plain text in NSData format

注意

  1. OpenSSL中使用的公钥以04开头,表示未压缩的公钥格式。后台返回的公钥可能不带04,需要进行手动拼接。
  2. 后台返回的解密结果可能为不带标准编码的原始密文C1C3C2格式,而OpenSSL的加密和解密要求ASN1编码格式,因此在与后台交互的过程中可能需要进行ASN1编码和解码。

SM2签名验证

SM2私钥签名,公钥验证,防篡改或身份验证。签名时传入明文、私钥和用户ID;签名时传入明文、签名、公钥和用户ID,代码

// public key
NSString *pubKey = @"0408E3FFF9505BCFAF9307E665E9229F4E1B3936437A870407EA3D97886BAFBC9"
                    "C624537215DE9507BC0E2DD276CF74695C99DF42424F28E9004CDE4678F63D698";
// private key
NSString *prikey = @"90F3A42B9FE24AB196305FD92EC82E647616C3A3694441FB3422E7838E24DEAE";

// plaintext
NSString *plaintext = @"123456"; // ordinary plaintext
NSString *plainHex = @"313233343536"; // Hex format character plain text (The Hex code of 123456 is 313233343536)
NSData *plainData = [NSData dataWithBytes:"123456" length:6]; // NSData format plain text

// When userID is passed in nil or empty, the default is 1234567812345678; when it is not empty, the signature and verification need the same ID
NSString *userID = @"[email protected]"; // userID of ordinary string
NSString *userHex = [GMUtils stringToHex:userID]; // userID in Hex format
NSData *userData = [userID dataUsingEncoding:NSUTF8StringEncoding]; // userID in NSData format

// The signature result is a 128-byte Hex format string spliced ​​by RS, the first 64 bytes are R, and the last 64 bytes are S
NSString *signStr1 = [GMSm2Utils signText:plaintext privateKey:priKey userID:userID];
NSString *signStr2 = [GMSm2Utils signHex:plainHex privateKey:priKey userHex:userHex];
NSString *signStr3 = [GMSm2Utils signData:plainData priKey:priKey userData:userData];

// Verify the signature, YES means the verification passed
BOOL isOK1 = [GMSm2Utils verifyText:plaintext signRS:signStr1 publicKey:pubKey userID:userID];
BOOL isOK2 = [GMSm2Utils verifyHex:plainHex signRS:signStr2 publicKey:pubKey userHex:userHex];
BOOL isOK3 = [GMSm2Utils verifyData:plainData signRS:signStr3 pubKey:pubKey userData:userData];

// Encoded in Der format, Der encoding and decoding should be the same as the original value
NSString *derSign1 = [GMSm2Utils derEncode:signStr1];
NSString *derSign2 = [GMSm2Utils derEncode:signStr2];
NSString *derSign3 = [GMSm2Utils derEncode:signStr3];

// Decode into RS string format, RS spliced ​​128-byte Hex format string, the first 64 bytes are R, the last 64 bytes are S
NSString *rs1 = [GMSm2Utils derDecode:derSign1];
NSString *rs2 = [GMSm2Utils derDecode:derSign2];
NSString *rs3 = [GMSm2Utils derDecode:derSign3];

注意

  1. 用户ID可以传入空值。当传入空值时,使用OpenSSL默认用户ID。OpenSSL中的默认用户定义是#define SM2_DEFAULT_USERID "1234567812345678"。客户端和服务器用户ID必须一致。
  2. 在客户端与后台交互过程中,假设后台签名,客户端验证签名,后台返回的签名是DER编码格式,签名需要先进行DER解码,然后进行验证。同样地,如果客户端签名,后台验证签名,根据后台是否要求RS拼接格式签名或DER格式进行编码和解码。

ECDH密钥协商

OpenSSL中的ECDH_compute_key()函数执行椭圆曲线Diffie-Hellman密钥协商,当双方以明文形式传输时可以协商相同的密钥。

协商过程

  1. 客户端随机生成一对公钥和私钥clientPublicKey、clientPrivateKey;
  2. 服务器随机生成一对公钥和私钥serverPublicKey、serverPrivateKey;
  3. 双方通过网络请求或其他方法交换公钥clientPublicKey和serverPublicKey,私钥由各自保管;
  4. 客户端计算 clientKey = ECDH_compute_key(clientPrivateKey, serverPublicKey)
  5. 服务器端计算 serverKey = ECDH_compute_key(serverPrivateKey, clientPublicKey)
  6. 双方计算的clientKey和serverKey应相等,这个密钥可以用作对称加密的密钥。
// The client generates a pair of public and private keys
NSArray *clientKey = [GMSm2Utils createKeyPair];
NSString *cPubKey = clientKey[0];
NSString *cPriKey = clientKey[1];

// The server generates a pair of public and private keys
NSArray *serverKey = [GMSm2Utils createKeyPair];
NSString *sPubKey = serverKey[0];
NSString *sPriKey = serverKey[1];

// The client obtains the public key sPubKey from the server, and the client negotiates a 32-byte symmetric key clientECDH, which is 64 bytes after being converted to Hex
NSString *clientECDH = [GMSm2Utils computeECDH:sPubKey privateKey:cPriKey];
// The client sends the public key cPubKey to the server, and the server negotiates a 32-byte symmetric key serverECDH, which is 64 bytes after being converted to Hex
NSString *serverECDH = [GMSm2Utils computeECDH:cPubKey privateKey:sPriKey];

// In the case of all plaintext transmission, the client and the server negotiate an equal symmetric key, clientECDH==serverECDH is established
if ([clientECDH isEqualToString:serverECDH]) {
    NSLog(@"ECDH key negotiation is successful, the negotiated symmetric key is:\n%@", clientECDH);
}else{
    NSLog(@"ECDH key negotiation failed");
}

SM2密钥文件读写(PEM/DER)

SM2的公钥和私钥格式可以是PEM或DER格式,可以用GMSm2Bio进行处理。

NSString *filePath = @"PEM or DER file address";
// Read SM2 public and private key from PEM file
NSString *pubPemKey = [GMSm2Bio readPublicKeyFromPemFile:filePath];
NSString *priPemKey = [GMSm2Bio readPrivateKeyFromPemFile:filePath];
// Read SM2 public and private key from DER file
NSString *pubDerKey = [GMSm2Bio readPublicKeyFromDerFile:filePath];
NSString *priDerKey = [GMSm2Bio readPrivateKeyFromDerFile:filePath];

NSString *savePath = @"Save SM2 public or private keys to the sandbox of the PEM/DER file";
// Save the public key string starting with 04 as a PEM or DER file, and return YES if the save is successful, otherwise NO
BOOL success1 = [GMSm2Bio savePublicKeyToPemFile:pubKey filePath:pubPemPath];
BOOL success2 = [GMSm2Bio savePublicKeyToDerFile:pubKey filePath:pubDerPath];
// Save the private key string as a PEM or DER file, return YES if saved successfully, otherwise NO
BOOL success3 = [GMSm2Bio savePrivateKeyToPemFile:priKey filePath:priPemPath];
BOOL success4 = [GMSm2Bio savePrivateKeyToDerFile:priKey filePath:priDerPath];

// Create a PEM or DER format key pair file, the array element 0 is the address of the public key file, and element 1 is the address of the private key file
NSArray<NSString *> *derFilesArray = [GMSm2Bio createDerKeyPairFiles];
NSArray<NSString *> *pemFilesArray = [GMSm2Bio createPemKeyPairFiles];

SM4加密和解密

SM4加密和解密非常简单,加密待加密的字符串和密钥,解密待解密密文和密钥。

  • ECB电子密码本模式,密文被分成等长的块(不足部分以空填充),逐块加密。
  • CBC密文分组链接模式,将前一组的密文和当前组的明文进行异或运算后再加密。
NSString *sm4Key = @"EA4EBDC1DCEAEC733FFD358BA15E8DCD"; // 32-byte Hex encoding format string key
NSString *ivec = @"1AFE5CC82D2DE304343FED0AF5FDE7FA"; // 32-byte initialization vector, required for CBC encryption mode

// plaintext
NSString *plaintext = @"123456"; // ordinary plaintext
NSData *plainData = [NSData dataWithBytes:"123456" length:6]; // NSData format plain text

// ECB encryption mode
NSString *ecbCipertext = [GMSm4Utils ecbEncryptText:plaintext key:sm4Key]; // Encrypt plain text of ordinary string
NSData *ecbCipherData = [GMSm4Utils ecbEncryptData:plainData key:sm4Key]; // Encrypt NSData type plaintext
// ECB decryption mode
NSString *ecbPlaintext = [GMSm4Utils ecbDecryptText:ecbCipertext key:sm4Key];
NSData *ecbDecryptData = [GMSm4Utils ecbDecryptData:ecbCipherData key:sm4Key];

// CBC encryption mode
NSString *cbcCipertext = [GMSm4Utils cbcEncryptText:plaintext key:sm4Key IV:ivec];
NSData *cbcCipherData = [GMSm4Utils cbcEncryptData:plainData key:sm4Key IV:ivec];
// CBC decryption mode
NSString *cbcPlaintext = [GMSm4Utils cbcDecryptText:cbcCipertext key:sm4Key IV:ivec];
NSData *cbcDecryptData = [GMSm4Utils cbcDecryptData:cbcCipherData key:sm4Key IV:ivec];

SM3摘要

类似于md5、sha1,SM3摘要算法可以对文本文件进行摘要计算,摘要长度是一个64字节的十六进制编码字符串。

// Original
NSString *plaintext = @"123456"; // normal original text
NSData *plainData = [NSData dataWithBytes:"123456" length:6]; // NSData format original text

// String summary
NSString *textDigest = [GMSm3Utils hashWithString:plaintext];
// Summary of NSData
NSString *dataDigest = [GMSm3Utils hashWithData:plainData];

HMAC计算摘要

HMAC算法计算摘要,计算出的摘要长度与原始摘要算法的长度相同。

NSString *plaintext = @"123456"; // plaintext
NSString *randomKey = @"qwertyuiop1234567890"; // Key passed from the server
// HMAC uses SM3 digest algorithm
NSString *hmacSM3 = [GMSm3Utils hmacWithSm3:randomKey plaintext:plaintext];
// HMAC uses MD5 digest algorithm
NSString *hmacMD5 = [GMSm3Utils hmac:GMHashType_MD5 key:randomKey plaintext:plaintext];
// HMAC uses SHA1 digest algorithm
NSString *hmacSHA1 = [GMSm3Utils hmac:GMHashType_SHA1 key:randomKey plaintext:plaintext];
// HMAC uses SHA224 digest algorithm
NSString *hmacSHA224 = [GMSm3Utils hmac:GMHashType_SHA224 key:randomKey plaintext:plaintext];
// HMAC uses SHA256 digest algorithm
NSString *hmacSHA256 = [GMSm3Utils hmac:GMHashType_SHA256 key:randomKey plaintext:plaintext];
// HMAC uses SHA384 digest algorithm
NSString *hmacSHA384 = [GMSm3Utils hmac:GMHashType_SHA384 key:randomKey plaintext:plaintext];
// HMAC uses SHA512 digest algorithm
NSString *hmacSHA512 = [GMSm3Utils hmac:GMHashType_SHA512 key:randomKey plaintext:plaintext];

ASN1编码和解码

OpenSSL将SM2加密结果编码为ASN1格式。在解密过程中,密文编码格式也必须是ASN1格式。解码后,以c1c3c2顺序插回原始密文。

// public key
NSString *pubKey = @"0408E3FFF9505BCFAF9307E665E9229F4E1B3936437A870407EA3D97886BAFBC9"
                    "C624537215DE9507BC0E2DD276CF74695C99DF42424F28E9004CDE4678F63D698";
// private key
NSString *prikey = @"90F3A42B9FE24AB196305FD92EC82E647616C3A3694441FB3422E7838E24DEAE";

// plaintext
NSString *plaintext = @"123456"; // ordinary plaintext
NSString *plainHex = @"313233343536"; // Hex format character plain text (The Hex code of 123456 is 313233343536)
NSData *plainData = [NSData dataWithBytes:"123456" length:6]; // NSData format plain text

// sm2 encryption result, ASN1 encoded cipher text
NSString *enResult1 = [GMSm2Utils encryptText:plaintext publicKey:pubKey]; // encrypt ordinary string
NSString *enResult2 = [GMSm2Utils encryptHex:plainHex publicKey:pubKey]; // Encrypted Hex encoding format string
NSData *enResult3 = [GMSm2Utils encryptData:plainData publicKey:pubKey]; // Encrypt NSData type data

// ASN1 decoding, decode the ciphertext in ASN1 encoding format string, array or NSData
NSString *c1c3c2Result1 = [GMSm2Utils asn1DecodeToC1C3C2:enResult1]; // Decode to c1c3c2 string
NSArray<NSString *> *c1c3c2Result2 = [GMSm2Utils asn1DecodeToC1C3C2Array:enResult2]; // decoded as @[c1,c3,c2]
NSData *c1c3c2Result3 = [GMSm2Utils asn1DecodeToC1C3C2Data:enResult3]; // decoded as data spliced ​​by c1c3c2

// ASN1 encoding, re-encoding the decoded c1c3c2 ciphertext into ASN1 format, which should be exactly the same as enResult1, enResult2, and enResult3
NSString *asn1Result1 = [GMSm2Utils asn1EncodeWithC1C3C2:c1c3c2Result1];
NSString *asn1Result2 = [GMSm2Utils asn1EncodeWithC1C3C2Array:c1c3c2Result2];
NSData *asn1Result3 = [GMSm2Utils asn1EncodeWithC1C3C2Data:c1c3c2Result3];

密文格式转换

在ASN1解码密文之后,得到的密文序列为c1c3c2,而其他平台可能需要按照c1c2c3的顺序排列的密文;例如,Java端使用bouncycastle进行SM2加密,密文可能以04开头,并按照c1c2c3排列。

OpenSSL解密需要将密文按照c1c3c2和ASN1编码格式排列。在这两种情况下都需要进行转换。对于由bouncycastle加密的密文,需要将密文格式从c1c2c3改为c1c3c2,然后进行ASN1编码和解密。

一般来说,密文不包含密文格式标识。至于是否包含,可以通过观察或其他平台来确认。常见的标识位于密文开头。

  • 02或03压缩表示
  • 04非压缩表示
  • 06或07混合表示
NSString *ciphertext = @"C1C2C3 Sequential ciphertext";
// Change the ciphertext in c1c2c3 order to c1c3c2 order
NSString *c1c3c2 = [GMSm2Utils convertC1C2C3ToC1C3C2:c1c2c3 hasPrefix:NO];
// ASN1 encoding, encoding the ciphertext in c1c3c2 order into ASN1 format
NSString *asn1Result = [GMSm2Utils asn1EncodeWithC1C3C2:c1c3c2];
// Decrypt to plain text string
NSString *deResult1 = [GMSm2Utils decryptToText:asn1Result privateKey:priKey]; 
// If necessary, you can change the ciphertext in c1c3c2 order to c1c2c3 order
NSString *c1c2c3 = [GMSm2Utils convertC1C3C2ToC1C2C3:c1c3c2 hasPrefix:NO];

密文分割原则:假设没有ASN1编码的密文是以十六进制编码(十六进制编码)格式,并按照c1c2c3的顺序排列,已知C1长度固定为128字节,C3长度固定为64字节,那么C2长度=密文字符串总长度 - C1长度128 - C3长度,然后分别获取C1、C2和C3字符串,并自由拼接。

生成公钥和私钥

基于SM2推荐曲线(素数域中的256位椭圆曲线),生成一个公钥和私钥。

NSArray *keyPair = [GMSm2Utils createKeyPair];
NSString *pubKey = keyPair[0]; // The public key at the beginning of 04, Hex encoding format
NSString *priKey = keyPair[1]; // Private key, Hex encoding format

SM2曲线

  1. GM/T 0003-2012标准推荐的参数sm2p256v1(NID_sm2);
  2. 如果需要使用其他曲线,请调用[GMSm2Utils setEllipticCurveType:*]并传入整数值;
  3. 如何找到所需的曲线,常用的三个曲线sm2p256v1、secp256k1、secp256r1在GMSm2Utils头文件枚举中列出;
  4. 如果是其他曲线,可以在OpenSSL源代码crypto/ec/ec_curve.c中找到,并输入整数值。

GMCurveType在GMSm2Utils.h文件中对应曲线参数

ECC recommended parameters: sm2p256v1 (corresponding to NID_sm2 in OpenSSL)
p   = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
a   = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC
b   = 28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93
n   = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123
Gx =  32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7
Gy =  BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0

ECC recommended parameters: secp256k1 (corresponding to NID_secp256k1 in OpenSSL)
p   = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
a   = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
b   = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000007
n   = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
Gx =  79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
Gy =  483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8

ECC recommended parameters: secp256r1 (corresponding to NID_X9_62_prime256v1 in OpenSSL)
p   = FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFF
a   = FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFC
b   = 5AC635D8 AA3A93E7 B3EBBD55 769886BC 651D06B0 CC53B0F6 3BCE3C3E 27D2604B
n   = FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551
Gx  = 6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0 F4A13945 D898C296
Gy  = 4FE342E2 FE1A7F9B 8EE7EB4A 7C0F9E16 2BCE3357 6B315ECE CBB64068 37BF51F5

其他

如果您觉得有帮助,请给个Star⭐️GitHub GMObjC上,您的鼓励是我的动力