iOS - ECC椭圆曲线、ECDSA签名验签和ECIES加解密
前言
ECC英文全称"Ellipse Curve Cryptography",与传统的基于大质数因子分解困难性的加密方法不同,ECC通过椭圆曲线方程式的性质产生密钥
ECC164位的密钥产生一个安全级,相当于RSA 1024位密钥提供的保密强度,而且计算量较小,处理速度更快,存储空间和传输带宽占用较少。目前我国居民二代身份证正在使用 256 位的椭圆曲线密码,虚拟货币比特币也选择ECC作为加密算法。
加密
基于这个秘密值,用来对Alice和Bob之间的报文进行加密的实际方法是适应以前的,最初是在其他组中描述使用的离散对数密码系统。这些系统包括:
Diffie-Hellman—ECDH
MQV—ECMQV
ElGamal discrete log cryptosystem—ECElGamal
数字签名算法—ECDSA
对于ECC系统来说,完成运行系统所必须的群操作比同样大小的因数分解系统或模整数离散对数系统要慢。不过,ECC系统的拥护者相信ECDLP问题比DLP或因数分解问题要难的多,并且因此使用ECC能用小的多的密钥长度来提供同等的安全,在这方面来说它确实比例如RSA之类的更快。到目前为止已经公布的结果趋于支持这个结论,不过一些专家表示怀疑。
ECC被广泛认为是在给定密钥长度的情况下,最强大的非对称算法,因此在对带宽要求十分紧的连接中会十分有用。
优点
安全性高
有研究表示160位的椭圆密钥与1024位的RSA密钥安全性相同。
处理速度快
在私钥的加密解密速度上,ecc算法比RSA、DSA速度更快。
存储空间占用小。
带宽要求低。
以上为ECC椭圆曲线算法需要了解的基本知识,摘自强大的百科度娘。
iOS-ECC
关于ECC,苹果支持以下算法:
PKG:
curves P-224, P-256, P-384, P-521
PKV:
curves P-224, P-256, P-384, P-521
Signature Generation:
curves P-224, P-256, P-384, P-521
using (SHA-224, SHA-256, SHA384, SHA512)
Signature Verification:
curves P-224, P-256, P-384, P-521
using (SHA-1, SHA-224, SHA-256, SHA384, SHA512)
采用的都是NIST标准和规范。但是苹果官方API仅为开发者提供了椭圆曲线P-256的256位EC密钥。由于苹果SEP硬件提供的保护机制,私钥会直接以keychain的形式截留在SEP中,不能提取,也不能从外部导入,只能通过引用使用。
ECDSA
椭圆曲线数字签名算法(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, (voidvoid *)&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, (voidvoid *)&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,
https://developer.virgilsecurity.com/docs/sdk-and-tools
https://kjur.github.io/jsrsasign/sample/sample-ecdsa.html
https://forums.developer.apple.com/thread/87758
PUBLIC_KEY = "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESJCvH4lEoGgLof637UGdAYHwFW0GddD/DbVu8yFVTt5Zq+kkftDpQDelSnhmmbr9v+ZsIESINctknP3LTbeLIg==";
PRIVATE_KEY = "MIGNAgEAMBAGByqGSM49AgEGBSuBBAAKBHYwdAIBAQQgi5h75Y80gEeJQQZ6zq7zjT9a11lyLhf9kF/ItIGFDHCgBwYFK4EEAAqhRANCAARIkK8fiUSgaAuh/rftQZ0BgfAVbQZ10P8NtW7zIVVO3lmr6SR+0OlAN6VKeGaZuv2/5mwgRIg1y2Sc/ctNt4si";
区块链中,交易被如何打包进区块
R:https://www.tangshuang.net/4097.html
大部分材料都详细分析了挖矿过程,介绍了区块是如何产生的。然而,区块的产生并不是区块链的最终目的,保存交易信息才是区块链的最终目的。所以,更重要的一点是要理解,交易信息是如何被打包进区块链的。
##输入和输出
一个交易在系统里被输入和输出表示。输入是指这笔交易所要进行转移的币来自之前的哪些输出。输出是指这些币将会被发送给哪些地址。在区块链上记账,不是告诉你一个账号现在有多少钱,而是告诉你这个账号当前得到了哪些输出。比如一个地址xsw0923sdfew2389dsfw它的相关记录里面,有A、B、C三个输出的目标地址是它,那么它实际上的余额就是这三个输出的金额的总和。
但是现在这个地址的用户要转账了,转账过程不是直接从总和数字中取出一部分进行转移,而是分别从A、B、C三个输出中取出部分或全部,加起来为想要转移的总和的币,进行转移。这个“取出”过程中,A、B、C就变成了输入,转账目标记录才是这次交易的输出。
这样的设计,保证了区块链中的钱从哪里来,到哪里去,一清二楚,绝不含糊。跟会计做账一样,花一笔钱,不单单要记录它花到哪里去了,还要记录这笔钱是从哪里来的,整个资金链是可追溯的,这也保证了交易不可伪造,资金既不会凭空消失,也不会无中生有。
##hash
将交易加入到区块里面需要涉及三个hash,一个是交易本身的hash,另一个是当前这个区块所有交易的merkle hash root,还有一个就是区块hash。
上面已经说过输入与输出了,一个交易可能包含多个输入输出,通过将这些输入输出信息进行排列并进行hash运算,就得到一个交易的唯一hash值。
一个区块里面包含了多个交易,包括挖矿奖励交易,这些交易都被通过一个merkle运算,得到一个hash root所包含,对于merkle可以阅读《区块链如何运用merkle tree验证交易真实性》了解。
区块都hash运算里面,merkle hash root作为一个参数,因此,所有交易的信息都体现在了一个区块的hash里面。
Q:
挖矿成功产生的hash值代表的区块的所有信息,应该包含了交易信息。为了保证区块未被篡改。在区块接收到上一个区块广播出的hash验证合理后,开始计算下一块hash,根据情况加入收到的交易信息。直到完成POW证明。代表区块已经产生(挖矿成功)
##挖矿
挖矿过程就是计算上述区块hash的过程,几乎所有的机器都可以挖矿成功。关键在于谁先挖到矿,因为当一台机器挖矿成功就向网络广播,其他挖矿在对这个hash进行校验之后,就停止自己的挖矿,开始基于这个区块挖新的矿。而每一个被挖到区块中记录的第一笔交易是给挖到这个区块的矿工自己的奖励金,所以抢到第一个挖矿成功名额对于矿工来说至关重要。
前面说过,计算区块hash过程里面,会以区块包含的交易的merkle hash root作为计算的一个参数,因此,挖矿时,矿工会事先从自己本地的交易信息里面提炼出merkle hash root,也就是说,在挖矿之前,对于当前这个矿工来说,新区块会包含哪些交易就已经确定好了的。关于这个过程,可以阅读《Merkle Tree》。
##打包交易记录
挖矿成功之后,矿工需要将完整的区块向网络广播,这个时候,这个区块里面就打包了所有上述对应的交易。
现在有三个问题:
在打包开始之前,这些交易记录是以什么方式存在于网络?
打包是否会把所有交易记录打包进区块?怎么可能保证所有交易都不被遗漏?
如何防止矿工伪造交易?将伪造的交易打包进区块?
##手续费
这里需要知道另外一个概念,即“手续费”。手续费是发起交易的节点决定给的,和小费性质一样。比如A打算转给B0.5个BTC,A手上有一个完整的(来自一个输入)BTC,这时A将这1BTC作为输入,输出包含两条,一条是给B0.5BTC,另一条是给自己0.49BTC(这个过程叫“找零”)。那么这个交易中就有0.01BTC是消失了,消失了的BTC将作为小费奖赏给矿工。
现在我们把自己的角色转换为矿工,当我们从自己的内存中收集所有交易,准备打包区块时,发现这里有一条交易有0.01BTC的小费,于是我把它作为本次打包优先考虑的交易记录。由于每个区块的大小限制在1M左右,所有我只选了那些给小费的交易打包进这次区块。而那些未给交易费的交易,在优先考虑完这些有交易费的交易之后,我才会考虑把它们加进来。
这也就是为什么有些交易被确认很快,有些交易被确认很慢。
##确认
“确认”这个概念也要解释一下,一个区块产生之后,它不是立即可信的,网络上的节点总是相信最长的区块链,当一条交易记录被打包进一个区块之后,就有了一个确认,而这个区块所在的链后面被再加入一个区块,就是第二个确认,如此下去,一个交易有了6个确认,我们就认为这个交易已经确定了,会被永远记录在区块链中。为什么是6个确认呢?因为每一个确认就是一个挖矿过程,都需要提供非常严格的计算,因此,这6个区块被同一个矿工创建的可能性微乎其微(可以说是不可能),因此矿工伪造交易也基本不可能。
由于比特币的区块平均产生时间是10分钟,所以一个交易要1小时左右才能保证成功(最快),不过也不是所有的系统都这样认为,有些网站在接受比特币支付时,认为4个确认就可以给客户发货了。如果不幸这个交易在创建的时候,没有被打包进最近的那个区块,那就要延迟10分钟,如此下去,如果后面过了好几个区块,交易都没有被打包进区块链,那就悲剧了。
##广播交易
不过也不用着急,比特币系统中只留给了这种优先级高的交易50k的存储空间,即使你没有给交易费,也可能在24小时内被打包进区块。不过也不一定,有些交易可能永远都进不了区块,因为矿工是从自己都内存中获取自己暂存的交易信息,一旦这些内存被释放,那么这些交易信息就会被清空。为了解决这个问题,比特币钱包需要不断对自己发起的交易进行检查,如果发现没有被打包进最新的区块,就要对网络广播,这样,这个交易就会在网络里不断被提起,矿工又可以把这笔交易写进自己的内存里暂时放着,等到下次打包区块时,选择是否把它打包进去。
Q:
是否将某个交易打包进挖的那个区块确实是矿工自己决定的,所以才会有51%攻击,当你手上控制了超过51%的算力,你就决定了整个网络哪些交易可以被加入到区块链,哪些可能永远都不会。
这和“只保留50K”并不矛盾,那50K是给有手续费的交易的,即使你机器里面还有其他包含了手续费的交易,你也加不到这个块里面来,剩下的大部分空间都是留给你机器上其他交易记录的。因为一次打包不一定可以把当前网络未进链的交易都装进来,所以还有一些交易被留在了网络中,当新块产生之后,这些交易都发起者会去检查,如果自己都交易没有进块,客户端会再次广播自己的交易。一般情况下,产生时间越早的交易会被优先打包,(虽然有些矿工可能把某个节点列入了黑名单,但其他矿工也有可能抢到记账权),24小时足以给这些交易进链的时间。要是正常网速情况下,过了24小时没进链,就说明整个网络可能面临风险,因为现在好像还无法取消一笔发出的交易。
##小结
本文讲解了对于一个交易而言,“创建(输入输出)-广播-挖矿-打包-确认”的整个过程,读完你应该可以理解交易是怎么被打包进区块的了。
BTC 比特币资料集
BTC 区块链浏览器
blockchain
https://testnet.blockchain.info
https://blockchain.info
https://www.blockchain.com/explorer
助记词转换器
Mnemonic Code Converter
https://iancoleman.io
https://iancoleman.io/bip39/
BTC 矿工费
https://bitcoinfees.earn.com/#fees
BTC 测试币领取
戳这里领取 BTC 测试币
请使用测试网的 BTC 地址(Bitcoin Testnet Address)!!!
BTC 钱包客户端
https://bitcoin.org/en/choose-your-wallet
http://webhdwallet.github.io
BTC 钱包开源项目
Bitcoin Github 搜索结果
开源库:
bitcoinj:
A library for working with Bitcoin
https://bitcoinj.github.io/
https://github.com/bitcoinj/bitcoinj
CoreBitcoin:
Awesome Bitcoin toolkit for ObjC and Swift
https://github.com/oleganza/CoreBitcoin
Bitcoin:
Bitcoin Core integration/staging tree
https://github.com/bitcoin
bitheri:
http://bither.net
https://github.com/bither/bitheri
BitcoinKit
Bitcoin protocol toolkit for Swift
https://github.com/kishikawakatsumi/BitcoinKit
https://github.com/Jax1993/BitcoinKit
Bitcoin Developer Reference:
https://bitcoin.org/en/developer-reference
https://bitcoin.org/en/developer-guide
https://bitcoin.org/zh_CN/
https://bitcoin.org/zh_CN/development#more
BitcoinDeveloperGuide_zhcn:比特币开发者指南(中文版)
https://github.com/vacing/BitcoinDeveloperGuide_zhcn
https://www.yiyibooks.cn/Gamma/bitcoin/developer-guide.html
Bitcoin Projects:
http://www.bitcoinprojects.net
https://bitcoin.org/en/wallets/mobile/ios/
BitcoinSwift:
A native framework for working with Bitcoin on iOS and OSX
https://github.com/DoubleSha/BitcoinSwift
https://github.com/blocktree/BitcoinSwift
iOS BTC Wallet:
breadwallet-ios:
bread - bitcoin wallet
http://breadapp.com
https://github.com/voisine/breadwallet-ios
BitStore-iOS:
Native iOS Bitcoin wallet
http://bitstoreapp.com
https://github.com/BitStore/BitStore-iOS
iOS_Blockchain-Merchant:
Blockchain, merchant, QR code, Bitcoin wallet, BTC, Payment integration
https://github.com/chuch0805/iOS_Blockchain-Merchant
chance_btc_wallet:
Chance Bitcoin Wallet — swift opensource bitcoin wallet
https://github.com/zhiquan911/chance_btc_wallet
Airbitz
Airbitz iOS GUI
https://github.com/Airbitz/airbitz-ios-gui-private
WalletCordova
GreenAddress' open source Android (Cordova) client https://greenaddress.it/
https://github.com/greenaddress/WalletCordova
CoinSpace
Coin.Space Digital currency wallet https://www.coin.space
https://github.com/CoinSpace/CoinSpace
Bither
Bither - a simple and secure Bitcoin wallet! http://bither.net
https://github.com/bither/bither-ios
arcbit-ios
arcbit - iOS bitcoin wallet http://arcbit.io
https://github.com/arcbit/arcbit-ios
mycelium-wallet-ios
Mycelium Bitcoin Wallet for iOS. http://mycelium.com
https://github.com/mycelium-com/wallet-ios
Android BTC Wallet:
samourai-wallet-android
Samourai Bitcoin Wallet for Android. https://samouraiwallet.com
https://github.com/Samourai-Wallet/samourai-wallet-android
mycelium-wallet-android
Mycelium Bitcoin Wallet for Android http://mycelium.com
https://github.com/mycelium-com/wallet-ios
BTC API 文档:
BTC.com:
https://btc.com/api-doc
BIP:
比特币改进方案 Bitcoin Improvement Proposals
https://github.com/bitcoin/bips
比特币改进协议BIP32(翻译)
https://blog.csdn.net/pony_maggie/article/details/76178228
区块链钱包之BIP32, BIP39, BIP44
https://blog.csdn.net/qq634416025/article/details/79686015
BTC 电子书:
《精通比特币》:
http://zhibimo.com/read/wang-miao/mastering-bitcoin/index.html
《中本聪(Satoshi Nakamoto)比特币白皮书英文版》
https://github.com/GammaGao/bitcoinwhitepaper/blob/master/bitcoin_en.pdf
《中本聪(Satoshi Nakamoto)比特币白皮书中文版》
https://github.com/GammaGao/bitcoinwhitepaper/blob/master/bitcoin_cn.pdf
《比特币开发者指南英文版》
https://bitcoin.org/en/developer-guide
《比特币开发者指南中文版》
https://www.yiyibooks.cn/Gamma/bitcoin/developer-guide.html
https://github.com/vacing/BitcoinDeveloperGuide_zhcn
https://legacy.gitbook.com/book/vacing/bitcoindeveloperguide_zhcn/details
《The Internet of Money》(第1卷)中文版
https://github.com/BtcGroupCn/TheInternetOfMoney_1
BTC 文章:
比太钱包的博客
http://blog.sina.com.cn/bither
nuptuser的专栏
https://blog.csdn.net/gammag/article/category/6954035
老杨QQ122209017的博客
https://blog.csdn.net/sinat_34070003/article/category/7582246
浅析比特币的找零机制
https://blog.csdn.net/wo541075754/article/details/53560061
比特币 区块链 几种交易标准详解 P2PKH、P2PK、MS、P2SH加密方式
https://blog.csdn.net/jerry81333/article/details/56824166
BIP16 P2SH交易脚本
https://blog.csdn.net/sinat_34070003/article/details/79871044
比特币系统的脚本(Script)——交易生成和验证的原理(第一部分)(初稿)
https://blog.csdn.net/taifei/article/details/73321293
多签名交易和P2SH
http://blog.sina.com.cn/s/blog_130223eeb0101ipwi.html
理解比特币脚本
https://zhuanlan.zhihu.com/p/25461051
比特币脚本及交易分析 - 智能合约雏形
https://blockflow.net/t/topic/196
Linuxest
https://blog.csdn.net/ddk3001/article/category/7736876
一文看懂怎样用 Python 创建比特币交易
https://blog.csdn.net/Blockchain_lemon/article/details/79798913
隔离见证
https://blog.csdn.net/taifei/article/details/73479998
https://www.jianshu.com/p/2a5e038074a0
https://baike.baidu.com/item/隔离见证/22448459?fr=aladdin
https://blog.csdn.net/sinat_34070003/article/details/79893114
作者:AlleniCoder
链接:https://www.jianshu.com/p/5521eecb0ad0
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
Testnet测试网络配置
测试网络BTC领取:
https://testnet.manu.backend.hamburg/faucet
https://testnet.coinfaucet.eu/en/
insight测试网络: http://192.168.50.159:3001/insight/
insight文档:
http://192.168.50.159:3001/insight/address/n44UNAeSMPLrZcr8W2QRn9jbZsW3NJ8YUj
交易费字节数计算方式:
148 * 输入数额 + 34 * 输出数额 + 10
148 * inputs_count + 34 * outputs_count + 10
Copyright © 2015 Powered by MWeb, 豫ICP备09002885号-5