ECC英文全称"Ellipse Curve Cryptography",与传统的基于大质数因子分解困难性的加密方法不同,ECC通过椭圆曲线方程式的性质产生密钥
ECC164位的密钥产生一个安全级,相当于RSA 1024位密钥提供的保密强度,而且计算量较小,处理速度更快,存储空间和传输带宽占用较少。目前我国居民二代身份证正在使用 256 位的椭圆曲线密码,虚拟货币比特币也选择ECC作为加密算法。
ECC被广泛认为是在给定密钥长度的情况下,最强大的非对称算法,因此在对带宽要求十分紧的连接中会十分有用。
安全性高
有研究表示160位的椭圆密钥与1024位的RSA密钥安全性相同。
处理速度快
在私钥的加密解密速度上,ecc算法比RSA、DSA速度更快。
存储空间占用小。
带宽要求低。
以上为ECC椭圆曲线算法需要了解的基本知识,摘自强大的百科度娘。
关于ECC,苹果支持以下算法:
PKG:
curves P-224, P-256, P-384, P-521PKV:
curves P-224, P-256, P-384, P-521Signature Generation:
curves P-224, P-256, P-384, P-521using (SHA-224, SHA-256, SHA384, SHA512)Signature Verification:curves P-224, P-256, P-384, P-521using (SHA-1, SHA-224, SHA-256, SHA384, SHA512)
采用的都是NIST标准和规范。但是苹果官方API仅为开发者提供了椭圆曲线P-256的256位EC密钥。由于苹果SEP硬件提供的保护机制,私钥会直接以keychain的形式截留在SEP中,不能提取,也不能从外部导入,只能通过引用使用。
椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟,下面是关于ECDSA的API调用。
1、创建ECC椭圆曲线的keychain属性,属性设置具体可以根据自己需要,获取ECC私钥。
sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
// kSecAccessControlTouchIDAny |
kSecAccessControlPrivateKeyUsage, &error);
// Create parameters dictionary for key generation.
NSDictionary *parameters = @{
(id)kSecAttrTokenID: (id)kSecAttrTokenIDSecureEnclave,
(id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom,
(id)kSecAttrKeySizeInBits: @256,
(id)kSecAttrLabel: @"my-se-key",
(id)kSecPrivateKeyAttrs: @{
(id)kSecAttrAccessControl: (__bridge_transfer id)sacObject,
(id)kSecAttrIsPermanent: @YES,
}
};
NSError *gen_error = nil;
//根据参数生成私钥
id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((__bridge CFDictionaryRef)parameters, (void *)&gen_error));
2.使用私钥提取公钥,并用于签名。
//根据keychain的属性查找ECC私钥,并获取私钥引用。
NSDictionary *params = @{
(id)kSecClass: (id)kSecClassKey, (id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeySizeInBits: @256, (id)kSecAttrLabel: @"my-se-key", (id)kSecReturnRef: @YES, (id)kSecUseOperationPrompt: @"Authenticate to sign data" };
SecKeyRef privateKey;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)params, (CFTypeRef *)&privateKey);
3.签名
NSError *error;
NSData *dataToSign = [@"我是签名内容" dataUsingEncoding:NSUTF8StringEncoding];
NSData *signature = CFBridgingRelease(SecKeyCreateSignature(privateKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (CFDataRef)dataToSign, (void *)&error));
对于kSecKeyAlgorithmECDSASignatureMessageX962SHA256签名算法,官方还给了:SHA1、SHA224、SHA384、SHA512用于EC密钥摘要。可以自己需求选择签名对应的摘要算法。API的名字也很明确的给了这里执行的标准规范为X9.62。
4.验签
//提取公钥,进行验签,验签选择的算法必须与签名时的算法一致。
id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
Boolean verified = SecKeyVerifySignature((SecKeyRef)publicKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (CFDataRef)dataToSign, (CFDataRef)signature, (void *)&error); if (verified == 1) { message = [NSString stringWithFormat:@"signature:%@ verified:%@ error:%@", signature, @"验签成功", error]; }else{ message = [NSString stringWithFormat:@"signature:%@ verified:%@ error:%@", signature, @"验签失败", error]; }ECIES
校验密钥是否和算法是否匹配,只有都符合条件了才能用于加密。
SecKeyAlgorithm algorithm = kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM;
BOOL canEncrypt = SecKeyIsAlgorithmSupported((SecKeyRef)publicKey, kSecKeyOperationTypeEncrypt, algorithm);加密
CFErrorRef error = NULL;
cipherText = (NSData*)CFBridgingRelease( // ARC takes ownership
SecKeyCreateEncryptedData(publicKey,
algorithm,
(__bridge CFDataRef)encryptionData,
&error));
encryptionData为要加密的数据,这里提示一下:
As an additional check before encrypting, because asymmetric encryption restricts the length of the data that you can encrypt, verify that the data is short enough. For this particular algorithm, the plain text data must be 130 bytes smaller than the key’s block size, as reported by SecKeyGetBlockSize
. You therefore further condition the proceedings on a length test:
NSData* plainText = <
canEncrypt &= ([plainText length] < (SecKeyGetBlockSize(publicKey)-130));
官方API描述,明文数据要比密钥块小130个字节。
解密
CFErrorRef error = NULL;
clearText = (NSData*)CFBridgingRelease( // ARC takes ownership
SecKeyCreateDecryptedData(private,
algorithm,
(__bridge CFDataRef)cipherText,
&error));
---------------------------------结束了,无话可说-------------------------------------