com.microsoft.azure.keyvault.extensions.KeyVaultKey.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.azure.keyvault.extensions.KeyVaultKey.java

Source

/**
 *
 * Copyright (c) Microsoft and contributors.  All rights reserved.
 *
 * 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.
 *
 */

package com.microsoft.azure.keyvault.extensions;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;

import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.microsoft.azure.keyvault.KeyVaultClient;
import com.microsoft.azure.keyvault.core.IKey;
import com.microsoft.azure.keyvault.cryptography.RsaKey;
import com.microsoft.azure.keyvault.webkey.JsonWebKey;
import com.microsoft.azure.keyvault.webkey.JsonWebKeyEncryptionAlgorithm;
import com.microsoft.azure.keyvault.webkey.JsonWebKeySignatureAlgorithm;
import com.microsoft.azure.keyvault.models.KeyBundle;
import com.microsoft.azure.keyvault.models.KeyOperationResult;
import com.microsoft.azure.keyvault.webkey.JsonWebKeyType;

/**
 * The key vault key that performs cryptography operations.
 */
public class KeyVaultKey implements IKey {

    /**
     * Transforms the result of decrypt operation to byte array.
     */
    class DecryptResultTransform implements Function<KeyOperationResult, byte[]> {

        DecryptResultTransform() {
            super();
        }

        @Override
        public byte[] apply(KeyOperationResult result) {
            return result.result();
        }
    }

    /**
     * Transforms the result of sign operation to byte array and algorithm pair.
     */
    class SignResultTransform implements Function<KeyOperationResult, Pair<byte[], String>> {

        private final String algorithm;

        SignResultTransform(String algorithm) {
            super();
            this.algorithm = algorithm;
        }

        @Override
        public Pair<byte[], String> apply(KeyOperationResult input) {

            return Pair.of(input.result(), algorithm);
        }
    }

    private final KeyVaultClient client;
    private IKey implementation;

    protected KeyVaultKey(KeyVaultClient client, KeyBundle keyBundle) {

        if (client == null) {
            throw new IllegalArgumentException("client");
        }

        if (keyBundle == null) {
            throw new IllegalArgumentException("keyBundle");
        }

        JsonWebKey key = keyBundle.key();

        if (key == null) {
            throw new IllegalArgumentException("keyBundle must contain a key");
        }

        if (key.kty().equals(JsonWebKeyType.RSA)) {
            // The private key is not available for KeyVault keys
            implementation = new RsaKey(key.kid(), key.toRSA(false));
        } else if (key.kty().equals(JsonWebKeyType.RSA_HSM)) {
            // The private key is not available for KeyVault keys
            implementation = new RsaKey(key.kid(), key.toRSA(false));
        }

        if (implementation == null) {
            throw new IllegalArgumentException(String.format("The key type %s is not supported", key.kty()));
        }

        this.client = client;
    }

    @Override
    public void close() throws IOException {
        if (implementation != null) {
            implementation.close();
        }
    }

    @Override
    public String getDefaultEncryptionAlgorithm() {
        if (implementation == null) {
            return null;
        }

        return implementation.getDefaultEncryptionAlgorithm();
    }

    @Override
    public String getDefaultKeyWrapAlgorithm() {

        if (implementation == null) {
            return null;
        }

        return implementation.getDefaultKeyWrapAlgorithm();
    }

    @Override
    public String getDefaultSignatureAlgorithm() {

        if (implementation == null) {
            return null;
        }

        return implementation.getDefaultSignatureAlgorithm();
    }

    @Override
    public String getKid() {

        if (implementation == null) {
            return null;
        }

        return implementation.getKid();
    }

    @Override
    public ListenableFuture<byte[]> decryptAsync(byte[] ciphertext, byte[] iv, byte[] authenticationData,
            byte[] authenticationTag, String algorithm) {

        if (implementation == null) {
            return null;
        }

        if (Strings.isNullOrWhiteSpace(algorithm)) {
            algorithm = getDefaultEncryptionAlgorithm();
        }

        // Never local
        ListenableFuture<KeyOperationResult> futureCall = client.decryptAsync(implementation.getKid(),
                new JsonWebKeyEncryptionAlgorithm(algorithm), ciphertext, null);
        return Futures.transform(futureCall, new DecryptResultTransform());
    }

    @Override
    public ListenableFuture<Triple<byte[], byte[], String>> encryptAsync(byte[] plaintext, byte[] iv,
            byte[] authenticationData, String algorithm) throws NoSuchAlgorithmException {
        if (implementation == null) {
            return null;
        }

        return implementation.encryptAsync(plaintext, iv, authenticationData, algorithm);
    }

    @Override
    public ListenableFuture<Pair<byte[], String>> wrapKeyAsync(byte[] plaintext, String algorithm)
            throws NoSuchAlgorithmException {
        if (implementation == null) {
            return null;
        }

        return implementation.wrapKeyAsync(plaintext, algorithm);
    }

    @Override
    public ListenableFuture<byte[]> unwrapKeyAsync(byte[] ciphertext, String algorithm) {
        if (implementation == null) {
            return null;
        }

        if (Strings.isNullOrWhiteSpace(algorithm)) {
            algorithm = getDefaultKeyWrapAlgorithm();
        }

        // Never local
        ListenableFuture<KeyOperationResult> futureCall = client.unwrapKeyAsync(implementation.getKid(),
                new JsonWebKeyEncryptionAlgorithm(algorithm), ciphertext, null);
        return Futures.transform(futureCall, new DecryptResultTransform());
    }

    @Override
    public ListenableFuture<Pair<byte[], String>> signAsync(byte[] digest, String algorithm)
            throws NoSuchAlgorithmException {
        if (implementation == null) {
            return null;
        }

        if (Strings.isNullOrWhiteSpace(algorithm)) {
            algorithm = getDefaultSignatureAlgorithm();
        }

        // Never local
        ListenableFuture<KeyOperationResult> futureCall = client.signAsync(implementation.getKid(),
                new JsonWebKeySignatureAlgorithm(algorithm), digest, null);
        return Futures.transform(futureCall, new SignResultTransform(algorithm));
    }

    @Override
    public ListenableFuture<Boolean> verifyAsync(byte[] digest, byte[] signature, String algorithm)
            throws NoSuchAlgorithmException {
        if (implementation == null) {
            return null;
        }

        return implementation.verifyAsync(digest, signature, algorithm);
    }
}