blob: 41cc01c8067a453b1722fee53f0b579488dca2e4 [file] [log] [blame]
// 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.
//
////////////////////////////////////////////////////////////////////////////////
goog.module('tink.UtilTest');
goog.setTestOnly('tink.UtilTest');
const EllipticCurves = goog.require('tink.subtle.EllipticCurves');
const Util = goog.require('tink.Util');
const {PbEllipticCurveType, PbHashType, PbKeyData, PbKeyStatusType, PbKeyset, PbOutputPrefixType, PbPointFormat} = goog.require('google3.third_party.tink.javascript.internal.proto');
////////////////////////////////////////////////////////////////////////////////
// tests
////////////////////////////////////////////////////////////////////////////////
describe('util test', function() {
// tests for validateKey method
it('validate key missing key data', async function() {
const key = createKey().setKeyData(null);
try {
await Util.validateKey(key);
} catch (e) {
expect(e.toString())
.toBe(ExceptionText.InvalidKeyMissingKeyData(key.getKeyId()));
return;
}
fail('An exception should be thrown.');
});
it('validate key unknown prefix', async function() {
const key =
createKey().setOutputPrefixType(PbOutputPrefixType.UNKNOWN_PREFIX);
try {
await Util.validateKey(key);
} catch (e) {
expect(e.toString())
.toBe(ExceptionText.InvalidKeyUnknownPrefix(key.getKeyId()));
return;
}
fail('An exception should be thrown.');
});
it('validate key unknown status', async function() {
const key = createKey().setStatus(PbKeyStatusType.UNKNOWN_STATUS);
try {
await Util.validateKey(key);
} catch (e) {
expect(e.toString())
.toBe(ExceptionText.InvalidKeyUnknownStatus(key.getKeyId()));
return;
}
fail('An exception should be thrown.');
});
it('validate key valid keys', async function() {
await Util.validateKey(createKey());
await Util.validateKey(
createKey(/* opt_keyId = */ 0xAABBCCDD, /* opt_enabled = */ true));
await Util.validateKey(
createKey(/* opt_keyId = */ 0xABCDABCD, /* opt_enabled = */ false));
});
// tests for validateKeyset method
it('validate keyset without keys', async function() {
const keyset = new PbKeyset();
try {
await Util.validateKeyset(keyset);
} catch (e) {
expect(e.toString()).toBe(ExceptionText.InvalidKeysetMissingKeys());
return;
}
fail('An exception should be thrown.');
});
it('validate keyset disabled primary', async function() {
const keyset = createKeyset();
keyset.addKey(
createKey(/* opt_id = */ 0xFFFFFFFF, /* opt_enabled = */ false));
keyset.setPrimaryKeyId(0xFFFFFFFF);
try {
await Util.validateKeyset(keyset);
} catch (e) {
expect(e.toString()).toBe(ExceptionText.InvalidKeysetDisabledPrimary());
return;
}
fail('An exception should be thrown.');
});
it('validate keyset multiple primaries', async function() {
const keyset = createKeyset();
const key =
createKey(/* opt_id = */ 0xFFFFFFFF, /* opt_enabled = */ true);
keyset.addKey(key);
keyset.addKey(key);
keyset.setPrimaryKeyId(0xFFFFFFFF);
try {
await Util.validateKeyset(keyset);
} catch (e) {
expect(e.toString()).toBe(ExceptionText.InvalidKeysetMultiplePrimaries());
return;
}
fail('An exception should be thrown.');
});
it('validate keyset with invalid key', async function() {
const keyset = createKeyset();
const key =
createKey(4294967295, true).setStatus(PbKeyStatusType.UNKNOWN_STATUS);
keyset.addKey(key);
try {
await Util.validateKeyset(keyset);
} catch (e) {
expect(e.toString())
.toBe(ExceptionText.InvalidKeyUnknownStatus(key.getKeyId()));
return;
}
fail('An exception should be thrown.');
});
it('validate keyset with valid keyset', async function() {
const keyset = createKeyset();
await Util.validateKeyset(keyset);
});
// tests for protoToSubtle methods
it('curve type proto to subtle', function() {
expect(Util.curveTypeProtoToSubtle(PbEllipticCurveType.NIST_P256))
.toBe(EllipticCurves.CurveType.P256);
expect(Util.curveTypeProtoToSubtle(PbEllipticCurveType.NIST_P384))
.toBe(EllipticCurves.CurveType.P384);
expect(Util.curveTypeProtoToSubtle(PbEllipticCurveType.NIST_P521))
.toBe(EllipticCurves.CurveType.P521);
});
it('point format proto to subtle', function() {
expect(Util.pointFormatProtoToSubtle(PbPointFormat.UNCOMPRESSED))
.toBe(EllipticCurves.PointFormatType.UNCOMPRESSED);
expect(Util.pointFormatProtoToSubtle(PbPointFormat.COMPRESSED))
.toBe(EllipticCurves.PointFormatType.COMPRESSED);
expect(Util.pointFormatProtoToSubtle(
PbPointFormat.DO_NOT_USE_CRUNCHY_UNCOMPRESSED))
.toBe(EllipticCurves.PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED);
});
it('hash type proto to string', function() {
expect(Util.hashTypeProtoToString(PbHashType.SHA1)).toBe('SHA-1');
expect(Util.hashTypeProtoToString(PbHashType.SHA256)).toBe('SHA-256');
expect(Util.hashTypeProtoToString(PbHashType.SHA512)).toBe('SHA-512');
});
});
/**
* Class which holds texts for each type of exception.
* @final
*/
class ExceptionText {
// Exceptions for invalid keys.
/**
* @param {number} keyId
*
* @return {string}
*/
static InvalidKeyMissingKeyData(keyId) {
return 'SecurityException: Key data are missing for key ' + keyId + '.';
}
/**
* @param {number} keyId
*
* @return {string}
*/
static InvalidKeyUnknownPrefix(keyId) {
return 'SecurityException: Key ' + keyId +
' has unknown output prefix type.';
}
/**
* @param {number} keyId
*
* @return {string}
*/
static InvalidKeyUnknownStatus(keyId) {
return 'SecurityException: Key ' + keyId + ' has unknown status.';
}
// Exceptions for invalid keysets.
/** @return {string} */
static InvalidKeysetMissingKeys() {
return 'SecurityException: Keyset should be non null and ' +
'must contain at least one key.';
}
/** @return {string} */
static InvalidKeysetDisabledPrimary() {
return 'SecurityException: Primary key has to be in the keyset and ' +
'has to be enabled.';
}
/** @return {string} */
static InvalidKeysetMultiplePrimaries() {
return 'SecurityException: Primary key has to be unique.';
}
}
/**
* Returns a valid PbKeyset.Key.
*
* @param {number=} opt_id
* @param {boolean=} opt_enabled
* @param {boolean=} opt_publicKey
*
* @return {!PbKeyset.Key}
*/
const createKey = function(
opt_id = 0x12345678, opt_enabled = true, opt_publicKey = false) {
const keyData =
new PbKeyData().setTypeUrl('someTypeUrl').setValue(new Uint8Array(10));
if (opt_publicKey) {
keyData.setKeyMaterialType(PbKeyData.KeyMaterialType.ASYMMETRIC_PUBLIC);
} else {
keyData.setKeyMaterialType(PbKeyData.KeyMaterialType.SYMMETRIC);
}
const key = new PbKeyset.Key().setKeyData(keyData);
if (opt_enabled) {
key.setStatus(PbKeyStatusType.ENABLED);
} else {
key.setStatus(PbKeyStatusType.DISABLED);
}
key.setKeyId(opt_id);
key.setOutputPrefixType(PbOutputPrefixType.TINK);
return key;
};
/**
* Returns a valid PbKeyset which primary has id equal to 1.
*
* @return {!PbKeyset}
*/
const createKeyset = function() {
const numberOfKeys = 20;
const keyset = new PbKeyset();
for (let i = 0; i < numberOfKeys; i++) {
// Key id is never set to 0 as primaryKeyId = 0 if it is unset.
const key = createKey(i + 1, /* opt_enabled = */ (i % 2) < 1, (i % 4) < 2);
keyset.addKey(key);
}
keyset.setPrimaryKeyId(1);
return keyset;
};