/*
 * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
 * available under the terms of the MIT License. See the LICENSE file in the project root for more information.
 */

package com.microsoft.sqlserver.jdbc;

import static java.nio.charset.StandardCharsets.UTF_16LE;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;


Encryption key class which consist of following 4 keys : 1) root key - Main key which is used to derive following keys 2) encryption key - A derived key that is used to encrypt the plain text and generate cipher text 3) mac_key - A derived key that is used to compute HMAC of the cipher text 4) iv_key - A derived key that is used to generate a synthetic IV from plain text data.
/** * Encryption key class which consist of following 4 keys : 1) root key - Main key which is used to derive following * keys 2) encryption key - A derived key that is used to encrypt the plain text and generate cipher text 3) mac_key - A * derived key that is used to compute HMAC of the cipher text 4) iv_key - A derived key that is used to generate a * synthetic IV from plain text data. */
class SQLServerAeadAes256CbcHmac256EncryptionKey extends SQLServerSymmetricKey { // This is the key size in the bits, since we are using AES256, it will 256 static final int keySize = 256; // Name of algorithm associated with this key private final String algorithmName; // Salt used to derive encryption key private String encryptionKeySaltFormat; // Salt used to derive mac key private String macKeySaltFormat; // Salt used to derive iv key private String ivKeySaltFormat; private SQLServerSymmetricKey encryptionKey; private SQLServerSymmetricKey macKey; private SQLServerSymmetricKey ivKey;
Derive all the keys from the root key
Params:
  • rootKey – key used to derive other keys
  • algorithmName – name of the algorithm associated with keys
Throws:
/** * Derive all the keys from the root key * * @param rootKey * key used to derive other keys * @param algorithmName * name of the algorithm associated with keys * @throws SQLServerException */
SQLServerAeadAes256CbcHmac256EncryptionKey(byte[] rootKey, String algorithmName) throws SQLServerException { super(rootKey); this.algorithmName = algorithmName; encryptionKeySaltFormat = "Microsoft SQL Server cell encryption key with encryption algorithm:" + this.algorithmName + " and key length:" + keySize; macKeySaltFormat = "Microsoft SQL Server cell MAC key with encryption algorithm:" + this.algorithmName + " and key length:" + keySize; ivKeySaltFormat = "Microsoft SQL Server cell IV key with encryption algorithm:" + this.algorithmName + " and key length:" + keySize; int keySizeInBytes = (keySize / 8); if (rootKey.length != keySizeInBytes) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidKeySize")); Object[] msgArgs = {rootKey.length, keySizeInBytes, this.algorithmName}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } // Derive encryption key byte[] encKeyBuff = new byte[keySizeInBytes]; try { // By default Java is big endian, we are getting bytes in little endian(LE in UTF-16LE) // to make it compatible with C# driver which is little endian encKeyBuff = SQLServerSecurityUtility.getHMACWithSHA256(encryptionKeySaltFormat.getBytes(UTF_16LE), rootKey, encKeyBuff.length); encryptionKey = new SQLServerSymmetricKey(encKeyBuff); // Derive mac key from root key byte[] macKeyBuff = new byte[keySizeInBytes]; macKeyBuff = SQLServerSecurityUtility.getHMACWithSHA256(macKeySaltFormat.getBytes(UTF_16LE), rootKey, macKeyBuff.length); macKey = new SQLServerSymmetricKey(macKeyBuff); // Derive the initialization vector from root key byte[] ivKeyBuff = new byte[keySizeInBytes]; ivKeyBuff = SQLServerSecurityUtility.getHMACWithSHA256(ivKeySaltFormat.getBytes(UTF_16LE), rootKey, ivKeyBuff.length); ivKey = new SQLServerSymmetricKey(ivKeyBuff); } catch (InvalidKeyException | NoSuchAlgorithmException e) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_KeyExtractionFailed")); Object[] msgArgs = {e.getMessage()}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } }
Returns:encryption key
/** * * @return encryption key */
byte[] getEncryptionKey() { return encryptionKey.getRootKey(); }
Returns:mac key
/** * * @return mac key */
byte[] getMacKey() { return macKey.getRootKey(); }
Returns:iv key
/** * * @return iv key */
byte[] getIVKey() { return ivKey.getRootKey(); } }