ECkeyUtils.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //
  2. // ECkeyUtils.m
  3. // RSADemo
  4. //
  5. // Created by 武建明 on 2018/6/20.
  6. // Copyright © 2018年 Ive. All rights reserved.
  7. //
  8. #import "ECkeyUtils.h"
  9. #import <openssl/pem.h>
  10. #import <openssl/obj_mac.h>
  11. #import <openssl/ecdh.h>
  12. @implementation ECkeyPairs
  13. @end
  14. @implementation ECkeyUtils
  15. typedef enum VoidType {
  16. VoidTypePrivate = 0,
  17. VoidTypePublic
  18. } voidType;
  19. static int KCurveName = NID_secp256k1; //曲线参数,需多端一致
  20. - (ECkeyPairs *)eckeyPairs{
  21. if (!_eckeyPairs) {
  22. _eckeyPairs = [[ECkeyPairs alloc] init];
  23. }
  24. return _eckeyPairs;
  25. }
  26. - (void)generatekeyPairs{
  27. // 生成公钥私钥
  28. EC_KEY *eckey;
  29. eckey = [self createNewKeyWithCurve:KCurveName];
  30. NSString *privatePem = [self getPem:eckey voidType:VoidTypePrivate];
  31. NSString *publicPem = [self getPem:eckey voidType:VoidTypePublic];
  32. self.eckeyPairs.privatePem = privatePem;
  33. self.eckeyPairs.privateKey = [ECkeyUtils getKeyFromPemKey:privatePem isPrivate:YES];
  34. self.eckeyPairs.publicPem = publicPem;
  35. self.eckeyPairs.publicKey = [ECkeyUtils getKeyFromPemKey:publicPem isPrivate:NO];
  36. EC_KEY_free(eckey);
  37. }
  38. + (NSString *)getShareKeyFromPeerPubPem:(NSString *)peerPubPem
  39. privatePem:(NSString *)privatePem
  40. length:(int)length{
  41. // 根据私钥PEM字符串,生成私钥
  42. EC_KEY *clientEcKey = [ECkeyUtils privateKeyFromPEM:privatePem];
  43. if (!clientEcKey) {
  44. return nil;
  45. }
  46. if (!length) {
  47. // 获取私钥长度
  48. const EC_GROUP *group = EC_KEY_get0_group(clientEcKey);
  49. length = (EC_GROUP_get_degree(group) + 7)/8;
  50. }
  51. NSLog(@"\n--------------------------------------------------------------需生成Sharekey长度:%d",length);
  52. // 根据peerPubPem生成新的公钥EC_KEY
  53. EC_KEY *serverEcKey = [ECkeyUtils publicKeyFromPEM:peerPubPem];
  54. const EC_POINT *serverEcKeyPoint = EC_KEY_get0_public_key(serverEcKey);
  55. char shareKey[length];
  56. ECDH_compute_key(shareKey, length, serverEcKeyPoint, clientEcKey, NULL);
  57. // 释放公钥,释放私钥
  58. EC_KEY_free(clientEcKey);
  59. EC_KEY_free(serverEcKey);
  60. NSData *shareKeyData = [NSData dataWithBytes:shareKey length:length];
  61. NSString *shareKeyStr = [shareKeyData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
  62. NSLog(@"\nShareKey:\n--------\n%@\n--------",shareKeyStr);
  63. return shareKeyStr;
  64. }
  65. /**
  66. 获取PEM格式的EC_KEY
  67. @param ecKey 目标EC_KEY
  68. @param voidType 方法类型
  69. @return 返回PEM格式的KEY
  70. */
  71. - (NSString *)getPem:(EC_KEY *)ecKey
  72. voidType:(voidType)voidType{
  73. BIO *out = NULL;
  74. BUF_MEM *buf;
  75. buf = BUF_MEM_new();
  76. out = BIO_new(BIO_s_mem());
  77. switch (voidType) {
  78. case VoidTypePrivate:
  79. PEM_write_bio_ECPrivateKey(out, ecKey, NULL, NULL, 0, NULL, NULL);
  80. break;
  81. case VoidTypePublic:
  82. PEM_write_bio_EC_PUBKEY(out, ecKey);
  83. break;
  84. default:
  85. break;
  86. }
  87. BIO_get_mem_ptr(out, &buf);
  88. NSString *pem = [[NSString alloc] initWithBytes:buf->data
  89. length:(NSUInteger)buf->length
  90. encoding:NSASCIIStringEncoding];
  91. BIO_free(out);
  92. return pem;
  93. }
  94. + (EC_KEY *)publicKeyFromPEM:(NSString *)publicKeyPEM {
  95. // 将PEM格式的公钥字符串转化成EC_KEY
  96. const char *buffer = [publicKeyPEM UTF8String];
  97. BIO *bpubkey = BIO_new_mem_buf(buffer, (int)strlen(buffer));
  98. EVP_PKEY *public = PEM_read_bio_PUBKEY(bpubkey, NULL, NULL, NULL);
  99. EC_KEY *ec_cdata = EVP_PKEY_get1_EC_KEY(public);
  100. BIO_free_all(bpubkey);
  101. return ec_cdata;
  102. }
  103. + (EC_KEY *)privateKeyFromPEM:(NSString *)privateKeyPEM {
  104. // 将PEM格式的私钥字符串转化成EC_KEY
  105. const char *buffer = [privateKeyPEM UTF8String];
  106. BIO *out = BIO_new_mem_buf(buffer, (int)strlen(buffer));
  107. EC_KEY *pricateKey = PEM_read_bio_ECPrivateKey(out, NULL, NULL, NULL);
  108. BIO_free_all(out);
  109. return pricateKey;
  110. }
  111. - (EC_KEY *)createNewKeyWithCurve:(int)curve {
  112. // 生成EC_KEY对象
  113. int asn1Flag = OPENSSL_EC_NAMED_CURVE;
  114. int form = POINT_CONVERSION_UNCOMPRESSED;
  115. EC_KEY *eckey = NULL;
  116. EC_GROUP *group = NULL;
  117. eckey = EC_KEY_new();
  118. group = EC_GROUP_new_by_curve_name(curve);
  119. EC_GROUP_set_asn1_flag(group, asn1Flag);
  120. EC_GROUP_set_point_conversion_form(group, form);
  121. EC_KEY_set_group(eckey, group);
  122. int resultFromKeyGen = EC_KEY_generate_key(eckey);
  123. if (resultFromKeyGen != 1){
  124. raise(-1);
  125. }
  126. return eckey;
  127. }
  128. // pem证书转换为普通证书
  129. + (NSString *)getKeyFromPemKey:(NSString *)pemKey isPrivate:(BOOL)isPrivate {
  130. NSString *key = [NSString string];
  131. key = [pemKey copy];
  132. key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
  133. NSRange range1, range2;
  134. if (isPrivate) {
  135. range1 = [key rangeOfString:@"-----BEGIN EC PRIVATE KEY-----"];
  136. range2 = [key rangeOfString:@"-----END EC PRIVATE KEY-----"];
  137. }else {
  138. range1 = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
  139. range2 = [key rangeOfString:@"-----END PUBLIC KEY-----"];
  140. }
  141. key = [key substringWithRange:NSMakeRange(range1.location + range1.length, range2.location - range1.location - range1.length)];
  142. return key;
  143. }
  144. // 普通证书转换为pem证书
  145. + (NSString *)getPemKeyFromKey:(NSString *)key isPrivate:(BOOL)isPrivate {
  146. NSMutableString *pemKey = [NSMutableString string];
  147. if (isPrivate) {
  148. [pemKey appendString:@"-----BEGIN EC PRIVATE KEY-----\n"];
  149. }else {
  150. [pemKey appendString:@"-----BEGIN PUBLIC KEY-----\n"];
  151. }
  152. // 没歌64需要插入换行符
  153. NSMutableString *appendStr = [key mutableCopy];
  154. NSInteger index = 0;
  155. if (appendStr.length > 64) {
  156. index = 64;
  157. }
  158. while (index > 0) {
  159. [appendStr insertString:@"\n" atIndex:index];
  160. NSString *str = [appendStr substringFromIndex:index + 2];
  161. if (str.length > 64) {
  162. // 设置index为插入的换行符后64的位置
  163. index = index + 2 + 64;
  164. }else {
  165. index = 0;
  166. }
  167. }
  168. [pemKey appendString:appendStr];
  169. if (isPrivate) {
  170. [pemKey appendString:@"\n-----END EC PRIVATE KEY-----"];
  171. }else {
  172. [pemKey appendString:@"\n-----END PUBLIC KEY-----"];
  173. }
  174. return pemKey;
  175. }
  176. @end