今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

iOS RC4 encryption

iOS RC4 Encryption#

The implementation of RC4 encryption in iOS requires special attention to the steps for generating the encrypted string. Some requirements call for base64 encryption output, while others require converting the byte array to a hexadecimal string. Therefore, special attention must be paid.

The code is as follows:



// RC4 encryption
- (NSString *)rc4Encode:(NSString *)aInput key:(NSString *)aKey {
    NSMutableArray *iS = [[NSMutableArray alloc] initWithCapacity:256];
        NSMutableArray *iK = [[NSMutableArray alloc] initWithCapacity:256];
        for (int i= 0; i<256; i++) {
            [iS addObject:[NSNumber numberWithInt:i]];
        }
        int j=1;
        for (short i=0; i<256; i++) {
            UniChar c = [aKey characterAtIndex:i%aKey.length];
            [iK addObject:[NSNumber numberWithChar:c]];
        }
        j=0;
        for (int i=0; i<256; i++) {
            int is = [[iS objectAtIndex:i] intValue];
            UniChar ik = (UniChar)[[iK objectAtIndex:i] charValue];
            j = (j + is + ik)%256;
            NSNumber *temp = [iS objectAtIndex:i];
            [iS replaceObjectAtIndex:i withObject:[iS objectAtIndex:j]];
            [iS replaceObjectAtIndex:j withObject:temp];
        }
        int i=0;
        j=0;
        Byte byteBuffer[aInput.length];
        for (short x=0; x<[aInput length]; x++) {
            i = (i+1)%256;
            int is = [[iS objectAtIndex:i] intValue];
            j = (j+is)%256;
            int is_i = [[iS objectAtIndex:i] intValue];
            int is_j = [[iS objectAtIndex:j] intValue];
            int t = (is_i+is_j) % 256;
            // Pay attention here, the original version retrieves the value first and then swaps the positions, but there is a problem, the positions should be swapped first and then the value should be retrieved!!!
            [iS exchangeObjectAtIndex:i withObjectAtIndex:j];
            int iY = [[iS objectAtIndex:t] intValue];
            UniChar ch = (UniChar)[aInput characterAtIndex:x];
            UniChar ch_y = ch^iY;
            byteBuffer[x] = ch_y;
        }
    
    // Convert byte array to hexadecimal string
    NSString *resultString = [self stringFromByte:byteBuffer length:aInput.length];
    
//    NSData *adata = [[NSData alloc] initWithBytes:byteBuffer length:aInput.length];
//    NSString *string = [adata base64EncodedStringWithOptions:0]; // Output as base64 encryption result
    return resultString;
}

// RC4 decryption
- (NSString *)rc4Decode:(NSString *)data key:(NSString*)secret{
    // If it is a hexadecimal string
    NSData *raw = [self ByteDataFromString:data];
    
    // If it is a string encrypted with base64
//    NSData *raw = [[NSData alloc] initWithBase64EncodedString:data options:0];
    
    int cipherLength = (int)raw.length;
    UInt8 *cipher = malloc(cipherLength);
    [raw getBytes:cipher length:cipherLength];
    NSData *kData = [secret dataUsingEncoding:NSUTF8StringEncoding];
    int keyLength = (int)kData.length;
    UInt8 *kBytes = malloc(kData.length);
    [kData getBytes:kBytes length:kData.length];
    UInt8 *decipher = malloc(cipherLength + 1);
    UInt8 iS[256];
    UInt8 iK[256];
    int i;
    for (i = 0; i < 256; i++){
        iS[i] = i;
        iK[i] = kBytes[i % keyLength];
    }
    int j = 0;
    for (i = 0; i < 256; i++){
        int is = iS[i];
        int ik = iK[i];
        j = (j + is + ik)% 256;
        UInt8 temp = iS[i];
        iS[i] = iS[j];
        iS[j] = temp;
    }
    int q = 0;
    int p = 0;
    for (int x = 0; x < cipherLength; x++){
        q = (q + 1)% 256;
        p = (p + iS[q])% 256;
        int k = iS[p];
        iS[p] = iS[q];
        iS[q] = k;
        k = iS[(iS[q] + iS[p])% 256];
        decipher[x] = cipher[x] ^ k;
    }
    free(kBytes);
    decipher[cipherLength] = '\0';
    return @((char *)decipher);
}

// Convert byte array to string
- (NSString *)stringFromByte:(Byte *)byteBuffer length:(NSInteger)length {
    NSMutableString *hexString = [[NSMutableString alloc] init];
    for (int i = 0; i < length; i++) {
        [hexString appendString:[NSString stringWithFormat:@"%0.2hhx", byteBuffer[i]]];
    }
    return [hexString uppercaseString];
}

- (NSData *)ByteDataFromString:(NSString *)targetStr {
    NSInteger len = [targetStr length] / 2;    // Target length
    unsigned char *buf = malloc(len);
    unsigned char *whole_byte = buf;
    char byte_chars[3] = {'\0','\0','\0'};

    int i;
    for (i=0; i < [targetStr length] / 2; i++) {
        byte_chars[0] = [targetStr characterAtIndex:i*2];
        byte_chars[1] = [targetStr characterAtIndex:i*2+1];
        *whole_byte = strtol(byte_chars, NULL, 16);
        whole_byte++;
    }

    NSData *data = [NSData dataWithBytes:buf length:len];
    free( buf );
    return data;
}

Reference#

iOS,objectC,RC4 Encryption and Decryption Methods
iOS Convert Binary Array to Hexadecimal String

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.