PKCS1填充/ RSA加密之间的区别ios objc和java [英] Difference between PKCS1-padding/RSA encryption ios objc and java

查看:241
本文介绍了PKCS1填充/ RSA加密之间的区别ios objc和java的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为ios和Android开发应用程序。我比较新的加密任务,而最后3天,我不停地将我的头撞在墙上,因为我无法获得RSA加密运行。

I’m developing a application for ios and Android. I’m relatively new to crypto tasks and for the last 3 Days I keep banging my head against the wall because I’m not able to get RSA encryption running.

两个客户端都从java服务器接收公钥。在android中(显然,因为它几乎与服务器端的代码相同)没有任何麻烦,但是ios的部分似乎是不兼容的。我想用公钥加密一小块数据(aes key),这是我在Java中如何做到这一点:$ b​​ $ b

Both clients receive a public key from a java server. In android i have (obviously, because it is almost the same code as on server side) no troubles, but the ios part seems to be not compatible at all. I want to encrypt a little piece of data (aes key) with the public key and this is how I do this in Java:

try {
    String publickey  = "MCwwDQYJKoZIhvcNAQEBBQADGwAwGAIRAK+dBpbOKw+1VKMWoFxjU6UCAwEAAQ==";
    byte[] bArr = Crypto.base64Decode(publicKey, false);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
    EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKey);
    PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

    Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding", "BC");
    cipher.init(1,publicKey);
    int cipherBlockSize = cipher.getBlockSize();
    ByteArrayOutputStream bArrOut = new ByteArrayOutputStream();
    bArrOut.flush();
    int pos = 0;
    Log.i("ContentBufferLength", contentBuffer.length+"");

    while (true) {
        if (cipherBlockSize > contentBuffer.length - pos) {
            cipherBlockSize = contentBuffer.length - pos;
        }
        Log.i("CipherBlockSize", cipherBlockSize+"");
        byte[] tmp = cipher.doFinal(contentBuffer, pos, cipherBlockSize);
        bArrOut.write(tmp);
        pos += cipherBlockSize;
        if (contentBuffer.length <= pos) {
            break;
        }
    }
    bArrOut.flush();
    encryptedBuffer = bArrOut.toByteArray();
    bArrOut.close();
} catch (Exception ex) {
    throw ex;
}

//  Log.i("Encrypted Buffer Length", encryptedBuffer.length+"");
return encryptedBuffer;

这是我的(不正常工作)的ios代码,从这里借来:

And this is my (not properly working) ios code, borrowed from here:

http://blog.wingsofhermes.org/?p= 75 和苹果密码练习。

