blob: 7137cb389276490e4dd300d24c62e64d0cfe4ce0 [file] [log] [blame]
/**
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**************************************************************************
*/
#import <XCTest/XCTest.h>
#include "tink/crypto_format.h"
#include "tink/util/status.h"
#include "tink/util/keyset_util.h"
#import "proto/EciesAeadHkdf.pbobjc.h"
#import "proto/Tink.pbobjc.h"
#import "objc/TINKConfig.h"
#import "objc/TINKHybridConfig.h"
#import "objc/TINKHybridDecrypt.h"
#import "objc/TINKHybridDecryptFactory.h"
#import "objc/TINKHybridEncrypt.h"
#import "objc/TINKHybridEncryptFactory.h"
#import "objc/TINKKeysetHandle.h"
#import "objc/core/TINKKeysetHandle_Internal.h"
#import "objc/util/TINKStrings.h"
#import "objc/util/TINKTestHelpers.h"
using crypto::tink::KeysetUtil;
@interface TINKHybridDecryptFactoryTest : XCTestCase
@end
static TINKPBEciesAeadHkdfPrivateKey *getNewEciesPrivateKey() {
return TINKGetEciesAesGcmHkdfTestKey(TINKPBEllipticCurveType_NistP256,
TINKPBEcPointFormat_Uncompressed, TINKPBHashType_Sha256, 32);
}
@implementation TINKHybridDecryptFactoryTest
- (void)testEncryptWith:(TINKPBKeyset *)publicKeyset andDecryptWith:(TINKPBKeyset *)privateKeyset {
NSError *error = nil;
std::string serializedKeyset = TINKPBSerializeToString(privateKeyset, &error);
XCTAssertNil(error);
google::crypto::tink::Keyset ccPrivateKeyset;
XCTAssertTrue(ccPrivateKeyset.ParseFromString(serializedKeyset));
TINKKeysetHandle *privateKeysetHandle = [[TINKKeysetHandle alloc]
initWithCCKeysetHandle:KeysetUtil::GetKeysetHandle(ccPrivateKeyset)];
error = nil;
serializedKeyset = TINKPBSerializeToString(publicKeyset, &error);
XCTAssertNil(error);
google::crypto::tink::Keyset ccPublicKeyset;
XCTAssertTrue(ccPublicKeyset.ParseFromString(serializedKeyset));
TINKKeysetHandle *publicKeysetHandle = [[TINKKeysetHandle alloc]
initWithCCKeysetHandle:KeysetUtil::GetKeysetHandle(ccPublicKeyset)];
// Get a HybridDecrypt primitive.
error = nil;
id<TINKHybridDecrypt> hybridDecrypt =
[TINKHybridDecryptFactory primitiveWithKeysetHandle:privateKeysetHandle error:&error];
XCTAssertNotNil(hybridDecrypt);
XCTAssertNil(error);
// Get a HybridEncrypt primitive.
error = nil;
id<TINKHybridEncrypt> primitive =
[TINKHybridEncryptFactory primitiveWithKeysetHandle:publicKeysetHandle error:&error];
XCTAssertNotNil(primitive);
XCTAssertNil(error);
NSData *const plaintext = [@"some plaintext" dataUsingEncoding:NSUTF8StringEncoding];
NSData *const context = [@"some context info" dataUsingEncoding:NSUTF8StringEncoding];
// Encrypt.
error = nil;
NSData *ciphertext = [primitive encrypt:plaintext withContextInfo:context error:&error];
XCTAssertNil(error);
XCTAssertNotNil(ciphertext);
// Decrypt.
error = nil;
NSData *result = [hybridDecrypt decrypt:ciphertext withContextInfo:context error:&error];
XCTAssertNil(error);
XCTAssertNotNil(result);
XCTAssertTrue([result isEqualToData:plaintext]);
}
- (void)testPrimitiveWithEmptyKeyset {
google::crypto::tink::Keyset keyset;
TINKKeysetHandle *keysetHandle =
[[TINKKeysetHandle alloc] initWithCCKeysetHandle:KeysetUtil::GetKeysetHandle(keyset)];
XCTAssertNotNil(keysetHandle);
NSError *error = nil;
id<TINKHybridDecrypt> primitive =
[TINKHybridDecryptFactory primitiveWithKeysetHandle:keysetHandle error:&error];
XCTAssertNil(primitive);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, crypto::tink::util::error::INVALID_ARGUMENT);
NSDictionary *userInfo = [error userInfo];
NSString *errorString = [userInfo objectForKey:NSLocalizedFailureReasonErrorKey];
XCTAssertTrue([errorString containsString:@"at least one key"]);
}
- (void)testPrimitiveWithKeyset {
NSError *error = nil;
TINKHybridConfig *hybridConfig = [[TINKHybridConfig alloc] initWithError:&error];
XCTAssertNotNil(hybridConfig);
XCTAssertNil(error);
XCTAssertTrue([TINKConfig registerConfig:hybridConfig error:&error]);
XCTAssertNil(error);
uint32_t keyId1 = 1;
uint32_t keyId2 = 2;
uint32_t keyId3 = 3;
TINKPBEciesAeadHkdfPrivateKey *eciesKey1 = getNewEciesPrivateKey();
TINKPBEciesAeadHkdfPrivateKey *eciesKey2 = getNewEciesPrivateKey();
TINKPBEciesAeadHkdfPrivateKey *eciesKey3 = getNewEciesPrivateKey();
NSString *privateKeyType = @"type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey";
TINKPBKeyset_Key *tinkPrivateKey =
TINKCreateKey(privateKeyType, keyId1, eciesKey1, TINKPBOutputPrefixType_Tink,
TINKPBKeyStatusType_Enabled, TINKPBKeyData_KeyMaterialType_AsymmetricPrivate);
TINKPBKeyset_Key *rawPrivateKey =
TINKCreateKey(privateKeyType, keyId2, eciesKey2, TINKPBOutputPrefixType_Raw,
TINKPBKeyStatusType_Enabled, TINKPBKeyData_KeyMaterialType_AsymmetricPrivate);
TINKPBKeyset_Key *legacyPrivateKey =
TINKCreateKey(privateKeyType, keyId3, eciesKey3, TINKPBOutputPrefixType_Legacy,
TINKPBKeyStatusType_Enabled, TINKPBKeyData_KeyMaterialType_AsymmetricPrivate);
NSString *publicKeyType = @"type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey";
TINKPBKeyset_Key *tinkPublicKey =
TINKCreateKey(publicKeyType, keyId1, eciesKey1.publicKey, TINKPBOutputPrefixType_Tink,
TINKPBKeyStatusType_Enabled, TINKPBKeyData_KeyMaterialType_AsymmetricPublic);
TINKPBKeyset_Key *rawPublicKey =
TINKCreateKey(publicKeyType, keyId2, eciesKey2.publicKey, TINKPBOutputPrefixType_Raw,
TINKPBKeyStatusType_Enabled, TINKPBKeyData_KeyMaterialType_AsymmetricPublic);
TINKPBKeyset_Key *legacyPublicKey =
TINKCreateKey(publicKeyType, keyId3, eciesKey3.publicKey, TINKPBOutputPrefixType_Legacy,
TINKPBKeyStatusType_Enabled, TINKPBKeyData_KeyMaterialType_AsymmetricPublic);
// Encrypt with tink and decrypt with tink.
TINKPBKeyset *privateKeyset = TINKCreateKeyset(tinkPrivateKey, rawPrivateKey, legacyPrivateKey);
TINKPBKeyset *publicKeyset = TINKCreateKeyset(tinkPublicKey, rawPublicKey, legacyPublicKey);
[self testEncryptWith:publicKeyset andDecryptWith:privateKeyset];
// Encrypt with raw and decrypt with raw.
privateKeyset = TINKCreateKeyset(rawPrivateKey, tinkPrivateKey, legacyPrivateKey);
publicKeyset = TINKCreateKeyset(rawPublicKey, tinkPublicKey, legacyPublicKey);
[self testEncryptWith:publicKeyset andDecryptWith:privateKeyset];
// Encrypt with legacy and decrypt with legacy
privateKeyset = TINKCreateKeyset(legacyPrivateKey, tinkPrivateKey, rawPrivateKey);
publicKeyset = TINKCreateKeyset(legacyPublicKey, tinkPublicKey, rawPublicKey);
[self testEncryptWith:publicKeyset andDecryptWith:privateKeyset];
// Encrypt with tink as primary, decrypt with raw as primary.
publicKeyset = TINKCreateKeyset(tinkPublicKey, legacyPublicKey, rawPublicKey);
privateKeyset = TINKCreateKeyset(rawPrivateKey, tinkPrivateKey, legacyPrivateKey);
[self testEncryptWith:publicKeyset andDecryptWith:privateKeyset];
// Encrypt with raw as primary, decrypt with tink as primary.
publicKeyset = TINKCreateKeyset(rawPublicKey, tinkPublicKey, legacyPublicKey);
privateKeyset = TINKCreateKeyset(tinkPrivateKey, rawPrivateKey, legacyPrivateKey);
[self testEncryptWith:publicKeyset andDecryptWith:privateKeyset];
}
@end