首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从私有SecKeyRef获取公钥

从私有SecKeyRef获取公钥
EN

Stack Overflow用户
提问于 2014-06-28 21:17:09
回答 2查看 843关注 0票数 11

给定使用SecKeyRef私钥使用SecItemImport加载的SecKeyRef,是否有一种方法只为公钥组件获取或创建SecKeyRef?在OpenSSL中,这可以通过将模数和公共指数复制到一个新的结构中来实现,但是SecKeyRef是不透明的,而且我一直无法找到执行此操作的函数。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-09-13 18:25:52

从macOS 10.12、iOS/tvOS 10和watchOS 3开始,SecKeyCopyPublicKey函数就已经存在了。

票数 1
EN

Stack Overflow用户

发布于 2014-12-12 19:20:12

老问题,但因为我今天和它斗争,我找到了一个方法。假设您有base64编码的公钥(它不是证书,它不是der,pem,.),在Java (X509证书公钥)中创建的,您可以这样创建SecKeyRef

代码语言:javascript
复制
- (NSData *)stripPublicKeyHeader2:(NSData *)keyBits {
  // Skip ASN.1 public key header
  if (keyBits == nil) {
    return nil;
  }

  unsigned int len = [keyBits length];
  if (!len) {
    return nil;
  }

  unsigned char *c_key = (unsigned char *)[keyBits bytes];
  unsigned int  idx    = 0;

  if (c_key[idx++] != 0x30) {
    return nil;
  }

  if (c_key[idx] > 0x80) {
    idx += c_key[idx] - 0x80 + 1;
  }
  else {
    idx++;
  }

  if (idx >= len) {
    return nil;
  }

  if (c_key[idx] != 0x30) {
    return nil;
  }

  idx += 15;

  if (idx >= len - 2) {
    return nil;
  }

  if (c_key[idx++] != 0x03) {
    return nil;
  }

  if (c_key[idx] > 0x80) {
    idx += c_key[idx] - 0x80 + 1;
  }
  else {
    idx++;
  }

  if (idx >= len) {
    return nil;
  }

  if (c_key[idx++] != 0x00) {
    return nil;
  }

  if (idx >= len) {
    return nil;
  }

  // Now make a new NSData from this buffer
  return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}

- (SecKeyRef)publicKey:(NSData *)d_key withTag:(NSString *)tag
{
  NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

  NSDictionary *saveDict = @{
                             (__bridge id) kSecClass : (__bridge id) kSecClassKey,
                             (__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA,
                             (__bridge id) kSecAttrApplicationTag : d_tag,
                             (__bridge id) kSecAttrKeyClass : (__bridge id) kSecAttrKeyClassPublic,
                             (__bridge id) kSecValueData : d_key
                             };

  OSStatus secStatus = SecItemAdd((__bridge CFDictionaryRef)saveDict, NULL );
  if (secStatus == errSecDuplicateItem ) {
    SecItemDelete((__bridge CFDictionaryRef)saveDict);
    secStatus = SecItemAdd((__bridge CFDictionaryRef)saveDict, NULL );
  }

  if ( secStatus != noErr ) {
    return NULL;
  }

  NSDictionary *queryDict = @{
                              (__bridge id) kSecClass : (__bridge id) kSecClassKey,
                              (__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA,
                              (__bridge id) kSecAttrApplicationTag : tag,
                              (__bridge id) kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPublic,
                              (__bridge id) kSecReturnRef : (__bridge id) kCFBooleanTrue
                              };

  // Now fetch the SecKeyRef version of the key
  SecKeyRef keyRef = nil;
  secStatus = SecItemCopyMatching((__bridge CFDictionaryRef)queryDict,
                                  (CFTypeRef *)&keyRef);

  if ( secStatus != noErr ) {
    return NULL;
  }

  return keyRef;
}

NSData *keyData = [[NSData alloc] initWithBase64EncodedString:@"base64encoded X509 private key"
                                                              options:0];
certificateData = [self stripPublicKeyHeader2:keyData];
SecKeyRef key = [self publicKey:certificateData withTag:[[NSUUID UUID] UUIDString]];

有点尴尬,不是我的代码,整天在谷歌上搜索,很多片段粘在一起。得清理一下..。把它当作是从互联网上汇编出来的黑客。

在用Java编写代码的服务器上进行测试,这是唯一的方法。我找到的唯一方法。也许还有另外一种方法,但只有这一种才对我有效,我可以用这个RSA公钥加密(我们的服务器代码(Java)可以解密它)。而且它只在没有填充(不推荐)的情况下工作,在iOS端使用kSecPaddingOAEP填充,在Java端使用RSA/NONE/OAEPWithSHA1AndMGF1Padding

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24471030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档