-(NSString* )encryptWithPublicKey:(NSString*)key input:(NSString*) input {
    const size_t BUFFER_SIZE =      16;
    const size_t CIPHER_BUFFER_SIZE = 16;
   //const uint32_t PADDING = kSecPaddingNone;
    const uint32_t PADDING = kSecPaddingPKCS1;

    static const UInt8 publicKeyIdentifier[] = "de.irgendwas.app";

    NSData *publicTag;

    publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];

    NSMutableDictionary *publicKey2 = [[NSMutableDictionary alloc] init];
    [publicKey2 setObject:kSecClassKey forKey:kSecClass];
    [publicKey2 setObject:kSecAttrKeyTypeRSA forKey:kSecAttrKeyType];
    [publicKey2 setObject:publicTag forKey:kSecAttrApplicationTag];
    SecItemDelete((CFDictionaryRef)publicKey2);


    NSData *strippedPublicKeyData = [NSData dataFromBase64String:key];

    unsigned char * bytes = (unsigned char *)[strippedPublicKeyData bytes];
    size_t bytesLen = [strippedPublicKeyData length];

    size_t i = 0;
    if (bytes[i++] != 0x30)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

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

    if (i >= bytesLen)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

    if (bytes[i] != 0x30)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

    /* Skip OID */
    i += 15;

    if (i >= bytesLen - 2)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

    if (bytes[i++] != 0x03)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

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

    if (i >= bytesLen)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

    if (bytes[i++] != 0x00)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

    if (i >= bytesLen)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

    strippedPublicKeyData = [NSData dataWithBytes:&bytes[i] length:bytesLen - i];

    DLog(@"X.509 Formatted Public Key bytes:\n%@",[strippedPublicKeyData description]);

    if (strippedPublicKeyData == nil)
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];



    CFTypeRef persistKey = nil;
    [publicKey2 setObject:strippedPublicKeyData forKey:kSecValueData];
    [publicKey2 setObject: (kSecAttrKeyClassPublic) forKey:kSecAttrKeyClass];
    [publicKey2 setObject:[NSNumber numberWithBool:YES] forKey:kSecReturnPersistentRef];

    OSStatus secStatus = SecItemAdd((CFDictionaryRef)publicKey2, &persistKey);

    if (persistKey != nil) CFRelease(persistKey);

    if ((secStatus != noErr) && (secStatus != errSecDuplicateItem))
        [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

    SecKeyRef keyRef = nil;
    [publicKey2 removeObjectForKey:kSecValueData];
    [publicKey2 removeObjectForKey:kSecReturnPersistentRef];
    [publicKey2 setObject:[NSNumber numberWithBool:YES] forKey:kSecReturnRef];
    [publicKey2 setObject: kSecAttrKeyTypeRSA forKey:kSecAttrKeyType];

    SecItemCopyMatching((CFDictionaryRef)publicKey2,(CFTypeRef *)&keyRef);
    if (!keyRef)
    [Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];  

    uint8_t *plainBuffer;
    uint8_t *cipherBuffer;
    uint8_t *decryptedBuffer;


    const char inputString[] = "1234";
    int len = strlen(inputString);
    // TODO: this is a hack since i know inputString length will be less than BUFFER_SIZE
    if (len > BUFFER_SIZE) len = BUFFER_SIZE-1;
    plainBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));
    cipherBuffer = (uint8_t *)calloc(CIPHER_BUFFER_SIZE, sizeof(uint8_t));
    decryptedBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));

    strncpy( (char *)plainBuffer, inputString, len);

    size_t plainBufferSize = strlen((char *)plainBuffer);
    size_t cipherBufferSize = CIPHER_BUFFER_SIZE;

    NSLog(@"SecKeyGetBlockSize() public = %lu", SecKeyGetBlockSize(keyRef));
    //  Error handling
    // Encrypt using the public.
    OSStatus status = noErr;

    status = SecKeyEncrypt(keyRef,
                           PADDING,
                           plainBuffer,
                           plainBufferSize,
                           &cipherBuffer[0],
                           &cipherBufferSize
                           );
    NSLog(@"encryption result code: %ld (size: %lu)", status, cipherBufferSize);

    return [[[NSString stringWithFormat:@"%s",cipherBuffer] dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString];
}

为了测试目的和简单性,我试图加密输入长度为4个字节。这应该足够小以适应一个块。公钥导入和加密过程似乎起作用,但是与android方法相比,我总是收到更长的输出。

For testing purposes and simplicity for the moment I am trying to encrypt only a input with a length of 4 bytes. This should be small enough to fit one block. The public key import and the encrypting process seems to work, however I always receive a much longer output compared to the android method.

到目前为止我遇到的唯一的区别是事实上, SecKeyGetBlockSize返回16 ,而在java cipher.blocksize中返回5.我认为其他11个字节是为pkcs1填充保留的,但是如何强制相同的行为在 ios / objc

The only difference I encountered so far is the fact, that SecKeyGetBlockSize returns 16 and in java cipher.blocksize returns 5. I think the other 11 bytes are reserved for the pkcs1 padding, but how can force the same behaviour in ios/objc?

推荐答案

尝试将密码分解成多个部分所以每个包含16个char long并单独解码它们。我也面临同样的问题,但PHP中长时间以上的技巧在为我工作。

Try up with splitting cipher text into multiple parts so that each contains 16 char long and separately decode them. I too faced the same problem but that was in PHP for a long time and above trick worked for me.

这可能有助于您解决问题。

This may be help you to get-out of the problem.

这篇关于PKCS1填充/ RSA加密之间的区别ios objc和java的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