swift - Swift/Objective-C ASN1编码公钥

标签 swift encryption rsa asn.1

我需要一些有关Swift中加密的帮助。我一直在搜索有关RSA加密的很多内容。

我们有一个从后端服务器生成的公共密钥,我们需要使用该密钥对将再次传递回后端服务器的秘密消息进行加密。

我能够找到RSA加密库,但是由于我们的公钥是在ASN.1中编码的,因此恐怕会遇到问题。

更新:

以下是我们的实际代码。我们尝试使用来自服务器的ASN.1编码的公共密钥对消息进行加密。问题是,我们的后端服务器要求加密的密码为十六进制值,尽管我已经这样做了,但是我们的后端无法解密消息。

+ (SecKeyRef) setPublicKey: (NSString *) keyAsBase64 {

/* First decode the Base64 string */
NSData * rawFormattedKey = base64_decode(keyAsBase64);

/* Now strip the uncessary ASN encoding guff at the start */
unsigned char * bytes = (unsigned char *)[rawFormattedKey bytes];
size_t bytesLen = [rawFormattedKey length];

/* Strip the initial stuff */
size_t i = 0;
if (bytes[i++] != 0x30)
    return FALSE;

/* Skip size bytes */
if (bytes[i] > 0x80)
    i += bytes[i] - 0x80 + 1;
else
    i++;

if (i >= bytesLen)
    return FALSE;

if (bytes[i] != 0x30)
    return FALSE;

/* Skip OID */
i += 15;

if (i >= bytesLen - 2)
    return FALSE;

if (bytes[i++] != 0x03)
    return FALSE;

/* Skip length and null */
if (bytes[i] > 0x80)
    i += bytes[i] - 0x80 + 1;
else
    i++;

if (i >= bytesLen)
    return FALSE;

if (bytes[i++] != 0x00)
    return FALSE;

if (i >= bytesLen)
    return FALSE;

/* Here we go! */
NSData * extractedKey = [NSData dataWithBytes:&bytes[i] length:bytesLen - i];

/* Load as a key ref */
OSStatus error = noErr;
CFTypeRef persistPeer = NULL;

static const UInt8 publicKeyIdentifier[] = "com.our.key";
NSData * refTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];

NSMutableDictionary * keyAttr = [[NSMutableDictionary alloc] init];

/* First we delete any current keys */
[keyAttr setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[keyAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[keyAttr setObject:refTag forKey:(__bridge id)kSecAttrApplicationTag];
error = SecItemDelete((__bridge CFDictionaryRef) keyAttr);

[keyAttr setObject:extractedKey forKey:(__bridge id)kSecValueData];
[keyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];
error = SecItemAdd((__bridge CFDictionaryRef) keyAttr, (CFTypeRef *)&persistPeer);

CFRelease(persistPeer);

/* Now we extract the real ref */
SecKeyRef publicKeyRef = nil;

[keyAttr removeAllObjects];
[keyAttr setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[keyAttr setObject:refTag forKey:(__bridge id)kSecAttrApplicationTag];
[keyAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[keyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];

// Get the persistent key reference.
error = SecItemCopyMatching((__bridge CFDictionaryRef)keyAttr, (CFTypeRef *)&publicKeyRef);

if (publicKeyRef == nil || ( error != noErr && error != errSecDuplicateItem)) {
    NSLog(@"Error retrieving public key reference from chain");
    return FALSE;
}


return publicKeyRef;
}


+(NSString* )encryptWithPublicKey:(NSString*)key input:(NSString*) input {
const size_t BUFFER_SIZE =      16;
const size_t CIPHER_BUFFER_SIZE = 16;
const uint32_t PKCS1 = kSecPaddingPKCS1;

SecKeyRef publicKey = [self setPublicKey:key];

NSData *crypted = nil;
NSData *rawinput = [input dataUsingEncoding:NSUTF8StringEncoding];
NSString *theInput = [self base64forData:rawinput];
NSData *data = [theInput dataUsingEncoding:NSUTF8StringEncoding];

uint8_t *srcbuf;
srcbuf = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));
srcbuf = (uint8_t *)[data bytes];

size_t srclen = (size_t)data.length;
size_t outlen = SecKeyGetBlockSize(publicKey) * sizeof(uint8_t);
void *outbuf = malloc(outlen);

OSStatus status = noErr;
status = SecKeyEncrypt(publicKey,
                       PKCS1,
                       srcbuf,
                       srclen,
                       outbuf,
                       &outlen);

if (status != 0) {
    //NSLog(@"SecKeyEncrypt fail. Error Code: %ld", status);
}else{
    crypted = [NSData dataWithBytes:outbuf length:outlen];
}

NSString *str = [crypted stringWithHexBytes2];

free(outbuf);
CFRelease(publicKey);
return str;
}


这是NSData十六进制转换的类别。

- (NSString*)stringWithHexBytes2 {
static const char hexdigits[] = "0123456789abcdef";
const size_t numBytes = [self length];
const unsigned char* bytes = [self bytes];
char *strbuf = (char *)malloc(numBytes * 2 + 1);
char *hex = strbuf;
NSString *hexBytes = nil;

for (int i = 0; i<numBytes; ++i) {
    const unsigned char c = *bytes++;
    *hex++ = hexdigits[(c >> 4) & 0xF];
    *hex++ = hexdigits[(c ) & 0xF];
}
*hex = 0;
hexBytes = [NSString stringWithUTF8String:strbuf];
free(strbuf);
return hexBytes;
}

最佳答案

问题不在于加密。但是,由于安全原因和公司政策,我们需要几个加密步骤和级别,后端才能成功解密密码。

非常感谢你们为帮助我所做的努力。

顺便说一句,即使上面的代码不包含我们额外的加密级别,也可以正常工作。

关于swift - Swift/Objective-C ASN1编码公钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32174164/

相关文章:

ios - 消除本地类与 Firebase 重命名类的歧义

swift - 如何从 Firebase 存储下载 URL 中删除查询字符串

java - 如何使用 RSA 公钥加密 java.util.Properties 对象(可以是任意大小)?

使用 SHA256withRSA 算法验证 WSO2 API 网关 JWT 签名的 C# .NET 代码

java - 如何在 Java 中将 PublicKey 转换为 JSON?

ios - 在不使用 SKShapeNode(IOS 7 兼容)的情况下在 swift sprite 工具包中绘制圆圈的最佳方法?

swift - Twilio - 使用快速客户端代码通过 inviteByIdentity 在私有(private) channel 上邀请用户

javascript - 如何确定PDF是否是加密的javascript客户端

java - SSL握手过程

javascript - 使用 CryptoJS 加密数据并使用 AESCipherService 解密