Question

I'm trying to decrypt string encrypted by golang script. The encryption is CBC, key size 256. 16 bytes long iv is include at the beginning of ciphered text, as golang doc suggested. Everything works fine except the objc codes always lost the last block. e.g. when I expect 80 bytes return but only get 64, expect 128 but get 112. any advice? thanks!

golang code

func encrypt(text_s, key_s string) byte[] {

    text := []byte(text_s)

    // padding text
    n := aes.BlockSize - (len(text) % aes.BlockSize)
    log.Println("Need to pad:", n)

    if n != aes.BlockSize || n != 0 {
        text = append([]byte(strings.Repeat(" ", n)), text...)
    }

    log.Println("to encrypt:'", string(text), "'")
    log.Println("padded length:", len(text))

    key  := []byte(key_s)[:32]
    block, _ := aes.NewCipher(key)

    // if err != nil {
    //  panic(err)
    // }

    ret := make([]byte, aes.BlockSize + len(text))
    iv  := ret[:aes.BlockSize]

    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        panic(err)
    }

    cbc := cipher.NewCBCEncrypter(block, iv)
    cbc.CryptBlocks(ret[aes.BlockSize:], text)

    return ret
}

objc codes:

    - (NSData *)decrypt:(NSData*)data{
    if (!key) {
        key = [[_token substringToIndex:32] dataUsingEncoding:NSUTF8StringEncoding];
    }

//    NSLog(@"decodbase64 :%@",[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
//    NSString *key = _token;
//    
//    char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)

    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
//    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

//    BOOL patchNeeded = ([_token length] > kCCKeySizeAES256);
//    NSLog(@"need patch? %@", patchNeeded ? @"YES": @"NO");
//    
//    if (patchNeeded) {
//        key = [_token substringToIndex:kCCKeySizeAES256]; // Ensure that the key isn't longer than what's needed (kCCKeySizeAES256)
//    }

    // fetch key data
//    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding];

//    if (patchNeeded) {
//        // Previous iOS version than iOS7 set the first char to '\0' if the key was longer than kCCKeySizeAES256
//        keyPtr[0] = '\0';  
//    }

    size_t dataLength   = [data length] - kCCBlockSizeAES128;
    NSData *iv          = [data subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)];
    NSData *encrypted   = [data subdataWithRange:NSMakeRange(kCCBlockSizeAES128, dataLength)];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
//    size_t bufferSize = dataLength + kCCBlockSizeAES128;
//    void *buffer = malloc(dataLength);
    NSMutableData *ret = [NSMutableData dataWithLength:dataLength + kCCBlockSizeAES128];

    size_t numBytesDecrypted = 0;
    CCCryptorStatus status = CCCrypt(kCCDecrypt, kCCAlgorithmAES,
                                          kCCOptionPKCS7Padding,
                                          [key bytes],
                                          kCCKeySizeAES256,
                                          [iv bytes],
                                          [encrypted bytes], dataLength, /* input */
                                          [ret mutableBytes], [ret length], /* output */
                                          &numBytesDecrypted
                                          );

    NSLog(@"err: %d", status);
    NSLog(@"dataLength: %d, num: %d", (int)dataLength, (int)numBytesDecrypted);
    if (status == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return ret;
    }

//    free(buffer); //free the buffer;
    return nil;
}
Was it helpful?

Solution

it turns out the problem is with the decryption option:

CCCryptorStatus status = CCCrypt(kCCDecrypt, kCCAlgorithmAES,
                                          0, // change to 0 solve the problem
                                          [key bytes],
                                          kCCKeySizeAES256,
                                          [iv bytes],
                                          [encrypted bytes], dataLength, /* input */
                                          [ret mutableBytes], [ret length], /* output */
                                          &numBytesDecrypted
                                          );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top