GMObjC
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。
- iOS 9.0或更高版本
- GMOpenSSL.framework(openssl.framework)
- 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 update
和 brew 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时的注意事项
- 工具依赖于OpenSSL。您可以通过
pod GMOpenSSL
安装OpenSSL,或者下载 openssl.framework,找到GMOpenSSL/openssl.framework
,并将其拖入项目中。 - 如果您需要自编译OpenSSL,GMOpenSSL项目目录中有
OpenSSL_BUILD
文件夹,在终端cd切换到此目录,首先执行./build -libssl.sh
命令编译并生成.a文件,等待后,执行./create-openssl-framework.sh
命令将其打包为框架,然后在目录中会出现openssl.framework。 - 打包的静态库没有暴露国家秘密头文件。打开下载的源代码,并将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
注意
- OpenSSL中使用的公钥以04开头,表示未压缩的公钥格式。后台返回的公钥可能不带04,需要进行手动拼接。
- 后台返回的解密结果可能为不带标准编码的原始密文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];
注意
- 用户ID可以传入空值。当传入空值时,使用OpenSSL默认用户ID。OpenSSL中的默认用户定义是
#define SM2_DEFAULT_USERID "1234567812345678"
。客户端和服务器用户ID必须一致。 - 在客户端与后台交互过程中,假设后台签名,客户端验证签名,后台返回的签名是DER编码格式,签名需要先进行DER解码,然后进行验证。同样地,如果客户端签名,后台验证签名,根据后台是否要求RS拼接格式签名或DER格式进行编码和解码。
ECDH密钥协商
OpenSSL中的ECDH_compute_key()
函数执行椭圆曲线Diffie-Hellman密钥协商,当双方以明文形式传输时可以协商相同的密钥。
协商过程
- 客户端随机生成一对公钥和私钥clientPublicKey、clientPrivateKey;
- 服务器随机生成一对公钥和私钥serverPublicKey、serverPrivateKey;
- 双方通过网络请求或其他方法交换公钥clientPublicKey和serverPublicKey,私钥由各自保管;
- 客户端计算
clientKey = ECDH_compute_key(clientPrivateKey, serverPublicKey)
; - 服务器端计算
serverKey = ECDH_compute_key(serverPrivateKey, clientPublicKey)
; - 双方计算的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曲线
- GM/T 0003-2012标准推荐的参数sm2p256v1(NID_sm2);
- 如果需要使用其他曲线,请调用
[GMSm2Utils setEllipticCurveType:*]
并传入整数值; - 如何找到所需的曲线,常用的三个曲线sm2p256v1、secp256k1、secp256r1在GMSm2Utils头文件枚举中列出;
- 如果是其他曲线,可以在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