0

使用 java 加密似乎比使用 Tink 的 obj-c 简单得多。给定一个已知的 32 字节XChaCha20Poly1305 key和一个 16 字节的认证数据(aad),如何在 Objective-c 中完成相同的操作?

爪哇

    import com.google.crypto.tink.subtle.XChaCha20Poly1305;

    XChaCha20Poly1305 xChaCha20Poly1305 = new XChaCha20Poly1305(key);
    byte[] encryptedData = xChaCha20Poly1305.encrypt(plainData, aad);
4

1 回答 1

0

长话短说,以下 java 和 obj-c 代码一起工作。

爪哇:

        import com.google.crypto.tink.aead.AeadConfig;
        import com.google.crypto.tink.*;

        byte[] plainData = ...
        byte[] key = ...//32 bytes
        byte[] aad = ...
        AeadConfig.register();
        byte[] preffix = {0x1a,0x20};
        byte[] fullKey = new byte[preffix.length + key.length];
        System.arraycopy(preffix, 0, fullKey, 0, preffix.length);
        System.arraycopy(key, 0, fullKey, preffix.length, key.length);
        String fullKeyBase64 = new String(com.groups.network.aes.Base64.encode(fullKey), "UTF-8");
        String jsonKey = "{\"primaryKeyId\":1635322858,\"key\":[{\"keyData\":{\"typeUrl\":\"type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key\",\"value\":\""+fullKeyBase64+"\",\"keyMaterialType\":\"SYMMETRIC\"},\"status\":\"ENABLED\",\"keyId\":1635322858,\"outputPrefixType\":\"TINK\"}]}";
        KeysetHandle keysetHandle = CleartextKeysetHandle.read(
                JsonKeysetReader.withString(jsonKey));
        Aead aead = keysetHandle.getPrimitive(Aead.class);
        byte[] encrypted =  aead.encrypt(plainData, aad);

目标 C:

    NSData* encryptedBytes = ...
    NSData* aad = ...
    NSData* key = ...//32-bytes
    NSError *error = nil;
    TINKAeadConfig *aeadConfig = [[TINKAeadConfig alloc] initWithError:&error];
    if (!aeadConfig || error) {
        //handle error
    }
    if (![TINKConfig registerConfig:aeadConfig error:&error]) {
        //handle error
    }
    NSString* preffix = @"1a20";
    NSMutableData* preffixData = [[NSMutableData alloc] init];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i;
    for(i=0; i<[preffix length]/2;i++){
        byte_chars[0] = [preffix characterAtIndex:i*2];
        byte_chars[1] = [preffix characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [preffixData appendBytes:&whole_byte length:1];
    }
    NSData* originalKeyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableData* finalKey = [preffixData mutableCopy];
    [finalKey appendData:originalKeyData];
    NSString* jsonTmp = [NSString stringWithFormat:@"{\"primaryKeyId\":1635322858,\"key\":[{\"keyData\":{\"typeUrl\":\"type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key\",\"value\":\"%@\",\"keyMaterialType\":\"SYMMETRIC\"},\"status\":\"ENABLED\",\"keyId\":1635322858,\"outputPrefixType\":\"TINK\"}]}", [finalKey base64Encoding]];
    NSData* jsonKeyData = [jsonTmp dataUsingEncoding:NSUTF8StringEncoding];
    TINKJSONKeysetReader *reader = [[TINKJSONKeysetReader alloc] initWithSerializedKeyset:jsonKeyData error:&error];
    if (!reader || error) {
        //handle error
    }
    TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initCleartextKeysetHandleWithKeysetReader:reader error:&error];
    if (!handle || error) {
        //handle error
    }
    id<TINKAead> aead = [TINKAeadFactory primitiveWithKeysetHandle:handle error:&error];
    if (!aead || error) {
        //handle error
    }
    NSData *aadData = [aad dataUsingEncoding:NSUTF8StringEncoding];
    NSData *plaintext = [aead decrypt:encryptedBytes withAdditionalData:aadData error:&error];
    if (!plaintext || error) {
        //handle error
    }

注意 {0x1a,0x20}。这会根据您使用的加密类型而变化(这里适用于 XChacha20-Poly1305)。这可以用Tinkey工具“发现”,如果你运行类似java -jar tinkey_deploy.jar create-keyset --key-template XCHACHA20_POLY1305的东西,它会输出一个 JSON 密钥模板(输出 base64 密钥需要然后转换为字节,你需要确定前 2 个字节对应于哪个加密)

于 2021-08-12T15:23:38.240 回答