Skip to content
Snippets Groups Projects
crypto_format.js 3.92 KiB
Newer Older
thaidn's avatar
thaidn committed
// 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.CryptoFormat');

const InvalidArgumentsException = goog.require('tink.exception.InvalidArgumentsException');
const PbKeyset = goog.require('proto.google.crypto.tink.Keyset');
const PbOutputPrefixType = goog.require('proto.google.crypto.tink.OutputPrefixType');
const SecurityException = goog.require('tink.exception.SecurityException');

/**
 * Constants and methods that deal with the format of the outputs handled by
 * Tink.
 *
 * @static
 * @final
 */
class CryptoFormat {
  /**
   * Generates the prefix for the outputs handled by the given 'key'.
   * Throws an exception if the prefix type of 'key' is invalid.
   *
   * @param {PbKeyset.Key} key
   *
   * @return {!Uint8Array}
   */
  static getOutputPrefix(key) {
    switch (key.getOutputPrefixType()) {
      case PbOutputPrefixType.LEGACY: // fall through
      case PbOutputPrefixType.CRUNCHY:
        return CryptoFormat.makeOutputPrefix_(
            key.getKeyId(), CryptoFormat.LEGACY_START_BYTE);
      case PbOutputPrefixType.TINK:
        return CryptoFormat.makeOutputPrefix_(
            key.getKeyId(), CryptoFormat.TINK_START_BYTE);
      case PbOutputPrefixType.RAW:
        return CryptoFormat.RAW_PREFIX;
      default:
        throw new SecurityException('Unsupported key prefix type.');
    }
  }

  /**
   * Makes output prefix which consits of 4 bytes of key id in Big Endian
   * representation followed by 1 byte of key type identifier.
   *
   * @static
   * @private
   * @param {number} keyId
   * @param {number} keyTypeIdentifier
   *
   * @return {!Uint8Array}
   */
  static makeOutputPrefix_(keyId, keyTypeIdentifier) {
    let /** Array */ res = [keyTypeIdentifier];
    res = res.concat(CryptoFormat.numberAsBigEndian_(keyId));
    return new Uint8Array(res);
  }


  /**
   * Returns the given number as Uint8Array in Big Endian format.
   *
   * Given number has to be a non-negative integer smaller than 2^32.
   *
   * @static
   * @private
   * @param {number} n
   *
   * @return {!Array}
   */
  static numberAsBigEndian_(n) {
    if (!Number.isInteger(n) || n < 0 || n >= 2**32) {
      throw new InvalidArgumentsException(
          'Number has to be unsigned 32-bit integer.');
    }
    const numberOfBytes = 4;
    let res = new Array(numberOfBytes);
    for (let i = 0; i < numberOfBytes; i++) {
      res[i] = 0xFF & (n >> 8 * (numberOfBytes - i - 1));
    }
    return res;
  }
}

/**
 * Prefix size of Tink and Legacy key types.
 * @const @static {number}
 */
CryptoFormat.NON_RAW_PREFIX_SIZE = 5;

/**
 * Prefix size of Legacy key types.
 * @const @static {number}
 */
CryptoFormat.LEGACY_PREFIX_SIZE = CryptoFormat.NON_RAW_PREFIX_SIZE;
/**
 * Legacy starts with 0 and is followed by 4-byte key id.
 * @const @static {number}
 */
CryptoFormat.LEGACY_START_BYTE = 0x00;

/**
 * Prefix size of Tink key types.
 * @const @static {number}
 */
CryptoFormat.TINK_PREFIX_SIZE = CryptoFormat.NON_RAW_PREFIX_SIZE;
/**
 * Tink starts with 1 and is followed by 4-byte key id.
 * @const @static {number}
 */
CryptoFormat.TINK_START_BYTE = 0x01;

/**
 * Raw prefix should have length 0.
 * @const @static {number}
 */
CryptoFormat.RAW_PREFIX_SIZE = 0;
/**
 * Raw prefix is empty Uint8Array.
 * @const @static
 * @type {!Uint8Array}
 */
CryptoFormat.RAW_PREFIX = new Uint8Array(0);

goog.exportSymbol('tink.CryptoFormat', CryptoFormat);
thaidn's avatar
thaidn committed
exports = CryptoFormat;