diff --git a/.gitignore b/.gitignore
index f1e3d20e0568..9d6304e11c8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,252 +1,56 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
+*.class
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
+#External libs
+extlib/
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
+# Auth files
+*.auth
+*.azureauth
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
+# Local checkstyle
+*.checkstyle
-# Visual Studio 2015 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
+# Package Files #
+*.jar
+*.war
+*.ear
-# NUNIT
-*.VisualState.xml
-TestResult.xml
+# Azure Tooling #
+node_modules
+packages
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# DNX
-project.lock.json
-artifacts/
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
+# Eclipse #
+*.pydevproject
+.project
+.metadata
+bin/**
+tmp/**
+tmp/**/*
*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/packages/*
-# except build/, which is used as an MSBuild target.
-!**/packages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/packages/repositories.config
-# NuGet v3's project.json files produces more ignoreable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.pfx
-*.publishsettings
-node_modules/
-orleans.codegen.cs
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# JetBrains Rider
-.idea/
-*.sln.iml
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+
+# Other Tooling #
+.classpath
+.project
+target
+.idea
+*.iml
+
+# Mac OS #
+.DS_Store
+.DS_Store?
+
+# Windows #
+Thumbs.db
+
+# reduced pom files should not be included
+dependency-reduced-pom.xml
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000000..2cac09f02bfa
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,7 @@
+language: java
+sudo: false
+jdk:
+- oraclejdk8
+script:
+- mvn install -DskipTests=true
+- mvn package javadoc:aggregate -DskipTests=true
\ No newline at end of file
diff --git a/azure-keyvault-core/pom.xml b/azure-keyvault-core/pom.xml
new file mode 100755
index 000000000000..1ae87e1b1176
--- /dev/null
+++ b/azure-keyvault-core/pom.xml
@@ -0,0 +1,104 @@
+
+
+ 4.0.0
+
+ com.microsoft.azure
+ azure-keyvault-parent
+ 1.0.0-beta6-SNAPSHOT
+ ../pom.xml
+
+
+ azure-keyvault-core
+ jar
+
+ Microsoft Azure SDK for Key Vault Core
+ This package contains Microsoft Azure Key Vault Core SDK.
+ https://github.com/Azure/azure-sdk-for-java
+
+
+
+ The MIT License (MIT)
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+
+ scm:git:https://github.com/Azure/azure-sdk-for-java
+ scm:git:git@github.com:Azure/azure-sdk-for-java.git
+ HEAD
+
+
+
+ UTF-8
+
+
+
+
+
+ microsoft
+ Microsoft
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ true
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ 1.7
+ 1.7
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.8
+
+ com.microsoft.schemas._2003._10.serialization
+ /**
+
* Copyright (c) Microsoft Corporation. All rights reserved.
+
* Licensed under the MIT License. See License.txt in the project root for
+
* license information.
+
*/]]>
+
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.4
+
+
+ com.google.guava
+ guava
+ 20.0
+
+
+
diff --git a/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/IKey.java b/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/IKey.java
new file mode 100755
index 000000000000..5eb18bd42677
--- /dev/null
+++ b/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/IKey.java
@@ -0,0 +1,148 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.core;
+
+import java.io.Closeable;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.tuple.Triple;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+
+/**
+ * Interface for representing cryptographic keys with the Microsoft Azure Key
+ * Vault libraries.
+ */
+public interface IKey extends Closeable {
+
+ /**
+ * The default encryption algorithm for this key, using the representations
+ * from Json Web Key Algorithms, RFC7513.
+ *
+ * @return The default encryption algorithm for this key.
+ */
+ String getDefaultEncryptionAlgorithm();
+
+ /**
+ * The default key wrap algorithm for this key, using the representations
+ * from Json Web Key Algorithms, RFC7513.
+ *
+ * @return The default key wrap algorithm for this key.
+ */
+ String getDefaultKeyWrapAlgorithm();
+
+ /**
+ * The default signature algorithm for this key, using the representations
+ * from Json Web Key Algorithms, RFC7513.
+ *
+ * @return The default signature algorithm for this key.
+ */
+ String getDefaultSignatureAlgorithm();
+
+ /**
+ * The unique key identifier for this key.
+ *
+ * @return The key identifier
+ */
+ String getKid();
+
+ /**
+ * Decrypts the specified cipher text. Note that not all algorithms require,
+ * or support, all parameters.
+ *
+ * @param ciphertext
+ * The cipher text to decrypt
+ * @param iv
+ * The initialization vector (optional with some algorithms)
+ * @param authenticationData
+ * Additional authentication data (optional with some algorithms)
+ * @param authenticationTag
+ * The authentication tag from the encrypt operation (optional
+ * with some algorithms)
+ * @param algorithm
+ * The encryption algorithm to use, must be supplied
+ * @return A ListenableFuture containing the plain text
+ * @throws NoSuchAlgorithmException the algorithm is not valid
+ */
+ ListenableFuture decryptAsync(final byte[] ciphertext, final byte[] iv, final byte[] authenticationData, final byte[] authenticationTag, final String algorithm) throws NoSuchAlgorithmException;
+
+ /**
+ * Encrypts the specified plain text. Note that not all algorithms require,
+ * or support, all parameters.
+ *
+ * @param plaintext
+ * The plain text to encrypt
+ * @param iv
+ * The initialization vector (optional with some algorithms)
+ * @param authenticationData
+ * Additional authentication data (optional with some algorithms)
+ * @param algorithm
+ * The encryption algorithm to use, defaults to the keys
+ * DefaultEncryptionAlgorithm
+ * @return A ListenableFuture containing the cipher text, the authentication
+ * tag and the algorithm that was used
+ * @throws NoSuchAlgorithmException the algorithm is not valid
+ */
+ ListenableFuture> encryptAsync(final byte[] plaintext, final byte[] iv, final byte[] authenticationData, final String algorithm) throws NoSuchAlgorithmException;
+
+ /**
+ * Wraps (encrypts) the specified symmetric key material using the specified
+ * algorithm, or the keys DefaultKeyWrapAlgorithm if none is specified.
+ *
+ * @param key
+ * The symmetric key to wrap
+ * @param algorithm
+ * The wrapping algorithm to use, defaults to the keys
+ * DefaultKeyWrapAlgorithm
+ * @return ListenableFuture containing the encrypted key and the algorithm
+ * that was used
+ * @throws NoSuchAlgorithmException the algorithm is not valid
+ */
+ ListenableFuture> wrapKeyAsync(final byte[] key, final String algorithm) throws NoSuchAlgorithmException;
+
+ /**
+ * Unwraps (decrypts) the specified encryped key material.
+ *
+ * @param encryptedKey
+ * The encrypted key to decrypt
+ * @param algorithm
+ * The algorithm to use, must be supplied
+ * @return A ListenableFuture containing the unwrapped key
+ * @throws NoSuchAlgorithmException the algorithm is not valid
+ */
+ ListenableFuture unwrapKeyAsync(final byte[] encryptedKey, final String algorithm) throws NoSuchAlgorithmException;
+
+ /**
+ * Signs the specified digest using the specified algorithm, or the keys
+ * DefaultSignatureAlgorithm if no algorithm is specified.
+ *
+ * @param digest
+ * The digest to sign
+ * @param algorithm
+ * The signature algorithm to use
+ * @return A ListenableFuture containing the signature and the algorithm used.
+ * @throws NoSuchAlgorithmException the algorithm is not valid
+ */
+ ListenableFuture> signAsync(final byte[] digest, final String algorithm) throws NoSuchAlgorithmException;
+
+ /**
+ * Verifies the supplied signature value using the supplied digest and
+ * algorithm.
+ *
+ * @param digest
+ * The digest input
+ * @param signature
+ * The signature to verify
+ * @param algorithm
+ * The algorithm to use, must be provided
+ * @return A ListenableFuture containing the signature and the algorithm used.
+ * @throws NoSuchAlgorithmException the algorithm is not valid
+ */
+ ListenableFuture verifyAsync(final byte[] digest, final byte[] signature, final String algorithm) throws NoSuchAlgorithmException;
+}
diff --git a/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/IKeyResolver.java b/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/IKeyResolver.java
new file mode 100755
index 000000000000..e0b08e9ea200
--- /dev/null
+++ b/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/IKeyResolver.java
@@ -0,0 +1,40 @@
+/**
+ *
+ * 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.core;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Interface for representing key resolving operations with the Microsoft Azure Key
+ * Vault libraries.
+ */
+public interface IKeyResolver {
+
+ /**
+ * Retrieves an IKey implementation for the specified key identifier.
+ * Implementations should check the format of the kid to ensure that it is
+ * recognized. Null, rather than an exception, should be returned for
+ * unrecognized key identifiers to enable chaining of key resolvers.
+ *
+ * @param kid
+ * The key identifier to resolve.
+ * @return A ListenableFuture containing the resolved IKey
+ */
+ ListenableFuture resolveKeyAsync(String kid);
+}
diff --git a/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/package-info.java b/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/package-info.java
new file mode 100755
index 000000000000..b3417f38285d
--- /dev/null
+++ b/azure-keyvault-core/src/main/java/com/microsoft/azure/keyvault/core/package-info.java
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+
+/**
+ * This package contains the interface for IKey and IKeyResolver.
+ */
+package com.microsoft.azure.keyvault.core;
diff --git a/azure-keyvault-cryptography/pom.xml b/azure-keyvault-cryptography/pom.xml
new file mode 100755
index 000000000000..efbdba24c988
--- /dev/null
+++ b/azure-keyvault-cryptography/pom.xml
@@ -0,0 +1,68 @@
+
+
+ 4.0.0
+
+
+ com.microsoft.azure
+ azure-keyvault-parent
+ 1.0.0-beta6-SNAPSHOT
+ ../pom.xml
+
+
+ azure-keyvault-cryptography
+ jar
+
+ Microsoft Azure SDK for Key Vault Cryptography
+ This package contains Microsoft Azure SDK for Key Vault Cryptography.
+ https://github.com/Azure/azure-sdk-for-java
+
+
+
+ The MIT License (MIT)
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+
+ scm:git:https://github.com/Azure/azure-sdk-for-java
+ scm:git:git@github.com:Azure/azure-sdk-for-java.git
+ HEAD
+
+
+
+ UTF-8
+
+
+ true
+
+
+
+
+
+ junit
+ junit
+ test
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ test
+ 1.54
+
+
+ com.microsoft.azure
+ azure-keyvault-core
+ 1.0.0-beta6-SNAPSHOT
+
+
+ com.microsoft.azure
+ azure-keyvault-webkey
+ 1.0.0-beta6-SNAPSHOT
+
+
+
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/Algorithm.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/Algorithm.java
new file mode 100755
index 000000000000..e80ccaf5a76b
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/Algorithm.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+/**
+ * Abstract base class for all Algorithm objects.
+ *
+ */
+public abstract class Algorithm {
+
+ private final String _name;
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the algorithm.
+ */
+ protected Algorithm(String name) {
+ if (Strings.isNullOrWhiteSpace(name)) {
+ throw new IllegalArgumentException("name");
+ }
+
+ _name = name;
+ }
+
+ /**
+ * Gets the name of the algorithm.
+ *
+ * @return The name of the algorithm.
+ */
+ public String getName() {
+ return _name;
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AlgorithmResolver.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AlgorithmResolver.java
new file mode 100755
index 000000000000..60930c8d1e3a
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AlgorithmResolver.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes128Cbc;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes128CbcHmacSha256;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes192Cbc;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes192CbcHmacSha384;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes256Cbc;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes256CbcHmacSha512;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw128;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw192;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw256;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Rs256;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Rsa15;
+import com.microsoft.azure.keyvault.cryptography.algorithms.RsaOaep;
+
+public class AlgorithmResolver {
+
+ public static final AlgorithmResolver Default = new AlgorithmResolver();
+
+ static {
+ Default.put(Aes128CbcHmacSha256.ALGORITHM_NAME, new Aes128CbcHmacSha256());
+ Default.put(Aes192CbcHmacSha384.ALGORITHM_NAME, new Aes192CbcHmacSha384());
+ Default.put(Aes256CbcHmacSha512.ALGORITHM_NAME, new Aes256CbcHmacSha512());
+
+ Default.put(Aes128Cbc.ALGORITHM_NAME, new Aes128Cbc());
+ Default.put(Aes192Cbc.ALGORITHM_NAME, new Aes192Cbc());
+ Default.put(Aes256Cbc.ALGORITHM_NAME, new Aes256Cbc());
+
+ Default.put(AesKw128.ALGORITHM_NAME, new AesKw128());
+ Default.put(AesKw192.ALGORITHM_NAME, new AesKw192());
+ Default.put(AesKw256.ALGORITHM_NAME, new AesKw256());
+
+ Default.put(Rsa15.ALGORITHM_NAME, new Rsa15());
+ Default.put(RsaOaep.ALGORITHM_NAME, new RsaOaep());
+
+ Default.put( Rs256.ALGORITHM_NAME, new Rs256() );
+ // Default.put( RsNull.ALGORITHM_NAME, new RsNull() );
+ }
+
+ private final ConcurrentMap _algorithms = new ConcurrentHashMap();
+
+ /**
+ * Returns the implementation for an algorithm name.
+ *
+ * @param algorithmName The algorithm name.
+ * @return The implementation for the algorithm or null.
+ */
+ public Algorithm get(String algorithmName) {
+ return _algorithms.get(algorithmName);
+ }
+
+ /**
+ * Add/Update a named algorithm implementation.
+ *
+ * @param algorithmName The algorithm name.
+ * @param provider The implementation of the algorithm.
+ */
+ public void put(String algorithmName, Algorithm provider) {
+ _algorithms.put(algorithmName, provider);
+ }
+
+ /**
+ * Remove a named algorithm implementation.
+ *
+ * @param algorithmName The algorithm name
+ */
+ public void remove(String algorithmName) {
+ _algorithms.remove(algorithmName);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AsymmetricEncryptionAlgorithm.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AsymmetricEncryptionAlgorithm.java
new file mode 100755
index 000000000000..b239a41d8530
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AsymmetricEncryptionAlgorithm.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.NoSuchPaddingException;
+
+/**
+ * Abstract base class for all asymmetric encryption algorithms.
+ *
+ */
+public abstract class AsymmetricEncryptionAlgorithm extends EncryptionAlgorithm {
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the algorithm.
+ */
+ protected AsymmetricEncryptionAlgorithm(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption that
+ * uses the specified {@link java.security.KeyPair} and the default {@link java.security.Provider} provider.
+ *
+ * @param keyPair
+ * The key pair to use.
+ * @return
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ */
+ public abstract ICryptoTransform CreateEncryptor(KeyPair keyPair) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption that
+ * uses the specified {@link java.security.KeyPair} and {@link java.security.Provider}.
+ *
+ * @param keyPair
+ * The key pair to use.
+ * @param provider
+ * The provider to use.
+ * @return
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ */
+ public abstract ICryptoTransform CreateEncryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption that
+ * uses the specified {@link java.security.KeyPair} and the default {@link java.security.Provider} provider.
+ *
+ * @param keyPair
+ * The key pair to use.
+ * @return
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ */
+ public abstract ICryptoTransform CreateDecryptor(KeyPair keyPair) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption that
+ * uses the specified {@link java.security.KeyPair} and {@link java.security.Provider}.
+ *
+ * @param keyPair
+ * The key pair to use.
+ * @param provider
+ * The provider to use.
+ * @return
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ */
+ public abstract ICryptoTransform CreateDecryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException;
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AsymmetricSignatureAlgorithm.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AsymmetricSignatureAlgorithm.java
new file mode 100755
index 000000000000..ff5e1417ba5c
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/AsymmetricSignatureAlgorithm.java
@@ -0,0 +1,15 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+public abstract class AsymmetricSignatureAlgorithm extends SignatureAlgorithm {
+
+ protected AsymmetricSignatureAlgorithm(String name) {
+ super(name);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ByteExtensions.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ByteExtensions.java
new file mode 100644
index 000000000000..07aee9a68949
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ByteExtensions.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.util.Arrays;
+
+public final class ByteExtensions {
+
+ public static byte[] or( byte[] self, byte[] other )
+ {
+ return or( self, other, 0 );
+ }
+
+ public static byte[] or( byte[] self, byte[] other, int offset )
+ {
+ if ( self == null )
+ throw new IllegalArgumentException( "self" );
+
+ if ( other == null )
+ throw new IllegalArgumentException( "other" );
+
+ if ( self.length > other.length - offset )
+ throw new IllegalArgumentException( "self and other lengths do not match" );
+
+ byte[] result = new byte[self.length];
+
+ for ( int i = 0; i < self.length; i++ )
+ {
+ result[i] = (byte)( self[i] | other[offset + i] );
+ }
+
+ return result;
+ }
+
+ public static byte[] xor( byte[] self, byte[] other ) {
+ return xor( self, other, 0 );
+ }
+
+ static byte[] xor( byte[] self, byte[] other, int offset )
+ {
+ if ( self == null )
+ throw new IllegalArgumentException( "self" );
+
+ if ( other == null )
+ throw new IllegalArgumentException( "other" );
+
+ if ( self.length > other.length - offset )
+ throw new IllegalArgumentException( "self and other lengths do not match" );
+
+ byte[] result = new byte[self.length];
+
+ for ( int i = 0; i < self.length; i++ )
+ {
+ result[i] = (byte)( self[i] ^ other[offset + i] );
+ }
+
+ return result;
+ }
+
+ public static void zero( byte[] self )
+ {
+ if ( self != null ) {
+ Arrays.fill(self, (byte)0);
+ }
+ }
+
+ /**
+ * Compares two byte arrays in constant time.
+ *
+ * @param self
+ * The first byte array to compare
+ * @param other
+ * The second byte array to compare
+ * @return
+ * True if the two byte arrays are equal.
+ */
+ public static boolean sequenceEqualConstantTime( byte[] self, byte[] other )
+ {
+ if ( self == null )
+ throw new IllegalArgumentException( "self" );
+
+ if ( other == null )
+ throw new IllegalArgumentException( "other" );
+
+ // Constant time comparison of two byte arrays
+ long difference = ( self.length & 0xffffffffl ) ^ ( other.length & 0xffffffffl );
+
+ for ( int i = 0; i < self.length && i < other.length; i++ )
+ {
+ difference |= ( self[i] ^ other[i] ) & 0xffffffffl;
+ }
+
+ return difference == 0;
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/EncryptionAlgorithm.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/EncryptionAlgorithm.java
new file mode 100755
index 000000000000..4d36c332b3be
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/EncryptionAlgorithm.java
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+/**
+ * Abstract base class for all encryption algorithms.
+ *
+ */
+public abstract class EncryptionAlgorithm extends Algorithm {
+
+ /**
+ * Constructor.
+ * @param name The name of the algorithm.
+ */
+ protected EncryptionAlgorithm(String name) {
+ super(name);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/IAuthenticatedCryptoTransform.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/IAuthenticatedCryptoTransform.java
new file mode 100755
index 000000000000..113a14404cf4
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/IAuthenticatedCryptoTransform.java
@@ -0,0 +1,12 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+public interface IAuthenticatedCryptoTransform extends ICryptoTransform {
+
+ public byte[] getTag();
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ICryptoTransform.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ICryptoTransform.java
new file mode 100755
index 000000000000..4787a9d11a0f
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ICryptoTransform.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+/**
+ * Defines the basic operations of cryptographic transformations.
+ *
+ */
+public interface ICryptoTransform {
+
+ /**
+ * Transforms the specified region of the specified byte array as a single operation.
+ *
+ * @param input
+ * The byte array to be transformed
+ * @return
+ * The transformed result.
+ * @throws IllegalBlockSizeException
+ * @throws BadPaddingException
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ */
+ public byte[] doFinal(byte[] input) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException;
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ISignatureTransform.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ISignatureTransform.java
new file mode 100644
index 000000000000..484b1448fb51
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/ISignatureTransform.java
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.security.GeneralSecurityException;
+
+public interface ISignatureTransform {
+
+ public byte[] sign(final byte[] digest) throws GeneralSecurityException;
+
+ public boolean verify(final byte[] digest, final byte[] signature) throws GeneralSecurityException;
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/KeyWrapAlgorithm.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/KeyWrapAlgorithm.java
new file mode 100755
index 000000000000..e0028d51a507
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/KeyWrapAlgorithm.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.NoSuchPaddingException;
+
+/**
+ * Abstract base class for all key wrap algorithms.
+ *
+ */
+public abstract class KeyWrapAlgorithm extends Algorithm {
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the algorithm.
+ */
+ protected KeyWrapAlgorithm(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption.
+ * Uses the default AES-KW initialization vector.
+ * @param key
+ * The AES key material to be used.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateEncryptor(byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption that
+ * uses the specified provider for the Java Security API. Uses the default AES-KW initialization vector.
+ *
+ * @param key
+ * The AES key material to be used.
+ * @param provider
+ * The provider to use.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateEncryptor(byte[] key, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption
+ * using the supplied initialization vector.
+ * @param key
+ * The AES key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateEncryptor(byte[] key, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption
+ * using the supplied initialization vector and the specific provider for the Java Security API.
+ * @param key
+ * The AES key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @param provider
+ * The provider to use.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption.
+ * Uses the default AES-KW initialization vector.
+ * @param key
+ * The AES key material to be used.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateDecryptor(byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption that
+ * uses the specified provider for the Java Security API. Uses the default AES-KW initialization vector.
+ *
+ * @param key
+ * The AES key material to be used.
+ * @param provider
+ * The provider to use.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateDecryptor(byte[] key, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption
+ * using the supplied initialization vector.
+ * @param key
+ * The AES key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateDecryptor(byte[] key, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption
+ * using the supplied initialization vector and the specific provider for the Java Security API.
+ * @param key
+ * The AES key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @param provider
+ * The provider to use.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidKeyException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException;
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/RsaKey.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/RsaKey.java
new file mode 100755
index 000000000000..c8807fc29c49
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/RsaKey.java
@@ -0,0 +1,297 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.interfaces.RSAPublicKey;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.tuple.Triple;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Rs256;
+import com.microsoft.azure.keyvault.cryptography.algorithms.RsaOaep;
+import com.microsoft.azure.keyvault.cryptography.Strings;
+
+public class RsaKey implements IKey {
+
+ public static int KeySize1024 = 1024;
+ public static int KeySize2048 = 2048;
+
+ public static int getDefaultKeySize() {
+ return RsaKey.KeySize2048;
+ }
+
+ private final String _kid;
+ private final KeyPair _keyPair;
+ private final Provider _provider;
+
+ public RsaKey(String kid) throws NoSuchAlgorithmException {
+ this(kid, getDefaultKeySize());
+ }
+
+ public RsaKey(String kid, int keySize) throws NoSuchAlgorithmException {
+ this(kid, keySize, null);
+ }
+
+ public RsaKey(String kid, int keySize, Provider provider) throws NoSuchAlgorithmException {
+
+ if (Strings.isNullOrWhiteSpace(kid)) {
+ throw new IllegalArgumentException("kid");
+ }
+
+ final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
+
+ generator.initialize(keySize);
+
+ _kid = kid;
+ _keyPair = generator.generateKeyPair();
+ _provider = provider;
+ }
+
+ public RsaKey(String kid, KeyPair keyPair) {
+ this(kid, keyPair, null);
+ }
+
+ public RsaKey(String kid, KeyPair keyPair, Provider provider) {
+
+ if (Strings.isNullOrWhiteSpace(kid)) {
+ throw new IllegalArgumentException("kid");
+ }
+
+ if (keyPair == null) {
+ throw new IllegalArgumentException("kid");
+ }
+
+ if (keyPair.getPublic() == null || !(keyPair.getPublic() instanceof RSAPublicKey)) {
+ throw new IllegalArgumentException("keyPair");
+ }
+
+ _kid = kid;
+ _keyPair = keyPair;
+ _provider = provider;
+ }
+
+ @Override
+ public String getDefaultEncryptionAlgorithm() {
+ return RsaOaep.ALGORITHM_NAME;
+ }
+
+ @Override
+ public String getDefaultKeyWrapAlgorithm() {
+ return RsaOaep.ALGORITHM_NAME;
+ }
+
+ @Override
+ public String getDefaultSignatureAlgorithm() {
+ return Rs256.ALGORITHM_NAME;
+ }
+
+ @Override
+ public String getKid() {
+ return _kid;
+ }
+
+ @Override
+ public ListenableFuture decryptAsync(final byte[] ciphertext, final byte[] iv, final byte[] authenticationData, final byte[] authenticationTag, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (ciphertext == null) {
+ throw new IllegalArgumentException("ciphertext");
+ }
+
+ // Interpret the requested algorithm
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ AsymmetricEncryptionAlgorithm algo = (AsymmetricEncryptionAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform;
+ ListenableFuture result;
+
+ try {
+ transform = algo.CreateDecryptor(_keyPair, _provider);
+ result = Futures.immediateFuture(transform.doFinal(ciphertext));
+ } catch (Exception e) {
+ result = Futures.immediateFailedFuture(e);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ListenableFuture> encryptAsync(final byte[] plaintext, final byte[] iv, final byte[] authenticationData, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (plaintext == null) {
+ throw new IllegalArgumentException("plaintext");
+ }
+
+ // Interpret the requested algorithm
+ String algorithmName = (Strings.isNullOrWhiteSpace(algorithm) ? getDefaultEncryptionAlgorithm() : algorithm);
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithmName);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithmName);
+ }
+
+ AsymmetricEncryptionAlgorithm algo = (AsymmetricEncryptionAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform;
+ ListenableFuture> result;
+
+ try {
+ transform = algo.CreateEncryptor(_keyPair, _provider);
+ result = Futures.immediateFuture(Triple.of(transform.doFinal(plaintext), (byte[]) null, algorithmName));
+ } catch (Exception e) {
+ result = Futures.immediateFailedFuture(e);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ListenableFuture> wrapKeyAsync(final byte[] key, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key");
+ }
+
+ // Interpret the requested algorithm
+ String algorithmName = (Strings.isNullOrWhiteSpace(algorithm) ? getDefaultKeyWrapAlgorithm() : algorithm);
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithmName);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithmName);
+ }
+
+ AsymmetricEncryptionAlgorithm algo = (AsymmetricEncryptionAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform;
+ ListenableFuture> result;
+
+ try {
+ transform = algo.CreateEncryptor(_keyPair, _provider);
+ result = Futures.immediateFuture(Pair.of(transform.doFinal(key), algorithmName));
+ } catch (Exception e) {
+ result = Futures.immediateFailedFuture(e);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ListenableFuture unwrapKeyAsync(final byte[] encryptedKey, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (encryptedKey == null) {
+ throw new IllegalArgumentException("encryptedKey ");
+ }
+
+ // Interpret the requested algorithm
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ // Interpret the requested algorithm
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ AsymmetricEncryptionAlgorithm algo = (AsymmetricEncryptionAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform;
+ ListenableFuture result;
+
+ try {
+ transform = algo.CreateDecryptor(_keyPair, _provider);
+ result = Futures.immediateFuture(transform.doFinal(encryptedKey));
+ } catch (Exception e) {
+ result = Futures.immediateFailedFuture(e);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ListenableFuture> signAsync(final byte[] digest, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (digest == null) {
+ throw new IllegalArgumentException("encryptedKey ");
+ }
+
+ // Interpret the requested algorithm
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ // Interpret the requested algorithm
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricSignatureAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ Rs256 algo = (Rs256)baseAlgorithm;
+
+ ISignatureTransform signer = algo.createSignatureTransform(_keyPair);
+
+ try {
+ return Futures.immediateFuture(Pair.of(signer.sign(digest), Rs256.ALGORITHM_NAME));
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+ }
+
+ @Override
+ public ListenableFuture verifyAsync(final byte[] digest, final byte[] signature, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (digest == null) {
+ throw new IllegalArgumentException("encryptedKey ");
+ }
+
+ // Interpret the requested algorithm
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ // Interpret the requested algorithm
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricSignatureAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ Rs256 algo = (Rs256)baseAlgorithm;
+
+ ISignatureTransform signer = algo.createSignatureTransform(_keyPair);
+
+ try {
+ return Futures.immediateFuture(signer.verify(digest, signature));
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ // Intentionally empty
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SignatureAlgorithm.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SignatureAlgorithm.java
new file mode 100755
index 000000000000..53d7459b9136
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SignatureAlgorithm.java
@@ -0,0 +1,15 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+public abstract class SignatureAlgorithm extends Algorithm {
+
+ protected SignatureAlgorithm(String name) {
+ super(name);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/Strings.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/Strings.java
new file mode 100755
index 000000000000..a1ead94749e6
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/Strings.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+public final class Strings {
+
+ /**
+ * Determines whether the parameter string is either null or empty.
+ *
+ * @param arg The string to be checked.
+ * @return true if the string is null or empty.
+ */
+ public static boolean isNullOrEmpty(String arg) {
+
+ if (arg == null || arg.length() == 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines whether the parameter string is null, empty or whitespace.
+ *
+ * @param arg The string to be checked.
+ * @return true if the string is null, empty or whitespace.
+ */
+ public static boolean isNullOrWhiteSpace(String arg) {
+
+ if (Strings.isNullOrEmpty(arg) || arg.trim().isEmpty()) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SymmetricEncryptionAlgorithm.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SymmetricEncryptionAlgorithm.java
new file mode 100755
index 000000000000..b582ced73492
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SymmetricEncryptionAlgorithm.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.NoSuchPaddingException;
+
+/**
+ * Abstract base class for all symmetric encryption algorithms.
+ *
+ */
+public abstract class SymmetricEncryptionAlgorithm extends EncryptionAlgorithm {
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the algorithm.
+ */
+ protected SymmetricEncryptionAlgorithm(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption
+ * using the supplied initialization vector and the specific provider for the Java Security API.
+ * @param key
+ * The key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @param authenticationData
+ * The authentication data to be used with authenticating encryption algorithms (ignored for non-authenticating algorithms)
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, byte[] authenticationData) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for encryption
+ * using the supplied initialization vector and the specific provider for the Java Security API.
+ * @param key
+ * The key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @param authenticationData
+ * The authentication data to be used with authenticating encryption algorithms (ignored for non-authenticating algorithms)
+ * @param provider
+ * The provider to use.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, byte[] authenticationData, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption
+ * using the supplied initialization vector and the specific provider for the Java Security API.
+ * @param key
+ * The key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @param authenticationData
+ * The authentication data to be used with authenticating encryption algorithms (ignored for non-authenticating algorithms)
+ * @param authenticationTag
+ * The authentication tag to verify when using authenticating encryption algorithms (ignored for non-authenticating algorithms)
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException;
+
+ /**
+ * Creates a {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation for decryption
+ * using the supplied initialization vector and the specific provider for the Java Security API.
+ * @param key
+ * The key material to be used.
+ * @param iv
+ * The initialization vector to be used.
+ * @param authenticationData
+ * The authentication data to be used with authenticating encryption algorithms (ignored for non-authenticating algorithms)
+ * @param authenticationTag
+ * The authentication tag to verify when using authenticating encryption algorithms (ignored for non-authenticating algorithms)
+ * @param provider
+ * The provider to use.
+ * @return A {@link com.microsoft.azure.keyvault.cryptography.ICryptoTransform} implementation
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchPaddingException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public abstract ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException;
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SymmetricKey.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SymmetricKey.java
new file mode 100755
index 000000000000..c401d77251a8
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/SymmetricKey.java
@@ -0,0 +1,389 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.util.UUID;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.tuple.Triple;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes128Cbc;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes128CbcHmacSha256;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes192Cbc;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes192CbcHmacSha384;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes256CbcHmacSha512;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw128;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw192;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw256;
+import com.microsoft.azure.keyvault.cryptography.Strings;
+
+/**
+ * A simple symmetric key implementation
+ *
+ */
+public class SymmetricKey implements IKey {
+
+ private static final SecureRandom Rng = new SecureRandom();
+
+ public static final int KeySize128 = 128 >> 3;
+ public static final int KeySize192 = 192 >> 3;
+ public static final int KeySize256 = 256 >> 3;
+ public static final int KeySize384 = 384 >> 3;
+ public static final int KeySize512 = 512 >> 3;
+
+ public static final int DefaultKeySize = KeySize256;
+
+ private final String _kid;
+ private final byte[] _key;
+ private final Provider _provider;
+
+ /**
+ * Creates a SymmetricKey with a random key identifier and
+ * a random key with DefaultKeySize bits.
+ */
+ public SymmetricKey() {
+ this(UUID.randomUUID().toString());
+ }
+
+ /**
+ * Creates a SymmetricKey with the specified key identifier and
+ * a random key with DefaultKeySize bits.
+ * @param kid
+ * The key identifier to use.
+ */
+ public SymmetricKey(String kid) {
+ this(kid, DefaultKeySize);
+ }
+
+ /**
+ * Creates a SymmetricKey with the specified key identifier and
+ * a random key with the specified size.
+ * @param kid
+ * The key identifier to use.
+ * @param keySizeInBytes
+ * The key size to use in bytes.
+ */
+ public SymmetricKey(String kid, int keySizeInBytes ) {
+ this(kid, keySizeInBytes, null);
+ }
+
+ /**
+ * Creates a SymmetricKey with the specified key identifier and
+ * a random key with the specified size that uses the specified provider.
+ * @param kid
+ * The key identifier to use.
+ * @param keySizeInBytes
+ * The key size to use in bytes.
+ * @param provider
+ * The provider to use (optional, null for default)
+ */
+ public SymmetricKey(String kid, int keySizeInBytes, Provider provider) {
+
+ if ( Strings.isNullOrWhiteSpace(kid) ) {
+ throw new IllegalArgumentException("kid");
+ }
+
+ if ( keySizeInBytes != KeySize128 && keySizeInBytes != KeySize192 && keySizeInBytes != KeySize256 && keySizeInBytes != KeySize384 && keySizeInBytes != KeySize512 ) {
+ throw new IllegalArgumentException("The key material must be 128, 192, 256, 384 or 512 bits of data");
+ }
+
+ _kid = kid;
+ _key = new byte[keySizeInBytes];
+ _provider = provider;
+
+ // Generate a random key
+ Rng.nextBytes(_key);
+ }
+
+ /**
+ * Creates a SymmetricKey with the specified key identifier and key material.
+ * @param kid
+ * The key identifier to use.
+ * @param keyBytes
+ * The key material to use.
+ */
+ public SymmetricKey(String kid, byte[] keyBytes) {
+ this(kid, keyBytes, null);
+ }
+
+ /**
+ * Creates a SymmetricKey with the specified key identifier and key material
+ * that uses the specified Provider.
+ * @param kid
+ * The key identifier to use.
+ * @param keyBytes
+ * The key material to use.
+ * @param provider
+ * The Provider to use (optional, null for default)
+ */
+ public SymmetricKey(String kid, byte[] keyBytes, Provider provider) {
+
+ if ( Strings.isNullOrWhiteSpace(kid) ) {
+ throw new IllegalArgumentException("kid");
+ }
+
+ if ( keyBytes == null ) {
+ throw new IllegalArgumentException("keyBytes");
+ }
+
+ if ( keyBytes.length != KeySize128 && keyBytes.length != KeySize192 && keyBytes.length != KeySize256 && keyBytes.length != KeySize384 && keyBytes.length != KeySize512 ) {
+ throw new IllegalArgumentException("The key material must be 128, 192, 256, 384 or 512 bits of data");
+ }
+
+ _kid = kid;
+ _key = keyBytes;
+ _provider = provider;
+ }
+
+ @Override
+ public String getDefaultEncryptionAlgorithm() {
+
+ switch (_key.length) {
+ case KeySize128:
+ return Aes128Cbc.ALGORITHM_NAME;
+
+ case KeySize192:
+ return Aes192Cbc.ALGORITHM_NAME;
+
+ case KeySize256:
+ return Aes128CbcHmacSha256.ALGORITHM_NAME;
+
+ case KeySize384:
+ return Aes192CbcHmacSha384.ALGORITHM_NAME;
+
+ case KeySize512:
+ return Aes256CbcHmacSha512.ALGORITHM_NAME;
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getDefaultKeyWrapAlgorithm() {
+
+ switch (_key.length) {
+ case KeySize128:
+ return AesKw128.ALGORITHM_NAME;
+
+ case KeySize192:
+ return AesKw192.ALGORITHM_NAME;
+
+ case KeySize256:
+ return AesKw256.ALGORITHM_NAME;
+
+ case KeySize384:
+ // Default to longest allowed key length for wrap
+ return AesKw256.ALGORITHM_NAME;
+
+ case KeySize512:
+ // Default to longest allowed key length for wrap
+ return AesKw256.ALGORITHM_NAME;
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getDefaultSignatureAlgorithm() {
+
+ return null;
+ }
+
+ @Override
+ public String getKid() {
+
+ return _kid;
+ }
+
+ @Override
+ public ListenableFuture decryptAsync(final byte[] ciphertext, final byte[] iv, final byte[] authenticationData, final byte[] authenticationTag, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ if (ciphertext == null) {
+ throw new IllegalArgumentException("ciphertext");
+ }
+
+ if (iv == null) {
+ throw new IllegalArgumentException("iv");
+ }
+
+ // Interpret the algorithm
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof SymmetricEncryptionAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ SymmetricEncryptionAlgorithm algo = (SymmetricEncryptionAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform = null;
+
+ try {
+ transform = algo.CreateDecryptor(_key, iv, authenticationData, authenticationTag, _provider );
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ byte[] result = null;
+
+ try {
+ result = transform.doFinal(ciphertext);
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ return Futures.immediateFuture(result);
+ }
+
+ @Override
+ public ListenableFuture> encryptAsync(final byte[] plaintext, final byte[] iv, final byte[] authenticationData, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (plaintext == null) {
+ throw new IllegalArgumentException("plaintext");
+ }
+
+ if (iv == null) {
+ throw new IllegalArgumentException("iv");
+ }
+
+ // Interpret the algorithm
+ String algorithmName = (Strings.isNullOrWhiteSpace(algorithm)) ? getDefaultEncryptionAlgorithm() : algorithm;
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithmName);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof SymmetricEncryptionAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ SymmetricEncryptionAlgorithm algo = (SymmetricEncryptionAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform = null;
+
+ try {
+ transform = algo.CreateEncryptor(_key, iv, authenticationData, _provider);
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ byte[] cipherText = null;
+
+ try {
+ cipherText = transform.doFinal(plaintext);
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ byte[] authenticationTag = null;
+
+ if (transform instanceof IAuthenticatedCryptoTransform) {
+
+ IAuthenticatedCryptoTransform authenticatedTransform = (IAuthenticatedCryptoTransform) transform;
+
+ authenticationTag = authenticatedTransform.getTag().clone();
+ }
+
+ return Futures.immediateFuture(Triple.of(cipherText, authenticationTag, algorithm));
+ }
+
+ @Override
+ public ListenableFuture> wrapKeyAsync(final byte[] key, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (key == null || key.length == 0) {
+ throw new IllegalArgumentException("key");
+ }
+
+ // Interpret the algorithm
+ String algorithmName = (Strings.isNullOrWhiteSpace(algorithm)) ? getDefaultKeyWrapAlgorithm() : algorithm;
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithmName);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof KeyWrapAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithmName);
+ }
+
+ KeyWrapAlgorithm algo = (KeyWrapAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform = null;
+
+ try {
+ transform = algo.CreateEncryptor(_key, null, _provider);
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = transform.doFinal(key);
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ return Futures.immediateFuture(Pair.of(encrypted, algorithmName));
+ }
+
+ @Override
+ public ListenableFuture unwrapKeyAsync(final byte[] encryptedKey, final String algorithm) throws NoSuchAlgorithmException {
+
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ if (encryptedKey == null || encryptedKey.length == 0) {
+ throw new IllegalArgumentException("wrappedKey");
+ }
+
+ Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm);
+
+ if (baseAlgorithm == null || !(baseAlgorithm instanceof KeyWrapAlgorithm)) {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ KeyWrapAlgorithm algo = (KeyWrapAlgorithm)baseAlgorithm;
+
+ ICryptoTransform transform = null;
+
+ try {
+ transform = algo.CreateDecryptor(_key, null, _provider);
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = transform.doFinal(encryptedKey);
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+
+ return Futures.immediateFuture(decrypted);
+ }
+
+ @Override
+ public ListenableFuture> signAsync(final byte[] digest, final String algorithm) {
+ return Futures.immediateFailedFuture(new NotImplementedException("signAsync is not currently supported"));
+ }
+
+ @Override
+ public ListenableFuture verifyAsync(final byte[] digest, final byte[] signature, final String algorithm) {
+ return Futures.immediateFailedFuture(new NotImplementedException("verifyAsync is not currently supported"));
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes128Cbc.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes128Cbc.java
new file mode 100755
index 000000000000..89a10584294d
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes128Cbc.java
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+public class Aes128Cbc extends AesCbc {
+
+ private static final int KEY_SIZE = 128;
+ public static final String ALGORITHM_NAME = "A128CBC";
+
+ public Aes128Cbc() {
+ super(ALGORITHM_NAME, KEY_SIZE);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes128CbcHmacSha256.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes128CbcHmacSha256.java
new file mode 100755
index 000000000000..f473aee20d11
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes128CbcHmacSha256.java
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+public class Aes128CbcHmacSha256 extends AesCbcHmacSha2 {
+
+ public static final String ALGORITHM_NAME = "A128CBC-HS256";
+
+ public Aes128CbcHmacSha256() {
+ super(ALGORITHM_NAME);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes192Cbc.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes192Cbc.java
new file mode 100755
index 000000000000..fe6f3ff8f1f1
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes192Cbc.java
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+public class Aes192Cbc extends AesCbc {
+
+ private static final int KEY_SIZE = 192;
+ public static final String ALGORITHM_NAME = "A192CBC";
+
+ public Aes192Cbc() {
+ super(ALGORITHM_NAME, KEY_SIZE);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes192CbcHmacSha384.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes192CbcHmacSha384.java
new file mode 100755
index 000000000000..ecfc65f49ff6
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes192CbcHmacSha384.java
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+public class Aes192CbcHmacSha384 extends AesCbcHmacSha2 {
+
+ public static final String ALGORITHM_NAME = "A192CBC-HS384";
+
+ public Aes192CbcHmacSha384() {
+ super(ALGORITHM_NAME);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes256Cbc.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes256Cbc.java
new file mode 100755
index 000000000000..f198b9012b54
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes256Cbc.java
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+public class Aes256Cbc extends AesCbc {
+
+ private static final int KEY_SIZE = 256;
+ public static final String ALGORITHM_NAME = "A256CBC";
+
+ public Aes256Cbc() {
+ super(ALGORITHM_NAME, KEY_SIZE);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes256CbcHmacSha512.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes256CbcHmacSha512.java
new file mode 100755
index 000000000000..61c1aead84b7
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Aes256CbcHmacSha512.java
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+public class Aes256CbcHmacSha512 extends AesCbcHmacSha2 {
+
+ public static final String ALGORITHM_NAME = "A256CBC-HS512";
+
+ public Aes256CbcHmacSha512() {
+ super(ALGORITHM_NAME);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesCbc.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesCbc.java
new file mode 100755
index 000000000000..f2b9d28f67e3
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesCbc.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.util.Arrays;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+import com.microsoft.azure.keyvault.cryptography.SymmetricEncryptionAlgorithm;
+
+public abstract class AesCbc extends SymmetricEncryptionAlgorithm {
+
+ final int keySizeInBytes;
+ final int keySize;
+ static class AesCbcDecryptor implements ICryptoTransform {
+
+ private final Cipher _cipher;
+
+ AesCbcDecryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ // Create the cipher using the Provider if specified
+ if (provider == null) {
+ _cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ } else {
+ _cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider);
+ }
+
+ _cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException {
+ return _cipher.doFinal(plaintext);
+ }
+ }
+
+ static class AesCbcEncryptor implements ICryptoTransform {
+
+ private final Cipher _cipher;
+
+ AesCbcEncryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ // Create the cipher using the Provider if specified
+ if (provider == null) {
+ _cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ } else {
+ _cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider);
+ }
+
+ _cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException {
+ return _cipher.doFinal(plaintext);
+ }
+ }
+
+ protected AesCbc(String name, int size) {
+ super(name);
+ keySize = size;
+ keySizeInBytes = size >> 3;
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, byte[] authenticationData) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null || key.length < keySizeInBytes) {
+ throw new InvalidKeyException("key must be at least " + keySize + " bits in length");
+ }
+
+ return new AesCbcEncryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, byte[] authenticationData, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null || key.length < keySizeInBytes) {
+ throw new InvalidKeyException("key must be at least " + keySize + " bits in length");
+ }
+
+ return new AesCbcEncryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null || key.length < keySizeInBytes) {
+ throw new InvalidKeyException("key must be at least " + keySize + " bits in length");
+ }
+
+ return new AesCbcDecryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null || key.length < keySizeInBytes) {
+ throw new InvalidKeyException("key must be at least " + keySize + " bits in length");
+ }
+
+ return new AesCbcDecryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, provider);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesCbcHmacSha2.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesCbcHmacSha2.java
new file mode 100755
index 000000000000..9ab0a3cd2f1e
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesCbcHmacSha2.java
@@ -0,0 +1,279 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.lang3.tuple.Triple;
+
+import com.microsoft.azure.keyvault.cryptography.ByteExtensions;
+import com.microsoft.azure.keyvault.cryptography.IAuthenticatedCryptoTransform;
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+import com.microsoft.azure.keyvault.cryptography.SymmetricEncryptionAlgorithm;
+
+public abstract class AesCbcHmacSha2 extends SymmetricEncryptionAlgorithm {
+
+ static class AesCbcHmacSha2Decryptor implements IAuthenticatedCryptoTransform {
+
+ final byte[] _aad_length;
+ final Mac _hmac;
+ final byte[] _hmac_key;
+ final ICryptoTransform _inner;
+
+ byte[] _tag;
+
+ AesCbcHmacSha2Decryptor(String name, byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ // Split the key to get the AES key, the HMAC key and the HMAC
+ // object
+ Triple parameters = GetAlgorithmParameters(name, key);
+
+ // Save the MAC provider and key
+ _hmac = parameters.getRight();
+ _hmac_key = parameters.getMiddle();
+
+ // Create the AES provider
+ _inner = new AesCbc.AesCbcDecryptor(parameters.getLeft(), iv, provider);
+
+ _aad_length = toBigEndian(authenticationData.length * 8);
+
+ // Save the tag
+ _tag = authenticationTag;
+
+ // Prime the hash.
+ _hmac.update(authenticationData);
+ _hmac.update(iv);
+ }
+
+ @Override
+ public byte[] getTag() {
+ return _tag;
+ }
+
+ @Override
+ public byte[] doFinal(byte[] input) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException {
+
+ // Add the cipher text to the running hash
+ _hmac.update(input);
+
+ // Add the associated_data_length bytes to the hash
+ byte[] hash = _hmac.doFinal(_aad_length);
+
+ // Compute the new tag
+ byte[] tag = new byte[_hmac_key.length];
+ System.arraycopy(hash, 0, tag, 0, _hmac_key.length);
+
+ // Check the tag before performing the final decrypt
+ if ( !ByteExtensions.sequenceEqualConstantTime(_tag, tag) ) {
+ throw new IllegalArgumentException("Data is not authentic");
+ }
+
+ return _inner.doFinal(input);
+ }
+ }
+
+ static class AesCbcHmacSha2Encryptor implements IAuthenticatedCryptoTransform {
+
+ final byte[] _aad_length;
+ final Mac _hmac;
+ final byte[] _hmac_key;
+ final ICryptoTransform _inner;
+
+ byte[] _tag;
+
+ AesCbcHmacSha2Encryptor(String name, byte[] key, byte[] iv, byte[] authenticationData, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+ // Split the key to get the AES key, the HMAC key and the HMAC
+ // object
+ Triple parameters = GetAlgorithmParameters(name, key);
+
+ // Save the MAC provider and key
+ _hmac = parameters.getRight();
+ _hmac_key = parameters.getMiddle();
+
+ // Create the AES encryptor
+ _inner = new AesCbc.AesCbcEncryptor(parameters.getLeft(), iv, provider);
+
+ _aad_length = toBigEndian(authenticationData.length * 8);
+
+ // Prime the hash.
+ _hmac.update(authenticationData);
+ _hmac.update(iv);
+ }
+
+ @Override
+ public byte[] getTag() {
+ return _tag;
+ }
+
+ // public int TransformBlock( byte[] inputBuffer, int inputOffset, int
+ // inputCount, byte[] outputBuffer, int outputOffset )
+ // {
+ // // Encrypt the block
+ // var result = _inner.TransformBlock( inputBuffer, inputOffset,
+ // inputCount, outputBuffer, outputOffset );
+ //
+ // // Add it to the running hash
+ // _hmac.TransformBlock( outputBuffer, outputOffset, result,
+ // outputBuffer, outputOffset );
+ //
+ // return result;
+ // }
+
+ @Override
+ public byte[] doFinal(byte[] input) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException {
+
+ // Encrypt the block
+ byte[] output = _inner.doFinal(input);
+
+ // Add the cipher text to the running hash
+ _hmac.update(output);
+
+ // Add the associated_data_length bytes to the hash
+ byte[] hash = _hmac.doFinal(_aad_length);
+
+ // Compute the tag
+ _tag = new byte[_hmac_key.length];
+ System.arraycopy(hash, 0, _tag, 0, _tag.length);
+
+ return output;
+ }
+ }
+
+ protected AesCbcHmacSha2(String name) {
+ super(name);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+ return CreateDecryptor(key, iv, authenticationData, authenticationTag, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+ if (key == null) {
+ throw new IllegalArgumentException("No key material");
+ }
+
+ if (iv == null) {
+ throw new IllegalArgumentException("No initialization vector");
+ }
+
+ if (authenticationData == null) {
+ throw new IllegalArgumentException("No authentication data");
+ }
+
+ if (authenticationTag == null) {
+ throw new IllegalArgumentException("No authentication tag");
+ }
+
+ // Create the Decryptor
+ return new AesCbcHmacSha2Decryptor(getName(), key, iv, authenticationData, authenticationTag, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, byte[] authenticationData) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+ return CreateEncryptor(key, iv, authenticationData, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, byte[] authenticationData, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("No key material");
+ }
+
+ if (iv == null) {
+ throw new IllegalArgumentException("No initialization vector");
+ }
+
+ if (authenticationData == null) {
+ throw new IllegalArgumentException("No authentication data");
+ }
+
+ // Create the Encryptor
+ return new AesCbcHmacSha2Encryptor(getName(), key, iv, authenticationData, provider);
+ }
+
+ private static Triple GetAlgorithmParameters(String algorithm, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException {
+
+ byte[] aes_key;
+ byte[] hmac_key;
+ Mac hmac;
+
+ if (algorithm.equalsIgnoreCase(Aes128CbcHmacSha256.ALGORITHM_NAME)) {
+ if ((key.length << 3) < 256) {
+ throw new IllegalArgumentException(String.format("%s key length in bits %d < 256", algorithm, key.length << 3));
+ }
+
+ hmac_key = new byte[128 >> 3];
+ aes_key = new byte[128 >> 3];
+
+ // The HMAC key precedes the AES key
+ System.arraycopy(key, 0, hmac_key, 0, 128 >> 3);
+ System.arraycopy(key, 128 >> 3, aes_key, 0, 128 >> 3);
+
+ hmac = Mac.getInstance("HmacSHA256");
+ hmac.init(new SecretKeySpec(hmac_key, "HmacSHA256"));
+
+ } else if (algorithm.equalsIgnoreCase(Aes192CbcHmacSha384.ALGORITHM_NAME)) {
+
+ if ((key.length << 3) < 384) {
+ throw new IllegalArgumentException(String.format("%s key length in bits %d < 384", algorithm, key.length << 3));
+ }
+
+ hmac_key = new byte[192 >> 3];
+ aes_key = new byte[192 >> 3];
+
+ // The HMAC key precedes the AES key
+ System.arraycopy(key, 0, hmac_key, 0, 192 >> 3);
+ System.arraycopy(key, 192 >> 3, aes_key, 0, 192 >> 3);
+
+ hmac = Mac.getInstance("HmacSHA384");
+ hmac.init(new SecretKeySpec(hmac_key, "HmacSHA384"));
+ } else if (algorithm.equalsIgnoreCase(Aes256CbcHmacSha512.ALGORITHM_NAME)) {
+
+ if ((key.length << 3) < 512) {
+ throw new IllegalArgumentException(String.format("%s key length in bits %d < 512", algorithm, key.length << 3));
+ }
+
+ hmac_key = new byte[256 >> 3];
+ aes_key = new byte[256 >> 3];
+
+ // The HMAC key precedes the AES key
+ System.arraycopy(key, 0, hmac_key, 0, 256 >> 3);
+ System.arraycopy(key, 256 >> 3, aes_key, 0, 256 >> 3);
+
+ hmac = Mac.getInstance("HmacSHA512");
+ hmac.init(new SecretKeySpec(hmac_key, "HmacSHA512"));
+ } else {
+ throw new IllegalArgumentException(String.format("Unsupported algorithm: %s", algorithm));
+ }
+
+ return Triple.of(aes_key, hmac_key, hmac);
+ }
+
+ static byte[] toBigEndian(long i) {
+
+ byte[] shortRepresentation = BigInteger.valueOf(i).toByteArray();
+ byte[] longRepresentation = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ System.arraycopy(shortRepresentation, 0, longRepresentation, longRepresentation.length - shortRepresentation.length, shortRepresentation.length);
+
+ return longRepresentation;
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw.java
new file mode 100755
index 000000000000..6bd7dfc28c63
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+import com.microsoft.azure.keyvault.cryptography.KeyWrapAlgorithm;
+
+public abstract class AesKw extends KeyWrapAlgorithm {
+
+ static final byte[] _defaultIv = new byte[] { (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6 };
+ static final String _cipherName = "AESWrap";
+
+ class AesKwDecryptor implements ICryptoTransform {
+
+ final Cipher _cipher;
+
+ AesKwDecryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ if (provider == null) {
+ _cipher = Cipher.getInstance(_cipherName);
+ } else {
+ _cipher = Cipher.getInstance(_cipherName, provider);
+ }
+
+ // The default provider does not support the specification of IV. This
+ // is guarded by the CreateEncrypter wrapper method and the iv parameter
+ // can be ignored when using the default provider
+ if (provider == null ) {
+ _cipher.init(Cipher.UNWRAP_MODE, new SecretKeySpec(key, "AES"));
+ } else {
+ _cipher.init(Cipher.UNWRAP_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
+ }
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException {
+
+ return _cipher.unwrap(plaintext, "AESWrap", Cipher.SECRET_KEY).getEncoded();
+ }
+
+ }
+
+ class AesKwEncryptor implements ICryptoTransform {
+
+ final Cipher _cipher;
+
+ AesKwEncryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ if (provider == null) {
+ _cipher = Cipher.getInstance(_cipherName);
+ } else {
+ _cipher = Cipher.getInstance(_cipherName, provider);
+ }
+
+ // The default provider does not support the specification of IV. This
+ // is guarded by the CreateEncrypter wrapper method and the iv parameter
+ // can be ignored when using the default provider
+ if (provider == null ) {
+ _cipher.init(Cipher.WRAP_MODE, new SecretKeySpec(key, "AES"));
+ } else {
+ _cipher.init(Cipher.WRAP_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
+ }
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
+
+ return _cipher.wrap(new SecretKeySpec(plaintext, "AES"));
+ }
+
+ }
+
+ protected AesKw(String name) {
+ super(name);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ return CreateEncryptor(key, null, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ return CreateEncryptor(key, null, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ return CreateEncryptor(key, iv, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key");
+ }
+
+ if (key.length != 128 >> 3 && key.length != 192 >> 3 && key.length != 256 >> 3) {
+ throw new IllegalArgumentException("key length must be 128, 192 or 256 bits");
+ }
+
+ if (iv != null ) {
+ // iv length must be 64 bits
+ if ( iv.length != 8) {
+ throw new IllegalArgumentException("iv length must be 64 bits");
+ }
+ // iv cannot be specified with the default provider
+ if (provider == null) {
+ throw new IllegalArgumentException("user specified iv is not supported with the default provider");
+ }
+ }
+
+ return new AesKwEncryptor(key, iv == null ? _defaultIv : iv, provider);
+
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ return CreateDecryptor(key, null, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ return CreateDecryptor(key, null, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+ return CreateDecryptor(key, iv, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key");
+ }
+
+ if (key.length != 128 >> 3 && key.length != 192 >> 3 && key.length != 256 >> 3) {
+ throw new IllegalArgumentException("key length must be 128, 192 or 256 bits");
+ }
+
+
+ if (iv != null ) {
+ // iv length must be 64 bits
+ if ( iv.length != 8) {
+ throw new IllegalArgumentException("iv length must be 64 bits");
+ }
+ // iv cannot be specified with the default provider
+ if (provider == null) {
+ throw new IllegalArgumentException("user specified iv is not supported with the default provider");
+ }
+ }
+
+ return new AesKwDecryptor(key, iv == null ? _defaultIv : iv, provider);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw128.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw128.java
new file mode 100755
index 000000000000..d5696f5998f3
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw128.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.util.Arrays;
+
+import javax.crypto.NoSuchPaddingException;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+
+public final class AesKw128 extends AesKw {
+
+ public static final String ALGORITHM_NAME = "A128KW";
+
+ static final int KeySizeInBytes = 128 >> 3;
+
+ public AesKw128() {
+ super(ALGORITHM_NAME);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key must not be null");
+ }
+
+ if (key.length < KeySizeInBytes) {
+ throw new IllegalArgumentException("key must be at least 128 bits long");
+ }
+
+ return super.CreateEncryptor(Arrays.copyOfRange(key, 0, KeySizeInBytes), iv, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key must not be null");
+ }
+
+ if (key.length < KeySizeInBytes) {
+ throw new IllegalArgumentException("key must be at least 128 bits long");
+ }
+
+ return super.CreateDecryptor(Arrays.copyOfRange(key, 0, KeySizeInBytes), iv, provider);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw192.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw192.java
new file mode 100755
index 000000000000..43225d8e080d
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw192.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.util.Arrays;
+
+import javax.crypto.NoSuchPaddingException;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+
+public final class AesKw192 extends AesKw {
+
+ public static final String ALGORITHM_NAME = "A192KW";
+
+ static final int KeySizeInBytes = 192 >> 3;
+
+ public AesKw192() {
+ super(ALGORITHM_NAME);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key must not be null");
+ }
+
+ if (key.length < KeySizeInBytes) {
+ throw new IllegalArgumentException("key must be at least 192 bits long");
+ }
+
+ return super.CreateEncryptor(Arrays.copyOfRange(key, 0, KeySizeInBytes), iv, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key must not be null");
+ }
+
+ if (key.length < KeySizeInBytes) {
+ throw new IllegalArgumentException("key must be at least 192 bits long");
+ }
+
+ return super.CreateDecryptor(Arrays.copyOfRange(key, 0, KeySizeInBytes), iv, provider);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw256.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw256.java
new file mode 100755
index 000000000000..b2b514713c96
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/AesKw256.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.util.Arrays;
+
+import javax.crypto.NoSuchPaddingException;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+
+public final class AesKw256 extends AesKw {
+
+ public static final String ALGORITHM_NAME = "A256KW";
+
+ static final int KeySizeInBytes = 256 >> 3;
+
+ public AesKw256() {
+ super(ALGORITHM_NAME);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key must not be null");
+ }
+
+ if (key.length < KeySizeInBytes) {
+ throw new IllegalArgumentException("key must be at least 256 bits long");
+ }
+
+ return super.CreateEncryptor(Arrays.copyOfRange(key, 0, KeySizeInBytes), iv, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new IllegalArgumentException("key must not be null");
+ }
+
+ if (key.length < KeySizeInBytes) {
+ throw new IllegalArgumentException("key must be at least 256 bits long");
+ }
+
+ return super.CreateDecryptor(Arrays.copyOfRange(key, 0, KeySizeInBytes), iv, provider);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Rs256.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Rs256.java
new file mode 100644
index 000000000000..e443398bf040
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Rs256.java
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+import com.microsoft.azure.keyvault.cryptography.ByteExtensions;
+import com.microsoft.azure.keyvault.cryptography.ISignatureTransform;
+
+/**
+ *
+ */
+public class Rs256 extends RsaSignature {
+
+ static final String RsaNone = "RSA/ECB/PKCS1Padding";
+
+ class Rs256SignatureTransform implements ISignatureTransform {
+
+ private final KeyPair _keyPair;
+ private final int _emLen;
+
+ Rs256SignatureTransform(KeyPair keyPair) {
+ _keyPair = keyPair;
+
+ BigInteger modulus = ((RSAPublicKey)_keyPair.getPublic()).getModulus();
+
+ _emLen = getOctetLength( modulus.bitLength() );
+
+ }
+
+ @Override
+ public byte[] sign(byte[] digest) throws NoSuchAlgorithmException {
+ // Signing isn't just a case of encrypting the digest, there is much more to do.
+ // For details of the algorithm, see https://tools.ietf.org/html/rfc3447#section-8.2
+
+ if ( _keyPair.getPrivate() == null ) {
+ // TODO
+ }
+
+ // Construct the encoded message
+ byte[] EM = EMSA_PKCS1_V1_5_ENCODE_HASH(digest, _emLen, "SHA-256");
+
+ // Convert to integer message
+ BigInteger s = OS2IP(EM);
+
+ // RSASP1(s)
+ s = RSASP1((RSAPrivateKey)_keyPair.getPrivate(), s);
+
+ // Convert to octet sequence
+ return I2OSP(s, _emLen );
+ }
+
+ @Override
+ public boolean verify(byte[] digest, byte[] signature) throws NoSuchAlgorithmException {
+
+ if ( signature.length != _emLen ) {
+ throw new IllegalArgumentException( "invalid signature length");
+ }
+
+ // Convert to integer signature
+ BigInteger s = OS2IP(signature);
+
+ // Convert integer message
+ BigInteger m = RSAVP1((RSAPublicKey)_keyPair.getPublic(), s);
+
+ byte[] EM = I2OSP(m, _emLen );
+ byte[] EM2 = EMSA_PKCS1_V1_5_ENCODE_HASH(digest, _emLen, "SHA-256");
+
+ // Use constant time compare
+ return ByteExtensions.sequenceEqualConstantTime(EM, EM2);
+ }
+
+ }
+
+ public final static String ALGORITHM_NAME = "RS256";
+
+ public Rs256() {
+ super(ALGORITHM_NAME);
+ }
+
+ @Override
+ public ISignatureTransform createSignatureTransform(KeyPair keyPair) {
+
+ return new Rs256SignatureTransform(keyPair);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Rsa15.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Rsa15.java
new file mode 100755
index 000000000000..18ea8d28514f
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/Rsa15.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+
+public final class Rsa15 extends RsaEncryption {
+
+ class Rsa15Decryptor implements ICryptoTransform {
+
+ private final Cipher _cipher;
+
+ Rsa15Decryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+
+ // Create a cipher object using the provider, if specified
+ if (provider == null) {
+ _cipher = Cipher.getInstance(RSA15);
+ } else {
+ _cipher = Cipher.getInstance(RSA15, provider);
+ }
+
+ // encrypt the plain text using the public key
+ _cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException {
+
+ return _cipher.doFinal(plaintext);
+ }
+
+ }
+
+ class Rsa15Encryptor implements ICryptoTransform {
+
+ private final Cipher _cipher;
+
+ Rsa15Encryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+
+ // Create a cipher object using the provider, if specified
+ if (provider == null) {
+ _cipher = Cipher.getInstance(RSA15);
+ } else {
+ _cipher = Cipher.getInstance(RSA15, provider);
+ }
+
+ // encrypt the plain text using the public key
+ _cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException {
+
+ return _cipher.doFinal(plaintext);
+ }
+
+ }
+
+ final static String RSA15 = "RSA/ECB/PKCS1Padding";
+
+ public final static String ALGORITHM_NAME = "RSA1_5";
+
+ public Rsa15() {
+ super(ALGORITHM_NAME);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(KeyPair keyPair) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+ return CreateEncryptor(keyPair, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+ return new Rsa15Encryptor(keyPair, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(KeyPair keyPair) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+ return CreateDecryptor(keyPair, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+ return new Rsa15Decryptor(keyPair, provider);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaEncryption.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaEncryption.java
new file mode 100755
index 000000000000..83343057aa55
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaEncryption.java
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import com.microsoft.azure.keyvault.cryptography.AsymmetricEncryptionAlgorithm;
+
+public abstract class RsaEncryption extends AsymmetricEncryptionAlgorithm {
+
+ protected RsaEncryption(String name) {
+ super(name);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaOaep.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaOaep.java
new file mode 100755
index 000000000000..38c3e4131231
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaOaep.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+
+public final class RsaOaep extends RsaEncryption {
+
+ class RsaOaepDecryptor implements ICryptoTransform {
+
+ private final Cipher _cipher;
+
+ RsaOaepDecryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+
+ // Create a cipher object using the provider, if specified
+ if (provider == null) {
+ _cipher = Cipher.getInstance(RSAOAEP);
+ } else {
+ _cipher = Cipher.getInstance(RSAOAEP, provider);
+ }
+
+ // encrypt the plain text using the public key
+ _cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException {
+
+ return _cipher.doFinal(plaintext);
+ }
+
+ }
+
+ class RsaOaepEncryptor implements ICryptoTransform {
+
+ private final Cipher _cipher;
+
+ RsaOaepEncryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+
+ // Create a cipher object using the provider, if specified
+ if (provider == null) {
+ _cipher = Cipher.getInstance(RSAOAEP);
+ } else {
+ _cipher = Cipher.getInstance(RSAOAEP, provider);
+ }
+
+ // encrypt the plain text using the public key
+ _cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
+ }
+
+ @Override
+ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException {
+
+ return _cipher.doFinal(plaintext);
+ }
+
+ }
+
+ final static String RSAOAEP = "RSA/ECB/OAEPWithSHA1AndMGF1Padding";
+
+ public final static String ALGORITHM_NAME = "RSA-OAEP";
+
+ public RsaOaep() {
+ super(ALGORITHM_NAME);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(KeyPair keyPair) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+ return CreateEncryptor(keyPair, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateEncryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+
+ return new RsaOaepEncryptor(keyPair, provider);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(KeyPair keyPair) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+ return CreateDecryptor(keyPair, null);
+ }
+
+ @Override
+ public ICryptoTransform CreateDecryptor(KeyPair keyPair, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
+
+ return new RsaOaepDecryptor(keyPair, provider);
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaSignature.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaSignature.java
new file mode 100644
index 000000000000..84d2257ae217
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/RsaSignature.java
@@ -0,0 +1,210 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.cryptography.algorithms;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import com.microsoft.azure.keyvault.cryptography.AsymmetricSignatureAlgorithm;
+import com.microsoft.azure.keyvault.cryptography.ISignatureTransform;
+import com.microsoft.azure.keyvault.cryptography.Strings;
+
+public abstract class RsaSignature extends AsymmetricSignatureAlgorithm {
+
+ private static final BigInteger twoFiveSix = new BigInteger("256");
+ private static final byte[] sha256Prefix = new byte[] { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, (byte) 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
+
+ protected RsaSignature(String name) {
+ super(name);
+ }
+
+ protected int getOctetLength(int bits) {
+ return ( bits % 8 > 0 ) ? bits >> 3 + 1 : bits >> 3;
+ }
+
+ /*
+ * See https://tools.ietf.org/html/rfc3447#section-4.2
+ */
+ protected BigInteger OS2IP(byte[] x) {
+
+ if ( x == null || x.length == 0 ) {
+ throw new IllegalArgumentException("x");
+ }
+
+ return new BigInteger(1,x);
+ }
+
+ /*
+ * See https://tools.ietf.org/html/rfc3447#section-4.1
+ */
+ protected byte[] I2OSP(BigInteger x, int xLen) {
+
+ if ( x == null ) {
+ throw new IllegalArgumentException("x");
+ }
+
+ if ( xLen <= 0 ) {
+ throw new IllegalArgumentException("xLen");
+ }
+
+ if ( x.compareTo( twoFiveSix.pow(xLen) ) == 1 ) {
+ throw new IllegalArgumentException("integer too large");
+ }
+
+ byte[] bytes = x.toByteArray();
+
+ if ( bytes.length > xLen ) {
+ throw new IllegalArgumentException("integer too large");
+ }
+
+ byte[] result = new byte[xLen];
+
+ System.arraycopy(bytes, 0, result, xLen - bytes.length, bytes.length);
+
+ return result;
+ }
+
+ /*
+ * See https://tools.ietf.org/html/rfc3447#section-5.2.1
+ */
+ protected BigInteger RSASP1(RSAPrivateKey K, BigInteger m) {
+
+ if ( K == null ) {
+ throw new IllegalArgumentException("K");
+ }
+
+ if ( m == null ) {
+ throw new IllegalArgumentException("m");
+ }
+
+ BigInteger n = K.getModulus();
+ BigInteger d = K.getPrivateExponent();
+
+ if ( m.compareTo(BigInteger.ONE) == -1 || m.compareTo(n) != -1 ) {
+ throw new IllegalArgumentException("message representative out of range");
+ }
+
+ return m.modPow(d, n);
+ }
+
+ /*
+ * See https://tools.ietf.org/html/rfc3447#section-5.2.2
+ */
+ protected BigInteger RSAVP1(RSAPublicKey K, BigInteger s) {
+
+ if ( K == null ) {
+ throw new IllegalArgumentException("K");
+ }
+
+ if ( s == null ) {
+ throw new IllegalArgumentException("s");
+ }
+ BigInteger n = K.getModulus();
+ BigInteger e = K.getPublicExponent();
+
+ if ( s.compareTo(BigInteger.ONE) == -1 || s.compareTo(n) != -1 ) {
+ throw new IllegalArgumentException("message representative out of range");
+ }
+
+ return s.modPow(e, n);
+ }
+
+ /*
+ * See https://tools.ietf.org/html/rfc3447#section-9.2
+ */
+ protected byte[] EMSA_PKCS1_V1_5_ENCODE(byte[] m, int emLen, String algorithm) throws NoSuchAlgorithmException {
+
+ // Check m
+ if ( m == null || m.length == 0 ) {
+ throw new IllegalArgumentException("m");
+ }
+
+ MessageDigest messageDigest = null;
+
+ // Check algorithm
+ if ( Strings.isNullOrWhiteSpace(algorithm) ) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ // Only supported algorithms
+ if ( algorithm.equals("SHA-256") ) {
+
+ // Initialize digest
+ messageDigest = MessageDigest.getInstance("SHA-256");
+ } else {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ // Hash the message
+ byte[] digest = messageDigest.digest(m);
+
+ // Construct T, the DER encoded DigestInfo structure
+ return EMSA_PKCS1_V1_5_ENCODE_HASH(digest, emLen, algorithm);
+ }
+
+ /*
+ * See https://tools.ietf.org/html/rfc3447#section-9.2
+ */
+ protected byte[] EMSA_PKCS1_V1_5_ENCODE_HASH(byte[] h, int emLen, String algorithm) throws NoSuchAlgorithmException {
+
+ // Check m
+ if ( h == null || h.length == 0 ) {
+ throw new IllegalArgumentException("m");
+ }
+
+ byte[] algorithmPrefix = null;
+
+ // Check algorithm
+ if ( Strings.isNullOrWhiteSpace(algorithm) ) {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+ // Only supported algorithms
+ if ( algorithm.equals("SHA-256") ) {
+
+ // Initialize prefix and digest
+ algorithmPrefix = sha256Prefix;
+
+ if ( h.length != 32 ) {
+ throw new IllegalArgumentException("h is incorrect length for SHA-256");
+ }
+ } else {
+ throw new IllegalArgumentException("algorithm");
+ }
+
+
+ // Construct T, the DER encoded DigestInfo structure
+ byte[] T = new byte[algorithmPrefix.length + h.length];
+
+ System.arraycopy(algorithmPrefix, 0, T, 0, algorithmPrefix.length);
+ System.arraycopy(h, 0, T, algorithmPrefix.length, h.length);
+
+ if ( emLen < T.length + 11 ) {
+ throw new IllegalArgumentException("intended encoded message length too short");
+ }
+
+ // Construct PS
+ byte[] PS = new byte[emLen - T.length - 3];
+
+ for ( int i = 0; i < PS.length; i++ ) PS[i] = (byte) 0xff;
+
+ // Construct EM
+ byte[] EM = new byte[PS.length + T.length + 3];
+
+ EM[0] = 0x00; EM[1] = 0x01; EM[PS.length + 2] = 0x00;
+
+ System.arraycopy(PS, 0, EM, 2, PS.length);
+ System.arraycopy(T, 0, EM, PS.length + 3, T.length);
+
+ return EM;
+ }
+
+ public abstract ISignatureTransform createSignatureTransform(KeyPair keyPair);
+}
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/package-info.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/package-info.java
new file mode 100644
index 000000000000..f3101db3f04c
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/algorithms/package-info.java
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+
+/**
+ * This package contains cryptographic functions and implementations.
+ */
+package com.microsoft.azure.keyvault.cryptography.algorithms;
diff --git a/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/package-info.java b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/package-info.java
new file mode 100644
index 000000000000..5492e8c67761
--- /dev/null
+++ b/azure-keyvault-cryptography/src/main/java/com/microsoft/azure/keyvault/cryptography/package-info.java
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+
+/**
+ * This package contains cryptographic functions and implementations
+ * of RSA and symmetric keys that conform with the IKey interface.
+ */
+package com.microsoft.azure.keyvault.cryptography;
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcBCProviderTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcBCProviderTest.java
new file mode 100755
index 000000000000..043b2b54808b
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcBCProviderTest.java
@@ -0,0 +1,18 @@
+package com.microsoft.azure.keyvault.cryptography.test;
+
+import java.security.Provider;
+
+import org.junit.Before;
+
+public class AesCbcBCProviderTest extends AesCbcTest {
+
+ @Before
+ public void setUp() throws Exception {
+ try {
+ super.setProvider((Provider) Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance());
+ } catch (Exception ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcHmacShaBCProviderTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcHmacShaBCProviderTest.java
new file mode 100644
index 000000000000..5c7e07a27347
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcHmacShaBCProviderTest.java
@@ -0,0 +1,17 @@
+package com.microsoft.azure.keyvault.cryptography.test;
+
+import java.security.Provider;
+
+import org.junit.Before;
+
+public class AesCbcHmacShaBCProviderTest extends AesCbcHmacShaTest {
+
+ @Before
+ public void setUp() throws Exception {
+ try {
+ super.setProvider((Provider) Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance());
+ } catch (Exception ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcHmacShaTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcHmacShaTest.java
new file mode 100755
index 000000000000..ef588b4830e9
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcHmacShaTest.java
@@ -0,0 +1,267 @@
+package com.microsoft.azure.keyvault.cryptography.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+import java.security.Provider;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.microsoft.azure.keyvault.cryptography.IAuthenticatedCryptoTransform;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes128CbcHmacSha256;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes192CbcHmacSha384;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes256CbcHmacSha512;
+
+public class AesCbcHmacShaTest {
+
+ private Provider _provider = null;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ setProvider(null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ protected void setProvider(Provider provider) {
+ _provider = null;
+ }
+
+ @Test
+ public void testAes128CbcHmacSha256() {
+ // Arrange: These values are taken from Appendix B of the JWE specification at
+ // https://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-40#appendix-B
+ byte[] K = { (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, (byte)0x09, (byte)0x0a, (byte)0x0b, (byte)0x0c, (byte)0x0d, (byte)0x0e, (byte)0x0f,
+ (byte)0x10, (byte)0x11, (byte)0x12, (byte)0x13, (byte)0x14, (byte)0x15, (byte)0x16, (byte)0x17, (byte)0x18, (byte)0x19, (byte)0x1a, (byte)0x1b, (byte)0x1c, (byte)0x1d, (byte)0x1e, (byte)0x1f };
+ byte[] P = { (byte)0x41, (byte)0x20, (byte)0x63, (byte)0x69, (byte)0x70, (byte)0x68, (byte)0x65, (byte)0x72, (byte)0x20, (byte)0x73, (byte)0x79, (byte)0x73, (byte)0x74, (byte)0x65, (byte)0x6d, (byte)0x20,
+ (byte)0x6d, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x20, (byte)0x6e, (byte)0x6f, (byte)0x74, (byte)0x20, (byte)0x62, (byte)0x65, (byte)0x20, (byte)0x72, (byte)0x65, (byte)0x71, (byte)0x75,
+ (byte)0x69, (byte)0x72, (byte)0x65, (byte)0x64, (byte)0x20, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x62, (byte)0x65, (byte)0x20, (byte)0x73, (byte)0x65, (byte)0x63, (byte)0x72, (byte)0x65,
+ (byte)0x74, (byte)0x2c, (byte)0x20, (byte)0x61, (byte)0x6e, (byte)0x64, (byte)0x20, (byte)0x69, (byte)0x74, (byte)0x20, (byte)0x6d, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x20, (byte)0x62,
+ (byte)0x65, (byte)0x20, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x20, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x66, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x20, (byte)0x69,
+ (byte)0x6e, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x74, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x68, (byte)0x61, (byte)0x6e, (byte)0x64, (byte)0x73, (byte)0x20, (byte)0x6f, (byte)0x66,
+ (byte)0x20, (byte)0x74, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x65, (byte)0x6e, (byte)0x65, (byte)0x6d, (byte)0x79, (byte)0x20, (byte)0x77, (byte)0x69, (byte)0x74, (byte)0x68, (byte)0x6f,
+ (byte)0x75, (byte)0x74, (byte)0x20, (byte)0x69, (byte)0x6e, (byte)0x63, (byte)0x6f, (byte)0x6e, (byte)0x76, (byte)0x65, (byte)0x6e, (byte)0x69, (byte)0x65, (byte)0x6e, (byte)0x63, (byte)0x65 };
+ byte[] IV = { (byte)0x1a, (byte)0xf3, (byte)0x8c, (byte)0x2d, (byte)0xc2, (byte)0xb9, (byte)0x6f, (byte)0xfd, (byte)0xd8, (byte)0x66, (byte)0x94, (byte)0x09, (byte)0x23, (byte)0x41, (byte)0xbc, (byte)0x04 };
+ byte[] A = { (byte)0x54, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x73, (byte)0x65, (byte)0x63, (byte)0x6f, (byte)0x6e, (byte)0x64, (byte)0x20, (byte)0x70, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x63,
+ (byte)0x69, (byte)0x70, (byte)0x6c, (byte)0x65, (byte)0x20, (byte)0x6f, (byte)0x66, (byte)0x20, (byte)0x41, (byte)0x75, (byte)0x67, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x65, (byte)0x20,
+ (byte)0x4b, (byte)0x65, (byte)0x72, (byte)0x63, (byte)0x6b, (byte)0x68, (byte)0x6f, (byte)0x66, (byte)0x66, (byte)0x73 };
+ byte[] E = { (byte)0xc8, (byte)0x0e, (byte)0xdf, (byte)0xa3, (byte)0x2d, (byte)0xdf, (byte)0x39, (byte)0xd5, (byte)0xef, (byte)0x00, (byte)0xc0, (byte)0xb4, (byte)0x68, (byte)0x83, (byte)0x42, (byte)0x79,
+ (byte)0xa2, (byte)0xe4, (byte)0x6a, (byte)0x1b, (byte)0x80, (byte)0x49, (byte)0xf7, (byte)0x92, (byte)0xf7, (byte)0x6b, (byte)0xfe, (byte)0x54, (byte)0xb9, (byte)0x03, (byte)0xa9, (byte)0xc9,
+ (byte)0xa9, (byte)0x4a, (byte)0xc9, (byte)0xb4, (byte)0x7a, (byte)0xd2, (byte)0x65, (byte)0x5c, (byte)0x5f, (byte)0x10, (byte)0xf9, (byte)0xae, (byte)0xf7, (byte)0x14, (byte)0x27, (byte)0xe2,
+ (byte)0xfc, (byte)0x6f, (byte)0x9b, (byte)0x3f, (byte)0x39, (byte)0x9a, (byte)0x22, (byte)0x14, (byte)0x89, (byte)0xf1, (byte)0x63, (byte)0x62, (byte)0xc7, (byte)0x03, (byte)0x23, (byte)0x36,
+ (byte)0x09, (byte)0xd4, (byte)0x5a, (byte)0xc6, (byte)0x98, (byte)0x64, (byte)0xe3, (byte)0x32, (byte)0x1c, (byte)0xf8, (byte)0x29, (byte)0x35, (byte)0xac, (byte)0x40, (byte)0x96, (byte)0xc8,
+ (byte)0x6e, (byte)0x13, (byte)0x33, (byte)0x14, (byte)0xc5, (byte)0x40, (byte)0x19, (byte)0xe8, (byte)0xca, (byte)0x79, (byte)0x80, (byte)0xdf, (byte)0xa4, (byte)0xb9, (byte)0xcf, (byte)0x1b,
+ (byte)0x38, (byte)0x4c, (byte)0x48, (byte)0x6f, (byte)0x3a, (byte)0x54, (byte)0xc5, (byte)0x10, (byte)0x78, (byte)0x15, (byte)0x8e, (byte)0xe5, (byte)0xd7, (byte)0x9d, (byte)0xe5, (byte)0x9f,
+ (byte)0xbd, (byte)0x34, (byte)0xd8, (byte)0x48, (byte)0xb3, (byte)0xd6, (byte)0x95, (byte)0x50, (byte)0xa6, (byte)0x76, (byte)0x46, (byte)0x34, (byte)0x44, (byte)0x27, (byte)0xad, (byte)0xe5,
+ (byte)0x4b, (byte)0x88, (byte)0x51, (byte)0xff, (byte)0xb5, (byte)0x98, (byte)0xf7, (byte)0xf8, (byte)0x00, (byte)0x74, (byte)0xb9, (byte)0x47, (byte)0x3c, (byte)0x82, (byte)0xe2, (byte)0xdb };
+ byte[] T = { (byte)0x65, (byte)0x2c, (byte)0x3f, (byte)0xa3, (byte)0x6b, (byte)0x0a, (byte)0x7c, (byte)0x5b, (byte)0x32, (byte)0x19, (byte)0xfa, (byte)0xb3, (byte)0xa3, (byte)0x0b, (byte)0xc1, (byte)0xc4 };
+
+ Aes128CbcHmacSha256 algo = new Aes128CbcHmacSha256();
+
+ IAuthenticatedCryptoTransform transform = null;
+
+ byte[] encrypted = null;
+ byte[] tag = null;
+
+ try {
+ transform = (IAuthenticatedCryptoTransform) algo.CreateEncryptor(K, IV, A, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ encrypted = transform.doFinal(P);
+ tag = transform.getTag();
+
+ assertArrayEquals(E, encrypted);
+ assertArrayEquals(T, tag);
+
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ transform = (IAuthenticatedCryptoTransform)algo.CreateDecryptor(K, IV, A, T, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = transform.doFinal(encrypted);
+ tag = transform.getTag();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(P, decrypted);
+ assertArrayEquals(T, tag);
+ }
+
+
+ @Test
+ public void testAes192CbcHmacSha384() {
+ // Arrange: These values are taken from Appendix B of the JWE specification at
+ // https://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-40#appendix-B
+ byte[] K = { (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, (byte)0x09, (byte)0x0a, (byte)0x0b, (byte)0x0c, (byte)0x0d, (byte)0x0e, (byte)0x0f,
+ (byte)0x10, (byte)0x11, (byte)0x12, (byte)0x13, (byte)0x14, (byte)0x15, (byte)0x16, (byte)0x17, (byte)0x18, (byte)0x19, (byte)0x1a, (byte)0x1b, (byte)0x1c, (byte)0x1d, (byte)0x1e, (byte)0x1f,
+ (byte)0x20, (byte)0x21, (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25, (byte)0x26, (byte)0x27, (byte)0x28, (byte)0x29, (byte)0x2a, (byte)0x2b, (byte)0x2c, (byte)0x2d, (byte)0x2e, (byte)0x2f };
+ byte[] P = { (byte)0x41, (byte)0x20, (byte)0x63, (byte)0x69, (byte)0x70, (byte)0x68, (byte)0x65, (byte)0x72, (byte)0x20, (byte)0x73, (byte)0x79, (byte)0x73, (byte)0x74, (byte)0x65, (byte)0x6d, (byte)0x20,
+ (byte)0x6d, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x20, (byte)0x6e, (byte)0x6f, (byte)0x74, (byte)0x20, (byte)0x62, (byte)0x65, (byte)0x20, (byte)0x72, (byte)0x65, (byte)0x71, (byte)0x75,
+ (byte)0x69, (byte)0x72, (byte)0x65, (byte)0x64, (byte)0x20, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x62, (byte)0x65, (byte)0x20, (byte)0x73, (byte)0x65, (byte)0x63, (byte)0x72, (byte)0x65,
+ (byte)0x74, (byte)0x2c, (byte)0x20, (byte)0x61, (byte)0x6e, (byte)0x64, (byte)0x20, (byte)0x69, (byte)0x74, (byte)0x20, (byte)0x6d, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x20, (byte)0x62,
+ (byte)0x65, (byte)0x20, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x20, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x66, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x20, (byte)0x69,
+ (byte)0x6e, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x74, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x68, (byte)0x61, (byte)0x6e, (byte)0x64, (byte)0x73, (byte)0x20, (byte)0x6f, (byte)0x66,
+ (byte)0x20, (byte)0x74, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x65, (byte)0x6e, (byte)0x65, (byte)0x6d, (byte)0x79, (byte)0x20, (byte)0x77, (byte)0x69, (byte)0x74, (byte)0x68, (byte)0x6f,
+ (byte)0x75, (byte)0x74, (byte)0x20, (byte)0x69, (byte)0x6e, (byte)0x63, (byte)0x6f, (byte)0x6e, (byte)0x76, (byte)0x65, (byte)0x6e, (byte)0x69, (byte)0x65, (byte)0x6e, (byte)0x63, (byte)0x65 };
+ byte[] IV = { (byte)0x1a, (byte)0xf3, (byte)0x8c, (byte)0x2d, (byte)0xc2, (byte)0xb9, (byte)0x6f, (byte)0xfd, (byte)0xd8, (byte)0x66, (byte)0x94, (byte)0x09, (byte)0x23, (byte)0x41, (byte)0xbc, (byte)0x04 };
+ byte[] A = { (byte)0x54, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x73, (byte)0x65, (byte)0x63, (byte)0x6f, (byte)0x6e, (byte)0x64, (byte)0x20, (byte)0x70, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x63,
+ (byte)0x69, (byte)0x70, (byte)0x6c, (byte)0x65, (byte)0x20, (byte)0x6f, (byte)0x66, (byte)0x20, (byte)0x41, (byte)0x75, (byte)0x67, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x65, (byte)0x20,
+ (byte)0x4b, (byte)0x65, (byte)0x72, (byte)0x63, (byte)0x6b, (byte)0x68, (byte)0x6f, (byte)0x66, (byte)0x66, (byte)0x73 };
+ byte[] E = { (byte)0xea, (byte)0x65, (byte)0xda, (byte)0x6b, (byte)0x59, (byte)0xe6, (byte)0x1e, (byte)0xdb, (byte)0x41, (byte)0x9b, (byte)0xe6, (byte)0x2d, (byte)0x19, (byte)0x71, (byte)0x2a, (byte)0xe5,
+ (byte)0xd3, (byte)0x03, (byte)0xee, (byte)0xb5, (byte)0x00, (byte)0x52, (byte)0xd0, (byte)0xdf, (byte)0xd6, (byte)0x69, (byte)0x7f, (byte)0x77, (byte)0x22, (byte)0x4c, (byte)0x8e, (byte)0xdb,
+ (byte)0x00, (byte)0x0d, (byte)0x27, (byte)0x9b, (byte)0xdc, (byte)0x14, (byte)0xc1, (byte)0x07, (byte)0x26, (byte)0x54, (byte)0xbd, (byte)0x30, (byte)0x94, (byte)0x42, (byte)0x30, (byte)0xc6,
+ (byte)0x57, (byte)0xbe, (byte)0xd4, (byte)0xca, (byte)0x0c, (byte)0x9f, (byte)0x4a, (byte)0x84, (byte)0x66, (byte)0xf2, (byte)0x2b, (byte)0x22, (byte)0x6d, (byte)0x17, (byte)0x46, (byte)0x21,
+ (byte)0x4b, (byte)0xf8, (byte)0xcf, (byte)0xc2, (byte)0x40, (byte)0x0a, (byte)0xdd, (byte)0x9f, (byte)0x51, (byte)0x26, (byte)0xe4, (byte)0x79, (byte)0x66, (byte)0x3f, (byte)0xc9, (byte)0x0b,
+ (byte)0x3b, (byte)0xed, (byte)0x78, (byte)0x7a, (byte)0x2f, (byte)0x0f, (byte)0xfc, (byte)0xbf, (byte)0x39, (byte)0x04, (byte)0xbe, (byte)0x2a, (byte)0x64, (byte)0x1d, (byte)0x5c, (byte)0x21,
+ (byte)0x05, (byte)0xbf, (byte)0xe5, (byte)0x91, (byte)0xba, (byte)0xe2, (byte)0x3b, (byte)0x1d, (byte)0x74, (byte)0x49, (byte)0xe5, (byte)0x32, (byte)0xee, (byte)0xf6, (byte)0x0a, (byte)0x9a,
+ (byte)0xc8, (byte)0xbb, (byte)0x6c, (byte)0x6b, (byte)0x01, (byte)0xd3, (byte)0x5d, (byte)0x49, (byte)0x78, (byte)0x7b, (byte)0xcd, (byte)0x57, (byte)0xef, (byte)0x48, (byte)0x49, (byte)0x27,
+ (byte)0xf2, (byte)0x80, (byte)0xad, (byte)0xc9, (byte)0x1a, (byte)0xc0, (byte)0xc4, (byte)0xe7, (byte)0x9c, (byte)0x7b, (byte)0x11, (byte)0xef, (byte)0xc6, (byte)0x00, (byte)0x54, (byte)0xe3 };
+ byte[] T = { (byte)0x84, (byte)0x90, (byte)0xac, (byte)0x0e, (byte)0x58, (byte)0x94, (byte)0x9b, (byte)0xfe, (byte)0x51, (byte)0x87, (byte)0x5d, (byte)0x73, (byte)0x3f, (byte)0x93, (byte)0xac, (byte)0x20,
+ (byte)0x75, (byte)0x16, (byte)0x80, (byte)0x39, (byte)0xcc, (byte)0xc7, (byte)0x33, (byte)0xd7 };
+
+ Aes192CbcHmacSha384 algo = new Aes192CbcHmacSha384();
+
+ IAuthenticatedCryptoTransform transform = null;
+
+ byte[] encrypted = null;
+ byte[] tag = null;
+
+ try {
+ transform = (IAuthenticatedCryptoTransform) algo.CreateEncryptor(K, IV, A, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ encrypted = transform.doFinal(P);
+ tag = transform.getTag();
+
+ assertArrayEquals(E, encrypted);
+ assertArrayEquals(T, tag);
+
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ transform = (IAuthenticatedCryptoTransform)algo.CreateDecryptor(K, IV, A, T, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = transform.doFinal(encrypted);
+ tag = transform.getTag();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(P, decrypted);
+ assertArrayEquals(T, tag);
+ }
+ @Test
+ public void testAes256CbcHmacSha512() {
+ // Arrange: These values are taken from Appendix B of the JWE specification at
+ // https://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-40#appendix-B
+ byte[] K = { (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, (byte)0x09, (byte)0x0a, (byte)0x0b, (byte)0x0c, (byte)0x0d, (byte)0x0e, (byte)0x0f,
+ (byte)0x10, (byte)0x11, (byte)0x12, (byte)0x13, (byte)0x14, (byte)0x15, (byte)0x16, (byte)0x17, (byte)0x18, (byte)0x19, (byte)0x1a, (byte)0x1b, (byte)0x1c, (byte)0x1d, (byte)0x1e, (byte)0x1f,
+ (byte)0x20, (byte)0x21, (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25, (byte)0x26, (byte)0x27, (byte)0x28, (byte)0x29, (byte)0x2a, (byte)0x2b, (byte)0x2c, (byte)0x2d, (byte)0x2e, (byte)0x2f,
+ (byte)0x30, (byte)0x31, (byte)0x32, (byte)0x33, (byte)0x34, (byte)0x35, (byte)0x36, (byte)0x37, (byte)0x38, (byte)0x39, (byte)0x3a, (byte)0x3b, (byte)0x3c, (byte)0x3d, (byte)0x3e, (byte)0x3f };
+ byte[] P = { (byte)0x41, (byte)0x20, (byte)0x63, (byte)0x69, (byte)0x70, (byte)0x68, (byte)0x65, (byte)0x72, (byte)0x20, (byte)0x73, (byte)0x79, (byte)0x73, (byte)0x74, (byte)0x65, (byte)0x6d, (byte)0x20,
+ (byte)0x6d, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x20, (byte)0x6e, (byte)0x6f, (byte)0x74, (byte)0x20, (byte)0x62, (byte)0x65, (byte)0x20, (byte)0x72, (byte)0x65, (byte)0x71, (byte)0x75,
+ (byte)0x69, (byte)0x72, (byte)0x65, (byte)0x64, (byte)0x20, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x62, (byte)0x65, (byte)0x20, (byte)0x73, (byte)0x65, (byte)0x63, (byte)0x72, (byte)0x65,
+ (byte)0x74, (byte)0x2c, (byte)0x20, (byte)0x61, (byte)0x6e, (byte)0x64, (byte)0x20, (byte)0x69, (byte)0x74, (byte)0x20, (byte)0x6d, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x20, (byte)0x62,
+ (byte)0x65, (byte)0x20, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x20, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x66, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x20, (byte)0x69,
+ (byte)0x6e, (byte)0x74, (byte)0x6f, (byte)0x20, (byte)0x74, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x68, (byte)0x61, (byte)0x6e, (byte)0x64, (byte)0x73, (byte)0x20, (byte)0x6f, (byte)0x66,
+ (byte)0x20, (byte)0x74, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x65, (byte)0x6e, (byte)0x65, (byte)0x6d, (byte)0x79, (byte)0x20, (byte)0x77, (byte)0x69, (byte)0x74, (byte)0x68, (byte)0x6f,
+ (byte)0x75, (byte)0x74, (byte)0x20, (byte)0x69, (byte)0x6e, (byte)0x63, (byte)0x6f, (byte)0x6e, (byte)0x76, (byte)0x65, (byte)0x6e, (byte)0x69, (byte)0x65, (byte)0x6e, (byte)0x63, (byte)0x65 };
+ byte[] IV = { (byte)0x1a, (byte)0xf3, (byte)0x8c, (byte)0x2d, (byte)0xc2, (byte)0xb9, (byte)0x6f, (byte)0xfd, (byte)0xd8, (byte)0x66, (byte)0x94, (byte)0x09, (byte)0x23, (byte)0x41, (byte)0xbc, (byte)0x04 };
+ byte[] A = { (byte)0x54, (byte)0x68, (byte)0x65, (byte)0x20, (byte)0x73, (byte)0x65, (byte)0x63, (byte)0x6f, (byte)0x6e, (byte)0x64, (byte)0x20, (byte)0x70, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x63,
+ (byte)0x69, (byte)0x70, (byte)0x6c, (byte)0x65, (byte)0x20, (byte)0x6f, (byte)0x66, (byte)0x20, (byte)0x41, (byte)0x75, (byte)0x67, (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x65, (byte)0x20,
+ (byte)0x4b, (byte)0x65, (byte)0x72, (byte)0x63, (byte)0x6b, (byte)0x68, (byte)0x6f, (byte)0x66, (byte)0x66, (byte)0x73 };
+ byte[] E = { (byte)0x4a, (byte)0xff, (byte)0xaa, (byte)0xad, (byte)0xb7, (byte)0x8c, (byte)0x31, (byte)0xc5, (byte)0xda, (byte)0x4b, (byte)0x1b, (byte)0x59, (byte)0x0d, (byte)0x10, (byte)0xff, (byte)0xbd,
+ (byte)0x3d, (byte)0xd8, (byte)0xd5, (byte)0xd3, (byte)0x02, (byte)0x42, (byte)0x35, (byte)0x26, (byte)0x91, (byte)0x2d, (byte)0xa0, (byte)0x37, (byte)0xec, (byte)0xbc, (byte)0xc7, (byte)0xbd,
+ (byte)0x82, (byte)0x2c, (byte)0x30, (byte)0x1d, (byte)0xd6, (byte)0x7c, (byte)0x37, (byte)0x3b, (byte)0xcc, (byte)0xb5, (byte)0x84, (byte)0xad, (byte)0x3e, (byte)0x92, (byte)0x79, (byte)0xc2,
+ (byte)0xe6, (byte)0xd1, (byte)0x2a, (byte)0x13, (byte)0x74, (byte)0xb7, (byte)0x7f, (byte)0x07, (byte)0x75, (byte)0x53, (byte)0xdf, (byte)0x82, (byte)0x94, (byte)0x10, (byte)0x44, (byte)0x6b,
+ (byte)0x36, (byte)0xeb, (byte)0xd9, (byte)0x70, (byte)0x66, (byte)0x29, (byte)0x6a, (byte)0xe6, (byte)0x42, (byte)0x7e, (byte)0xa7, (byte)0x5c, (byte)0x2e, (byte)0x08, (byte)0x46, (byte)0xa1,
+ (byte)0x1a, (byte)0x09, (byte)0xcc, (byte)0xf5, (byte)0x37, (byte)0x0d, (byte)0xc8, (byte)0x0b, (byte)0xfe, (byte)0xcb, (byte)0xad, (byte)0x28, (byte)0xc7, (byte)0x3f, (byte)0x09, (byte)0xb3,
+ (byte)0xa3, (byte)0xb7, (byte)0x5e, (byte)0x66, (byte)0x2a, (byte)0x25, (byte)0x94, (byte)0x41, (byte)0x0a, (byte)0xe4, (byte)0x96, (byte)0xb2, (byte)0xe2, (byte)0xe6, (byte)0x60, (byte)0x9e,
+ (byte)0x31, (byte)0xe6, (byte)0xe0, (byte)0x2c, (byte)0xc8, (byte)0x37, (byte)0xf0, (byte)0x53, (byte)0xd2, (byte)0x1f, (byte)0x37, (byte)0xff, (byte)0x4f, (byte)0x51, (byte)0x95, (byte)0x0b,
+ (byte)0xbe, (byte)0x26, (byte)0x38, (byte)0xd0, (byte)0x9d, (byte)0xd7, (byte)0xa4, (byte)0x93, (byte)0x09, (byte)0x30, (byte)0x80, (byte)0x6d, (byte)0x07, (byte)0x03, (byte)0xb1, (byte)0xf6 };
+ byte[] T = { (byte)0x4d, (byte)0xd3, (byte)0xb4, (byte)0xc0, (byte)0x88, (byte)0xa7, (byte)0xf4, (byte)0x5c, (byte)0x21, (byte)0x68, (byte)0x39, (byte)0x64, (byte)0x5b, (byte)0x20, (byte)0x12, (byte)0xbf,
+ (byte)0x2e, (byte)0x62, (byte)0x69, (byte)0xa8, (byte)0xc5, (byte)0x6a, (byte)0x81, (byte)0x6d, (byte)0xbc, (byte)0x1b, (byte)0x26, (byte)0x77, (byte)0x61, (byte)0x95, (byte)0x5b, (byte)0xc5 };
+
+ Aes256CbcHmacSha512 algo = new Aes256CbcHmacSha512();
+
+ IAuthenticatedCryptoTransform transform = null;
+
+ byte[] encrypted = null;
+ byte[] tag = null;
+
+ try {
+ transform = (IAuthenticatedCryptoTransform) algo.CreateEncryptor(K, IV, A, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ encrypted = transform.doFinal(P);
+ tag = transform.getTag();
+
+ assertArrayEquals(E, encrypted);
+ assertArrayEquals(T, tag);
+
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ transform = (IAuthenticatedCryptoTransform)algo.CreateDecryptor(K, IV, A, T, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = transform.doFinal(encrypted);
+ tag = transform.getTag();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(P, decrypted);
+ assertArrayEquals(T, tag);
+ }
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcTest.java
new file mode 100755
index 000000000000..7b41487ef988
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesCbcTest.java
@@ -0,0 +1,230 @@
+package com.microsoft.azure.keyvault.cryptography.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+import java.security.Provider;
+import java.util.Arrays;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Aes128Cbc;
+
+public class AesCbcTest {
+
+ private Provider _provider = null;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ setProvider(null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ protected void setProvider(Provider provider) {
+ _provider = provider;
+ }
+
+ @Test
+ public void testAes128CbcOneBlock() {
+ // Note that AES128CBC as implemented in this library uses PKCS7 padding mode where the test
+ // vectors from RFC3602 do not use padding.
+ byte[] CEK = { 0x06, (byte)0xa9, 0x21, 0x40, 0x36, (byte)0xb8, (byte)0xa1, 0x5b, 0x51, 0x2e, 0x03, (byte)0xd5, 0x34, 0x12, 0x00, 0x06 };
+ byte[] PLAIN = "Single block msg".getBytes();
+ byte[] IV = { 0x3d, (byte)0xaf, (byte)0xba, 0x42, (byte)0x9d, (byte)0x9e, (byte)0xb4, 0x30, (byte)0xb4, 0x22, (byte)0xda, (byte)0x80, 0x2c, (byte)0x9f, (byte)0xac, 0x41 };
+ byte[] ED = { (byte)0xe3, 0x53, 0x77, (byte)0x9c, 0x10, 0x79, (byte)0xae, (byte)0xb8, 0x27, 0x08, (byte)0x94, 0x2d, (byte)0xbe, 0x77, 0x18, 0x1a };
+
+ Aes128Cbc algo = new Aes128Cbc();
+ byte[] encrypted = null;
+
+ ICryptoTransform encryptor = null;
+ try {
+ encryptor = algo.CreateEncryptor(CEK, IV, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ encrypted = encryptor.doFinal(PLAIN);
+
+ // Assert: we only compare the first 16 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(encrypted, 0, 16), ED);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ICryptoTransform decryptor = null;
+ try {
+ decryptor = algo.CreateDecryptor(CEK, IV, null, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(encrypted);
+
+ // Assert: we only compare the first 16 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(decrypted, 0, 16), PLAIN);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAes128CbcTwoBlock() {
+ // Note that AES128CBC as implemented in this library uses PKCS7 padding mode where the test
+ // vectors do not use padding.
+ byte[] CEK = { (byte)0xc2, (byte)0x86, 0x69, 0x6d, (byte)0x88, 0x7c, (byte)0x9a, (byte)0xa0, 0x61, 0x1b, (byte)0xbb, 0x3e, 0x20, 0x25, (byte)0xa4, 0x5a };
+ byte[] PLAIN = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
+ byte[] IV = { 0x56, 0x2e, 0x17, (byte)0x99, 0x6d, 0x09, 0x3d, 0x28, (byte)0xdd, (byte)0xb3, (byte)0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 };
+ byte[] ED = { (byte)0xd2, (byte)0x96, (byte)0xcd, (byte)0x94, (byte)0xc2, (byte)0xcc, (byte)0xcf, (byte)0x8a, 0x3a, (byte)0x86, 0x30, 0x28, (byte)0xb5, (byte)0xe1, (byte)0xdc, 0x0a, 0x75, (byte)0x86, 0x60, 0x2d, 0x25, 0x3c, (byte)0xff, (byte)0xf9, 0x1b, (byte)0x82, 0x66, (byte)0xbe, (byte)0xa6, (byte)0xd6, 0x1a, (byte)0xb1 };
+
+ Aes128Cbc algo = new Aes128Cbc();
+ byte[] encrypted = null;
+
+ ICryptoTransform encryptor = null;
+ try {
+ encryptor = algo.CreateEncryptor(CEK, IV, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ encrypted = encryptor.doFinal(PLAIN);
+
+ // Assert: we only compare the first 32 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(encrypted, 0, 32), ED);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ICryptoTransform decryptor = null;
+ try {
+ decryptor = algo.CreateDecryptor(CEK, IV, null, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(encrypted);
+
+ // Assert: we only compare the first 32 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(decrypted, 0, 32), PLAIN);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAes128CbcOneBlock_ExcessKeyMaterial() {
+ // Note that AES128CBC as implemented in this library uses PKCS7 padding mode where the test
+ // vectors from RFC3602 do not use padding.
+ byte[] CEK = { 0x06, (byte)0xa9, 0x21, 0x40, 0x36, (byte)0xb8, (byte)0xa1, 0x5b, 0x51, 0x2e, 0x03, (byte)0xd5, 0x34, 0x12, 0x00, 0x06, (byte)0xc2, (byte)0x86, 0x69, 0x6d, (byte)0x88, 0x7c, (byte)0x9a, (byte)0xa0, 0x61, 0x1b, (byte)0xbb, 0x3e, 0x20, 0x25, (byte)0xa4, 0x5a };
+ byte[] PLAIN = "Single block msg".getBytes();
+ byte[] IV = { 0x3d, (byte)0xaf, (byte)0xba, 0x42, (byte)0x9d, (byte)0x9e, (byte)0xb4, 0x30, (byte)0xb4, 0x22, (byte)0xda, (byte)0x80, 0x2c, (byte)0x9f, (byte)0xac, 0x41 };
+ byte[] ED = { (byte)0xe3, 0x53, 0x77, (byte)0x9c, 0x10, 0x79, (byte)0xae, (byte)0xb8, 0x27, 0x08, (byte)0x94, 0x2d, (byte)0xbe, 0x77, 0x18, 0x1a };
+
+ Aes128Cbc algo = new Aes128Cbc();
+ byte[] encrypted = null;
+
+ ICryptoTransform encryptor = null;
+ try {
+ encryptor = algo.CreateEncryptor(CEK, IV, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ encrypted = encryptor.doFinal(PLAIN);
+
+ // Assert: we only compare the first 16 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(encrypted, 0, 16),ED);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ICryptoTransform decryptor = null;
+ try {
+ decryptor = algo.CreateDecryptor(CEK, IV, null, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(encrypted);
+
+ // Assert: we only compare the first 16 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(decrypted, 0, 16), PLAIN);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAes128CbcTwoBlock_ExcessKeyMaterial() {
+ // Note that AES128CBC as implemented in this library uses PKCS7 padding mode where the test
+ // vectors do not use padding.
+ byte[] CEK = { (byte)0xc2, (byte)0x86, 0x69, 0x6d, (byte)0x88, 0x7c, (byte)0x9a, (byte)0xa0, 0x61, 0x1b, (byte)0xbb, 0x3e, 0x20, 0x25, (byte)0xa4, 0x5a, (byte)0xc2, (byte)0x86, 0x69, 0x6d, (byte)0x88, 0x7c, (byte)0x9a, (byte)0xa0, 0x61, 0x1b, (byte)0xbb, 0x3e, 0x20, 0x25, (byte)0xa4, 0x5a };
+ byte[] PLAIN = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
+ byte[] IV = { 0x56, 0x2e, 0x17, (byte)0x99, 0x6d, 0x09, 0x3d, 0x28, (byte)0xdd, (byte)0xb3, (byte)0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 };
+ byte[] ED = { (byte)0xd2, (byte)0x96, (byte)0xcd, (byte)0x94, (byte)0xc2, (byte)0xcc, (byte)0xcf, (byte)0x8a, 0x3a, (byte)0x86, 0x30, 0x28, (byte)0xb5, (byte)0xe1, (byte)0xdc, 0x0a, 0x75, (byte)0x86, 0x60, 0x2d, 0x25, 0x3c, (byte)0xff, (byte)0xf9, 0x1b, (byte)0x82, 0x66, (byte)0xbe, (byte)0xa6, (byte)0xd6, 0x1a, (byte)0xb1 };
+
+ Aes128Cbc algo = new Aes128Cbc();
+ byte[] encrypted = null;
+
+ ICryptoTransform encryptor = null;
+ try {
+ encryptor = algo.CreateEncryptor(CEK, IV, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try {
+ encrypted = encryptor.doFinal(PLAIN);
+
+ // Assert: we only compare the first 32 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(encrypted, 0, 32), ED);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ICryptoTransform decryptor = null;
+ try {
+ decryptor = algo.CreateDecryptor(CEK, IV, null, null, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(encrypted);
+
+ // Assert: we only compare the first 32 bytes as this library uses PKCS7 padding
+ assertArrayEquals(Arrays.copyOfRange(decrypted, 0, 32), PLAIN);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesKwBCProviderTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesKwBCProviderTest.java
new file mode 100755
index 000000000000..480db6f2e896
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesKwBCProviderTest.java
@@ -0,0 +1,34 @@
+/**
+ *
+ * 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.cryptography.test;
+
+import java.security.Provider;
+import org.junit.Before;
+
+public class AesKwBCProviderTest extends AesKwTest {
+
+ @Before
+ public void setUp() throws Exception {
+ try {
+ super.setProvider((Provider) Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance());
+ } catch (Exception ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesKwTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesKwTest.java
new file mode 100755
index 000000000000..e79e5569fe71
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/AesKwTest.java
@@ -0,0 +1,429 @@
+/**
+ *
+ * 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.cryptography.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import javax.crypto.Cipher;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.microsoft.azure.keyvault.cryptography.ICryptoTransform;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw128;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw192;
+import com.microsoft.azure.keyvault.cryptography.algorithms.AesKw256;
+
+public class AesKwTest {
+
+ // Always null for the default provider
+ private Provider _provider = null;
+
+ private static boolean hasUnlimitedCrypto() {
+ try {
+ return Cipher.getMaxAllowedKeyLength("RC5") >= 256;
+ } catch (NoSuchAlgorithmException e) {
+ return false;
+ }
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ protected void setProvider(Provider provider) {
+ _provider = provider;
+ }
+
+ @Test
+ public void KeyVault_AesKw128() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x1F, (byte) 0xA6, (byte) 0x8B, 0x0A, (byte) 0x81, 0x12, (byte) 0xB4, 0x47, (byte) 0xAE, (byte) 0xF3, 0x4B, (byte) 0xD8, (byte) 0xFB, 0x5A, 0x7B, (byte) 0x82, (byte) 0x9D, 0x3E, (byte) 0x86, 0x23, 0x71, (byte) 0xD2, (byte) 0xCF, (byte) 0xE5 };
+
+ AesKw kw = new AesKw128();
+
+ ICryptoTransform encryptor = null;
+
+ try {
+ encryptor = kw.CreateEncryptor(KEK, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = encryptor.doFinal(CEK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ ICryptoTransform decryptor = null;
+
+ try {
+ decryptor = kw.CreateDecryptor(KEK, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(EK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ @Test
+ public void KeyVault_AesKw192() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { (byte) 0x96, 0x77, (byte) 0x8B, 0x25, (byte) 0xAE, 0x6C, (byte) 0xA4, 0x35, (byte) 0xF9, 0x2B, 0x5B, (byte) 0x97, (byte) 0xC0, 0x50, (byte) 0xAE, (byte) 0xD2, 0x46, (byte) 0x8A, (byte) 0xB8, (byte) 0xA1, 0x7A, (byte) 0xD8, 0x4E, 0x5D };
+
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ AesKw kw = new AesKw192();
+
+ ICryptoTransform encryptor = null;
+
+ try {
+ encryptor = kw.CreateEncryptor(KEK, _provider);
+
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] encrypted = null;
+
+ try {
+ encrypted = encryptor.doFinal(CEK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+
+ ICryptoTransform decryptor = null;
+
+ try {
+ decryptor = kw.CreateDecryptor(KEK, _provider);
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(EK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+ }
+
+ @Test
+ public void KeyVault_AesKw256() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x64, (byte) 0xE8, (byte) 0xC3, (byte) 0xF9, (byte) 0xCE, 0x0F, 0x5B, (byte) 0xA2, 0x63, (byte) 0xE9, 0x77, 0x79, 0x05, (byte) 0x81, (byte) 0x8A, 0x2A, (byte) 0x93, (byte) 0xC8, 0x19, 0x1E, 0x7D, 0x6E, (byte) 0x8A, (byte) 0xE7 };
+
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ AesKw kw = new AesKw256();
+
+ ICryptoTransform encryptor = null;
+
+ try {
+ encryptor = kw.CreateEncryptor(KEK, _provider);
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] encrypted = null;
+
+ try {
+ encrypted = encryptor.doFinal(CEK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+
+ ICryptoTransform decryptor = null;
+
+ try {
+ decryptor = kw.CreateDecryptor(KEK, _provider);
+
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(EK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+ }
+
+ @Test
+ public void KeyVault_AesKw128_ExcessKeyMaterial() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte)0x88, (byte)0x99, (byte)0xAA, (byte)0xBB, (byte)0xCC, (byte)0xDD, (byte)0xEE, (byte)0xFF };
+ byte[] EK = { 0x1F, (byte)0xA6, (byte)0x8B, 0x0A, (byte)0x81, 0x12, (byte)0xB4, 0x47, (byte)0xAE, (byte)0xF3, 0x4B, (byte)0xD8, (byte)0xFB, 0x5A, 0x7B, (byte)0x82, (byte)0x9D, 0x3E, (byte)0x86, 0x23, 0x71, (byte)0xD2, (byte)0xCF, (byte)0xE5 };
+
+ AesKw kw = new AesKw128();
+
+ ICryptoTransform encryptor = null;
+
+ try {
+ encryptor = kw.CreateEncryptor(KEK, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = encryptor.doFinal(CEK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ ICryptoTransform decryptor = null;
+
+ try {
+ decryptor = kw.CreateDecryptor(KEK, _provider);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(EK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ @Test
+ public void KeyVault_AesKw192_ExcessKeyMaterial() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { (byte) 0x96, 0x77, (byte) 0x8B, 0x25, (byte) 0xAE, 0x6C, (byte) 0xA4, 0x35, (byte) 0xF9, 0x2B, 0x5B, (byte) 0x97, (byte) 0xC0, 0x50, (byte) 0xAE, (byte) 0xD2, 0x46, (byte) 0x8A, (byte) 0xB8, (byte) 0xA1, 0x7A, (byte) 0xD8, 0x4E, 0x5D };
+
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ AesKw kw = new AesKw192();
+
+ ICryptoTransform encryptor = null;
+
+ try {
+ encryptor = kw.CreateEncryptor(KEK, _provider);
+
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] encrypted = null;
+
+ try {
+ encrypted = encryptor.doFinal(CEK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+
+ ICryptoTransform decryptor = null;
+
+ try {
+ decryptor = kw.CreateDecryptor(KEK, _provider);
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(EK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+ }
+
+ @Test
+ public void KeyVault_AesKw256_ExcessKeyMaterial() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x64, (byte) 0xE8, (byte) 0xC3, (byte) 0xF9, (byte) 0xCE, 0x0F, 0x5B, (byte) 0xA2, 0x63, (byte) 0xE9, 0x77, 0x79, 0x05, (byte) 0x81, (byte) 0x8A, 0x2A, (byte) 0x93, (byte) 0xC8, 0x19, 0x1E, 0x7D, 0x6E, (byte) 0x8A, (byte) 0xE7 };
+
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ AesKw kw = new AesKw256();
+
+ ICryptoTransform encryptor = null;
+
+ try {
+ encryptor = kw.CreateEncryptor(KEK, _provider);
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] encrypted = null;
+
+ try {
+ encrypted = encryptor.doFinal(CEK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+
+ ICryptoTransform decryptor = null;
+
+ try {
+ decryptor = kw.CreateDecryptor(KEK, _provider);
+
+ if (!unlimited) fail("Expected InvalidKeyException");
+ } catch (InvalidKeyException e) {
+ if (unlimited) fail("InvalidKeyException");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ if (unlimited) {
+ byte[] decrypted = null;
+
+ try {
+ decrypted = decryptor.doFinal(EK);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/RsaKeyBCProviderTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/RsaKeyBCProviderTest.java
new file mode 100644
index 000000000000..c9a9c70acaeb
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/RsaKeyBCProviderTest.java
@@ -0,0 +1,16 @@
+package com.microsoft.azure.keyvault.cryptography.test;
+
+import java.security.Provider;
+import org.junit.Before;
+
+public class RsaKeyBCProviderTest extends RsaKeyTest {
+
+ @Before
+ public void setUp() throws Exception {
+ try {
+ super.setProvider((Provider) Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance());
+ } catch (Exception ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/RsaKeyTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/RsaKeyTest.java
new file mode 100755
index 000000000000..799827bd349c
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/RsaKeyTest.java
@@ -0,0 +1,171 @@
+package com.microsoft.azure.keyvault.cryptography.test;
+
+import static org.junit.Assert.*;
+
+import java.security.MessageDigest;
+import java.security.Provider;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.tuple.Triple;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.azure.keyvault.cryptography.RsaKey;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Rs256;
+import com.microsoft.azure.keyvault.cryptography.algorithms.Rsa15;
+import com.microsoft.azure.keyvault.cryptography.algorithms.RsaOaep;
+import com.microsoft.azure.keyvault.webkey.JsonWebKey;
+
+public class RsaKeyTest {
+
+ // A Content Encryption Key, or Message. This value is kept consistent with the .NET
+ // unit test cases to enable cross platform testing.
+ static final byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte)0x88, (byte)0x99, (byte)0xAA, (byte)0xBB, (byte)0xCC, (byte)0xDD, (byte)0xEE, (byte)0xFF };
+ static final String CrossPlatformHash = "qPrtarvzXBKksm5A9v6xnXNtkARcg7n5ox9jjTI+aBE=";
+ static final String CrossPlatformSignature = "RaNc+8WcWxplS8I7ynJLSoLJKz+dgBvrZhIGH3VFlTTyzu7b9d+lpaV9IKhzCNBsgSysKhgL7EZwVCOTBZ4m6xvKSXqVFXYaBPyBTD7VoKPMYMW6ai5x6xV5XAMaZPfMkff3Deg/RXcc8xQ28FhYuUa8yly01GySY4Hk55anEvb2wBxSy1UGun/0LE1lYH3C3XEgSry4cEkJHDJl1hp+wB4J/noXOqn5ECGU+/4ehBJOyW1gtUH0/gRe8yXnDH0AXepHRyH8iBHLWlKX1r+1/OrMulqOoi82RZzJlTyEz9X+bsQhllqGF6n3hdLS6toH9o7wUtwYNqSx82JuQT6iMg==";
+
+ private Provider _provider = null;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ protected void setProvider(Provider provider) {
+ _provider = provider;
+ }
+
+ @Test
+ public void testRsa15() throws Exception {
+
+ RsaKey key = getTestRsaKey();
+
+ // Wrap and Unwrap
+ Pair wrapped = key.wrapKeyAsync(CEK, Rsa15.ALGORITHM_NAME).get();
+ byte[] unwrapped = key.unwrapKeyAsync(wrapped.getLeft(), wrapped.getRight()).get();
+
+ // Assert
+ assertEquals(Rsa15.ALGORITHM_NAME, wrapped.getRight());
+ assertArrayEquals(CEK, unwrapped);
+
+ // Encrypt and Decrypt
+ Triple encrypted = key.encryptAsync(CEK, null, null, Rsa15.ALGORITHM_NAME).get();
+ byte[] decrypted = key.decryptAsync(encrypted.getLeft(), null, null, null, encrypted.getRight()).get();
+
+ // Assert
+ assertEquals(Rsa15.ALGORITHM_NAME, encrypted.getRight());
+ assertArrayEquals(CEK, decrypted);
+
+ key.close();
+ }
+
+ @Test
+ public void testRsaOaep() throws Exception {
+
+ RsaKey key = getTestRsaKey();
+
+ // Wrap and Unwrap
+ Pair wrapped = key.wrapKeyAsync(CEK, RsaOaep.ALGORITHM_NAME).get();
+ byte[] unwrapped = key.unwrapKeyAsync(wrapped.getLeft(), wrapped.getRight()).get();
+
+ // Assert
+ assertEquals(RsaOaep.ALGORITHM_NAME, wrapped.getRight());
+ assertArrayEquals(CEK, unwrapped);
+
+ // Encrypt and Decrypt
+ Triple encrypted = key.encryptAsync(CEK, null, null, RsaOaep.ALGORITHM_NAME).get();
+ byte[] decrypted = key.decryptAsync(encrypted.getLeft(), null, null, null, encrypted.getRight()).get();
+
+ // Assert
+ assertEquals(RsaOaep.ALGORITHM_NAME, encrypted.getRight());
+ assertArrayEquals(CEK, decrypted);
+
+ key.close();
+ }
+
+ @Test
+ public void testDefaultAlgorithm() throws Exception {
+
+ RsaKey key = getTestRsaKey();
+
+ assertEquals(RsaOaep.ALGORITHM_NAME, key.getDefaultEncryptionAlgorithm());
+ assertEquals(RsaOaep.ALGORITHM_NAME, key.getDefaultKeyWrapAlgorithm());
+ assertEquals(Rs256.ALGORITHM_NAME, key.getDefaultSignatureAlgorithm());
+
+ // Wrap and Unwrap
+ Pair wrapped = key.wrapKeyAsync(CEK, key.getDefaultKeyWrapAlgorithm()).get();
+ byte[] unwrapped = key.unwrapKeyAsync(wrapped.getLeft(), wrapped.getRight()).get();
+
+ // Assert
+ assertEquals(RsaOaep.ALGORITHM_NAME, wrapped.getRight());
+ assertArrayEquals(CEK, unwrapped);
+
+ // Encrypt and Decrypt
+ Triple encrypted = key.encryptAsync(CEK, null, null, key.getDefaultEncryptionAlgorithm()).get();
+ byte[] decrypted = key.decryptAsync(encrypted.getLeft(), null, null, null, encrypted.getRight()).get();
+
+ // Assert
+ assertEquals(RsaOaep.ALGORITHM_NAME, encrypted.getRight());
+ assertArrayEquals(CEK, decrypted);
+
+ key.close();
+ }
+
+ @Test
+ public void testSignVerify() throws Exception {
+
+ RsaKey key = getTestRsaKey();
+
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] hash = digest.digest(CEK);
+
+ byte[] crossPlatformHash = Base64.decodeBase64(CrossPlatformHash);
+ byte[] crossPlatformSignature = Base64.decodeBase64(CrossPlatformSignature);
+
+ // Check the hash
+ assertNotNull( hash );
+ assertEquals( 32, hash.length );
+ assertArrayEquals(hash, crossPlatformHash);
+
+ Pair signature = key.signAsync(hash, "RS256").get();
+ boolean result = key.verifyAsync(hash, signature.getLeft(), "RS256").get();
+
+ // Check the signature
+ assertTrue(result);
+ assertArrayEquals(crossPlatformSignature, signature.getLeft());
+
+ // Now prove we can verify the cross platform signature
+ result = key.verifyAsync(hash, Base64.decodeBase64(CrossPlatformSignature), "RS256").get();
+
+ assertTrue(result);
+
+ key.close();
+ }
+
+ private RsaKey getTestRsaKey() throws Exception {
+ String jwkString = "{\"kty\":\"RSA\",\"n\":\"rZ8pnmXkhfmmgNWVVdtNcYy2q0OAcCGIpeFzsN9URqJsiBEiWQfxlUxFTbM4kVWPqjauKt6byvApBGEeMA7Qs8kxwRVP-BD4orXRe9VPgliM92rH0UxQWHmCHUe7G7uUAFPwbiDVhWuFzELxNa6Kljg6Z9DuUKoddmQvlYWj8uSunofCtDi_zzlZKGYTOYJma5IYScHNww1yjLp8-b-Be2UdHbrPkCv6Nuwi6MVIKjPpEeRQgfefRmxDBJQKY3OfydMXZmEwukYXVkUcdIP8XwG2OxnfdRK0oAo0NDebNNVuT89k_3AyZLTr1KbDmx1nnjwa8uB8k-uLtcOC9igbTw\",\"e\":\"AQAB\",\"d\":\"H-z7hy_vVJ9yeZBMtIvt8qpQUK_J51STPwV085otcgud72tPKJXoW2658664ASl9kGwbnLBwb2G3-SEunuGqiNS_PGUB3niob6sFSUMRKsPDsB9HfPoOcCZvwZiWFGRqs6C7vlR1TuJVqRjKJ_ffbf4K51oo6FZPspx7j4AShLAwLUSQ60Ld5QPuxYMYZIMpdVbMVIVHJ26pR4Y18e_0GYmEGnbF5N0HkwqQmfmTiIK5aoGnD3GGgqHeHmWBwh6_WAq90ITLcX_zBeqQUgBSj-Z5v61SroO9Eang36T9mMoYrcPpYwemtAOb4HhQYDj8dCCfbeOcVmvZ9UJKWCX2oQ\",\"dp\":\"HW87UpwPoj3lPI9B9K1hJFeuGgarpakvtHuk1HpZ5hXWFGAJiXoWRV-jvYyjoM2k7RpSxPyuuFFmYHcIxiGFp2ES4HnP0BIhKVa2DyugUxIEcMK53C43Ub4mboJPZTSC3sapKgAmA2ue624sapWmshTPpx9qnUP2Oj3cSMkgMGE\",\"dq\":\"RhwEwb5FYio0GS2tmul8FAYsNH7JDehwI1yUApnTiakhSenFetml4PYyVkKR4csgLZEi3RY6J3R8Tg-36zrZuF7hxhVJn80L5_KETSpfEI3jcrXMVg4SRaMsWLY9Ahxflt2FJgUnHOmWRLmP6_hmaTcxxSACjbyUd_HhwNavD5E\",\"qi\":\"wYPZ4lKIslA1w3FaAzQifnNLABYXXUZ_KAA3a8T8fuxkdE4OP3xIFX7WHhnmBd6uOFiEcGoeq2jNQqDg91rV5661-5muQKcvp4uUsNId5rQw9EZw-kdDcwMtVFTEBfvVuyp83X974xYAHn1Jd8wWohSwrpi1QuH5cQMR5Fm6I1A\",\"p\":\"74Ot7MgxRu4euB31UWnGtrqYPjJmvbjYESS43jfDfo-s62ggV5a39P_YPg6oosgtGHNw0QDxunUOXNu9iriaYPf_imptRk69bKN8Nrl727Y-AaBYdLf1UZuwz8X07FqHAH5ghYpk79djld8QvkUUJLpx6rzcW8BJLTOi46DtzZE\",\"q\":\"uZJu-qenARIt28oj_Jlsk-p_KLnqdczczZfbRDd7XNp6csGLa8R0EyYqUB4xLWELQZsX4tAu9SaAO62tuuEy5wbOAmOVrq2ntoia1mGQSJdoeVq6OqtN300xVnaBc3us0rm8C6-824fEQ1PWXoulXLKcSqBhFT-hQahsYi-kat8\"}";
+ ObjectMapper mapper = new ObjectMapper();
+ JsonWebKey jwk = null;
+
+ jwk = mapper.readValue(jwkString, JsonWebKey.class);
+
+ return new RsaKey("foo", jwk.toRSA(true, _provider) );
+ }
+
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/SymmetricKeyBCProviderTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/SymmetricKeyBCProviderTest.java
new file mode 100755
index 000000000000..2954df416105
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/SymmetricKeyBCProviderTest.java
@@ -0,0 +1,34 @@
+/**
+ *
+ * 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.cryptography.test;
+
+import java.security.Provider;
+import org.junit.Before;
+
+public class SymmetricKeyBCProviderTest extends SymmetricKeyTest {
+
+ @Before
+ public void setUp() throws Exception {
+ try {
+ super.setProvider((Provider) Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance());
+ } catch (Exception ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+}
diff --git a/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/SymmetricKeyTest.java b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/SymmetricKeyTest.java
new file mode 100644
index 000000000000..b6d3194cae05
--- /dev/null
+++ b/azure-keyvault-cryptography/src/test/java/com/microsoft/azure/keyvault/cryptography/test/SymmetricKeyTest.java
@@ -0,0 +1,592 @@
+/**
+ *
+ * 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.cryptography.test;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.util.concurrent.ExecutionException;
+
+import javax.crypto.Cipher;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.microsoft.azure.keyvault.cryptography.SymmetricKey;
+
+public class SymmetricKeyTest {
+
+ private Provider _provider = null;
+
+ private static boolean hasUnlimitedCrypto() {
+ try {
+ return Cipher.getMaxAllowedKeyLength("RC5") >= 256;
+ } catch (NoSuchAlgorithmException e) {
+ return false;
+ }
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ setProvider(null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ protected void setProvider(Provider provider) {
+ _provider = provider;
+ }
+
+ @Test
+ public void testSymmetricKeyAesKw128() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x1F, (byte) 0xA6, (byte) 0x8B, 0x0A, (byte) 0x81, 0x12, (byte) 0xB4, 0x47, (byte) 0xAE, (byte) 0xF3, 0x4B, (byte) 0xD8, (byte) 0xFB, 0x5A, 0x7B, (byte) 0x82, (byte) 0x9D, 0x3E, (byte) 0x86, 0x23, 0x71, (byte) 0xD2, (byte) 0xCF, (byte) 0xE5 };
+
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = key.wrapKeyAsync(CEK, "A128KW").get().getLeft();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, "A128KW").get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyAesKw192() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { (byte) 0x96, 0x77, (byte) 0x8B, 0x25, (byte) 0xAE, 0x6C, (byte) 0xA4, 0x35, (byte) 0xF9, 0x2B, 0x5B, (byte) 0x97, (byte) 0xC0, 0x50, (byte) 0xAE, (byte) 0xD2, 0x46, (byte) 0x8A, (byte) 0xB8, (byte) 0xA1, 0x7A, (byte) 0xD8, 0x4E, 0x5D };
+
+ boolean unlimited = hasUnlimitedCrypto();
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = key.wrapKeyAsync(CEK, "A192KW").get().getLeft();
+
+ if (!unlimited) fail("Expected ExecutionException");
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ if (unlimited) {
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, "A192KW").get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyAesKw256() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x64, (byte) 0xE8, (byte) 0xC3, (byte) 0xF9, (byte) 0xCE, 0x0F, 0x5B, (byte) 0xA2, 0x63, (byte) 0xE9, 0x77, 0x79, 0x05, (byte) 0x81, (byte) 0x8A, 0x2A, (byte) 0x93, (byte) 0xC8, 0x19, 0x1E, 0x7D, 0x6E, (byte) 0x8A, (byte) 0xE7 };
+
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = key.wrapKeyAsync(CEK, "A256KW").get().getLeft();
+
+ if (!unlimited) fail("Expected ExecutionException");
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ if (unlimited) {
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, "A256KW").get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyDefaultAlgorithmAesKw128() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x1F, (byte) 0xA6, (byte) 0x8B, 0x0A, (byte) 0x81, 0x12, (byte) 0xB4, 0x47, (byte) 0xAE, (byte) 0xF3, 0x4B, (byte) 0xD8, (byte) 0xFB, 0x5A, 0x7B, (byte) 0x82, (byte) 0x9D, 0x3E, (byte) 0x86, 0x23, 0x71, (byte) 0xD2, (byte) 0xCF, (byte) 0xE5 };
+
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+ String algorithm = null;
+
+ try {
+ Pair result = key.wrapKeyAsync(CEK, null).get();
+ encrypted = result.getLeft();
+ algorithm = result.getRight();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertEquals("A128KW", algorithm);
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, algorithm).get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyDefaultAlgorithmAesKw192() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { (byte) 0x96, 0x77, (byte) 0x8B, 0x25, (byte) 0xAE, 0x6C, (byte) 0xA4, 0x35, (byte) 0xF9, 0x2B, 0x5B, (byte) 0x97, (byte) 0xC0, 0x50, (byte) 0xAE, (byte) 0xD2, 0x46, (byte) 0x8A, (byte) 0xB8, (byte) 0xA1, 0x7A, (byte) 0xD8, 0x4E, 0x5D };
+
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+ String algorithm = null;
+
+ try {
+ Pair result = key.wrapKeyAsync(CEK, null).get();
+
+ encrypted = result.getLeft();
+ algorithm = result.getRight();
+
+ if (!unlimited) fail("Expected ExecutionException");
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ if (unlimited) {
+ // Assert
+ assertEquals( "A192KW", algorithm);
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, algorithm).get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyDefaultAlgorithmAesKw256() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x64, (byte) 0xE8, (byte) 0xC3, (byte) 0xF9, (byte) 0xCE, 0x0F, 0x5B, (byte) 0xA2, 0x63, (byte) 0xE9, 0x77, 0x79, 0x05, (byte) 0x81, (byte) 0x8A, 0x2A, (byte) 0x93, (byte) 0xC8, 0x19, 0x1E, 0x7D, 0x6E, (byte) 0x8A, (byte) 0xE7 };
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+ String algorithm = null;
+
+ try {
+ Pair result = key.wrapKeyAsync(CEK, null).get();
+ encrypted = result.getLeft();
+ algorithm = result.getRight();
+
+ if (!unlimited) fail("Expected ExecutionException");
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ if (unlimited) {
+ // Assert
+ assertEquals("A256KW", algorithm);
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, algorithm).get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyAesKw128_ExcessKeyMaterial() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte)0x88, (byte)0x99, (byte)0xAA, (byte)0xBB, (byte)0xCC, (byte)0xDD, (byte)0xEE, (byte)0xFF };
+ byte[] EK = { 0x1F, (byte)0xA6, (byte)0x8B, 0x0A, (byte)0x81, 0x12, (byte)0xB4, 0x47, (byte)0xAE, (byte)0xF3, 0x4B, (byte)0xD8, (byte)0xFB, 0x5A, 0x7B, (byte)0x82, (byte)0x9D, 0x3E, (byte)0x86, 0x23, 0x71, (byte)0xD2, (byte)0xCF, (byte)0xE5 };
+
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = key.wrapKeyAsync(CEK, "A128KW").get().getLeft();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, "A128KW").get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyAesKw192_ExcessKeyMaterial() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte)0x88, (byte)0x99, (byte)0xAA, (byte)0xBB, (byte)0xCC, (byte)0xDD, (byte)0xEE, (byte)0xFF };
+ byte[] EK = { (byte)0x96, 0x77, (byte)0x8B, 0x25, (byte)0xAE, 0x6C, (byte)0xA4, 0x35, (byte)0xF9, 0x2B, 0x5B, (byte)0x97, (byte)0xC0, 0x50, (byte)0xAE, (byte)0xD2, 0x46, (byte)0x8A, (byte)0xB8, (byte)0xA1, 0x7A, (byte)0xD8, 0x4E, 0x5D };
+
+ boolean unlimited = hasUnlimitedCrypto();
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = key.wrapKeyAsync(CEK, "A192KW").get().getLeft();
+
+ if (!unlimited) fail("Expected ExecutionException");
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ if (unlimited) {
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, "A192KW").get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+
+ @Test
+ public void testSymmetricKeyAesKw256_ExcessKeyMaterial() {
+ // Arrange
+ byte[] KEK = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x64, (byte)0xE8, (byte)0xC3, (byte)0xF9, (byte)0xCE, 0x0F, 0x5B, (byte)0xA2, 0x63, (byte)0xE9, 0x77, 0x79, 0x05, (byte)0x81, (byte)0x8A, 0x2A, (byte)0x93, (byte)0xC8, 0x19, 0x1E, 0x7D, 0x6E, (byte)0x8A, (byte)0xE7 };
+
+ /*
+ * This test using the default JCE provider depends on whether unlimited security
+ * is installed or not. In the unlimited case, the full test should pass but in
+ * the limited case, it should fail with InvalidKeyException.
+ */
+ boolean unlimited = hasUnlimitedCrypto();
+ SymmetricKey key = new SymmetricKey("KEK", KEK, _provider);
+
+ byte[] encrypted = null;
+
+ try {
+ encrypted = key.wrapKeyAsync(CEK, "A256KW").get().getLeft();
+
+ if (!unlimited) fail("Expected ExecutionException");
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ if (unlimited) {
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = key.unwrapKeyAsync(EK, "A256KW").get();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(CEK, decrypted);
+ }
+
+ try {
+ key.close();
+ } catch (IOException e) {
+ fail("Key could not be closed");
+ }
+ }
+}
diff --git a/azure-keyvault-extensions/pom.xml b/azure-keyvault-extensions/pom.xml
new file mode 100755
index 000000000000..ac865845cfed
--- /dev/null
+++ b/azure-keyvault-extensions/pom.xml
@@ -0,0 +1,149 @@
+
+
+ 4.0.0
+
+ com.microsoft.azure
+ azure-keyvault-parent
+ 1.0.0-beta6-SNAPSHOT
+ ../pom.xml
+
+
+ azure-keyvault-extensions
+ jar
+
+ Microsoft Azure SDK for Key Vault Extensions
+ This package contains Microsoft Azure Key Vault SDK Extensions.
+ https://github.com/Azure/azure-sdk-for-java
+
+
+
+ The MIT License (MIT)
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+
+ scm:git:https://github.com/Azure/azure-sdk-for-java
+ scm:git:git@github.com:Azure/azure-sdk-for-java.git
+ HEAD
+
+
+
+ UTF-8
+
+
+
+
+
+ microsoft
+ Microsoft
+
+
+
+
+
+ com.microsoft.azure
+ azure-client-runtime
+
+
+ commons-codec
+ commons-codec
+
+
+ junit
+ junit
+ test
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ test
+ 1.54
+
+
+ com.microsoft.azure
+ azure-keyvault-core
+ 1.0.0-beta6-SNAPSHOT
+
+
+ com.microsoft.azure
+ azure-keyvault-cryptography
+ 1.0.0-beta6-SNAPSHOT
+
+
+ com.microsoft.azure
+ azure-keyvault
+ 1.0.0-beta6-SNAPSHOT
+
+
+ com.microsoft.azure
+ azure-keyvault-webkey
+ 1.0.0-beta6-SNAPSHOT
+
+
+ org.mockito
+ mockito-core
+ 1.10.19
+ test
+
+
+ com.microsoft.azure
+ azure-client-authentication
+ test
+
+
+ com.google.guava
+ guava
+ 20.0
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ true
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ 1.7
+ 1.7
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.8
+
+ *.implementation.*;*.utils.*;com.microsoft.schemas._2003._10.serialization;*.blob.core.storage
+ /**
+
* Copyright (c) Microsoft Corporation. All rights reserved.
+
* Licensed under the MIT License. See License.txt in the project root for
+
* license information.
+
*/]]>
+
+
+
+
+
diff --git a/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/AggregateKeyResolver.java b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/AggregateKeyResolver.java
new file mode 100755
index 000000000000..30062e6ab527
--- /dev/null
+++ b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/AggregateKeyResolver.java
@@ -0,0 +1,154 @@
+/**
+ *
+ * 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.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import com.google.common.util.concurrent.AbstractFuture;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.core.IKeyResolver;
+
+/**
+ * The collection of key resolvers that would iterate on a key id to resolve to {@link IKey}.
+ */
+public class AggregateKeyResolver implements IKeyResolver {
+
+ /**
+ * Future key class that resolves a key id after the async result is available.
+ */
+ class FutureKey extends AbstractFuture {
+
+ private final String kid;
+
+ private boolean isCancelled = false;
+ private boolean isDone = false;
+ private IKey result = null;
+
+ FutureKey(String kid) {
+ this.kid = kid;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+
+ // mark cancelled
+ isCancelled = true;
+
+ return isCancelled;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return isCancelled;
+ }
+
+ @Override
+ public boolean isDone() {
+
+ // always true
+ return isDone;
+ }
+
+ @Override
+ public IKey get() throws InterruptedException, ExecutionException {
+
+ // throw if cancelled
+ if (isCancelled) {
+ throw new InterruptedException();
+ }
+
+ synchronized (resolvers) {
+ for (IKeyResolver resolver : resolvers) {
+ Future futureKey = resolver.resolveKeyAsync(kid);
+
+ result = futureKey.get();
+
+ if (result != null) {
+ break;
+ }
+ }
+ }
+
+ // Mark done
+ isDone = true;
+
+ return result;
+ }
+
+ @Override
+ public IKey get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+
+ // throw if cancelled
+ if (isCancelled) {
+ throw new InterruptedException();
+ }
+
+ synchronized (resolvers) {
+ for (IKeyResolver resolver : resolvers) {
+ Future futureKey = resolver.resolveKeyAsync(kid);
+
+ result = futureKey.get(timeout, unit);
+
+ if (result != null) {
+ break;
+ }
+ }
+ }
+
+ // Mark done
+ isDone = true;
+
+ return result;
+ }
+ }
+
+ private final List resolvers;
+
+ /**
+ * Constructor.
+ */
+ public AggregateKeyResolver() {
+
+ resolvers = Collections.synchronizedList(new ArrayList());
+ }
+
+ /**
+ * Adds a key resolver to the collection of key resolvers.
+ * @param resolver the key resolver
+ */
+ public void add(IKeyResolver resolver) {
+
+ synchronized (resolvers) {
+ resolvers.add(resolver);
+ }
+ }
+
+ @Override
+ public ListenableFuture resolveKeyAsync(String kid) {
+ return new FutureKey(kid);
+ }
+
+}
diff --git a/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/CachingKeyResolver.java b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/CachingKeyResolver.java
new file mode 100755
index 000000000000..f86a98b0916b
--- /dev/null
+++ b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/CachingKeyResolver.java
@@ -0,0 +1,54 @@
+/**
+ *
+ * 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 com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.core.IKeyResolver;
+
+/**
+ * The key resolver that caches the key after resolving to {@link IKey}.
+ */
+public class CachingKeyResolver implements IKeyResolver {
+
+ private final LoadingCache> cache;
+
+ /**
+ * Constructor.
+ * @param capacity the cache size
+ * @param keyResolver the key resolver
+ */
+ public CachingKeyResolver(int capacity, final IKeyResolver keyResolver) {
+ cache = CacheBuilder.newBuilder().maximumSize(capacity)
+ .build(new CacheLoader>() {
+
+ @Override
+ public ListenableFuture load(String kid) {
+ return keyResolver.resolveKeyAsync(kid);
+ } });
+ }
+
+ @Override
+ public ListenableFuture resolveKeyAsync(String kid) {
+ return cache.getUnchecked(kid);
+ }
+}
diff --git a/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/KeyVaultKey.java b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/KeyVaultKey.java
new file mode 100755
index 000000000000..d3bf97abc148
--- /dev/null
+++ b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/KeyVaultKey.java
@@ -0,0 +1,245 @@
+/**
+ *
+ * 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 {
+
+ 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> {
+
+ private final String algorithm;
+
+ SignResultTransform(String algorithm) {
+ super();
+ this.algorithm = algorithm;
+ }
+
+ @Override
+ public Pair 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 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 futureCall =
+ client.decryptAsync(
+ implementation.getKid(),
+ new JsonWebKeyEncryptionAlgorithm(algorithm),
+ ciphertext,
+ null);
+ return Futures.transform(futureCall, new DecryptResultTransform());
+ }
+
+ @Override
+ public ListenableFuture> 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> wrapKeyAsync(byte[] plaintext, String algorithm) throws NoSuchAlgorithmException {
+ if (implementation == null) {
+ return null;
+ }
+
+ return implementation.wrapKeyAsync(plaintext, algorithm);
+ }
+
+ @Override
+ public ListenableFuture unwrapKeyAsync(byte[] ciphertext, String algorithm) {
+ if (implementation == null) {
+ return null;
+ }
+
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ algorithm = getDefaultKeyWrapAlgorithm();
+ }
+
+ // Never local
+ ListenableFuture futureCall =
+ client.unwrapKeyAsync(
+ implementation.getKid(),
+ new JsonWebKeyEncryptionAlgorithm(algorithm),
+ ciphertext,
+ null);
+ return Futures.transform(futureCall, new DecryptResultTransform());
+ }
+
+ @Override
+ public ListenableFuture> signAsync(byte[] digest, String algorithm) throws NoSuchAlgorithmException {
+ if (implementation == null) {
+ return null;
+ }
+
+ if (Strings.isNullOrWhiteSpace(algorithm)) {
+ algorithm = getDefaultSignatureAlgorithm();
+ }
+
+ // Never local
+ ListenableFuture futureCall =
+ client.signAsync(
+ implementation.getKid(),
+ new JsonWebKeySignatureAlgorithm(algorithm),
+ digest,
+ null);
+ return Futures.transform(futureCall, new SignResultTransform(algorithm));
+ }
+
+ @Override
+ public ListenableFuture verifyAsync(byte[] digest, byte[] signature, String algorithm) throws NoSuchAlgorithmException {
+ if (implementation == null) {
+ return null;
+ }
+
+ return implementation.verifyAsync(digest, signature, algorithm);
+ }
+}
diff --git a/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/KeyVaultKeyResolver.java b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/KeyVaultKeyResolver.java
new file mode 100755
index 000000000000..7f8e778ef068
--- /dev/null
+++ b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/KeyVaultKeyResolver.java
@@ -0,0 +1,134 @@
+/**
+ *
+ * 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.security.Provider;
+import org.apache.commons.codec.binary.Base64;
+
+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.KeyIdentifier;
+import com.microsoft.azure.keyvault.KeyVaultClient;
+import com.microsoft.azure.keyvault.SecretIdentifier;
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.core.IKeyResolver;
+import com.microsoft.azure.keyvault.cryptography.SymmetricKey;
+import com.microsoft.azure.keyvault.models.KeyBundle;
+import com.microsoft.azure.keyvault.models.SecretBundle;
+
+/**
+ * The key resolver class that handles resolving key id to type {@link IKey}
+ * to be used for cryptography operations.
+ */
+public class KeyVaultKeyResolver implements IKeyResolver {
+
+ static final Base64 BASE64 = new Base64(-1, null, true);
+
+ /**
+ * Transforms {@link KeyBundle} to {@link IKey}.
+ */
+ class FutureKeyFromKey implements Function {
+
+ protected FutureKeyFromKey() {
+ super();
+ }
+
+ @Override
+ public IKey apply(KeyBundle keyBundle) {
+
+ if (keyBundle != null) {
+ return new KeyVaultKey(client, keyBundle);
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Transforms {@link SecretBundle} to {@link IKey}.
+ */
+ class FutureKeyFromSecret implements Function {
+
+ protected FutureKeyFromSecret() {
+ super();
+ }
+
+ @Override
+ public IKey apply(SecretBundle secretBundle) {
+
+ if (secretBundle != null && secretBundle.contentType().equalsIgnoreCase("application/octet-stream")) {
+ byte[] keyBytes = BASE64.decode(secretBundle.value());
+
+ if (keyBytes != null) {
+ return new SymmetricKey(secretBundle.id(), keyBytes, provider);
+ }
+ }
+
+ return null;
+ }
+ }
+
+ private final KeyVaultClient client;
+ private final Provider provider;
+
+ /**
+ * Constructor.
+ * @param client the key vault client
+ */
+ public KeyVaultKeyResolver(KeyVaultClient client) {
+ this.client = client;
+ this.provider = null;
+ }
+
+ /**
+ * Constructor.
+ * @param client the key vault client
+ * @param provider the java security provider
+ */
+ public KeyVaultKeyResolver(KeyVaultClient client, Provider provider) {
+ this.client = client;
+ this.provider = provider;
+ }
+
+ private ListenableFuture resolveKeyFromSecretAsync(String kid) {
+
+ ListenableFuture futureCall = client.getSecretAsync(kid, null);
+ return Futures.transform(futureCall, new FutureKeyFromSecret());
+ }
+
+ private ListenableFuture resolveKeyFromKeyAsync(String kid) {
+
+ ListenableFuture futureCall = client.getKeyAsync(kid, null);
+ return Futures.transform(futureCall, new FutureKeyFromKey());
+ }
+
+ @Override
+ public ListenableFuture resolveKeyAsync(String kid) {
+
+ if (KeyIdentifier.isKeyIdentifier(kid)) {
+ return resolveKeyFromKeyAsync(kid);
+ } else if (SecretIdentifier.isSecretIdentifier(kid)) {
+ return resolveKeyFromSecretAsync(kid);
+ }
+
+ return Futures.immediateFuture(null);
+ }
+
+}
diff --git a/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/Strings.java b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/Strings.java
new file mode 100755
index 000000000000..52ef356b78e3
--- /dev/null
+++ b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/Strings.java
@@ -0,0 +1,53 @@
+/**
+ *
+ * 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;
+
+/**
+ * String handlers.
+ */
+public class Strings {
+
+ /**
+ * Determines whether the parameter string is either null or empty.
+ * @param arg the string to verify
+ * @return true if the string is empty or null and false otherwise.
+ */
+ public static boolean isNullOrEmpty(String arg) {
+
+ if (arg == null || arg.length() == 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines whether the parameter string is null, empty or whitespace.
+ * @param arg the string to verify
+ * @return true if the string is empty, contains only whitespace or is null and false otherwise
+ */
+ public static boolean isNullOrWhiteSpace(String arg) {
+
+ if (Strings.isNullOrEmpty(arg) || arg.trim().isEmpty()) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/package.html b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/package.html
new file mode 100755
index 000000000000..12edd05fd0ba
--- /dev/null
+++ b/azure-keyvault-extensions/src/main/java/com/microsoft/azure/keyvault/extensions/package.html
@@ -0,0 +1,5 @@
+
+
+This package contains the Azure Key Vault Extension classes.
+
+
diff --git a/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/CachingKeyResolverTest.java b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/CachingKeyResolverTest.java
new file mode 100755
index 000000000000..a5263c820a6d
--- /dev/null
+++ b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/CachingKeyResolverTest.java
@@ -0,0 +1,97 @@
+/**
+ *
+ * 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.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.core.IKeyResolver;
+import com.microsoft.azure.keyvault.extensions.CachingKeyResolver;
+import static org.mockito.Mockito.*;
+
+public class CachingKeyResolverTest {
+
+ @SuppressWarnings("unchecked")
+ final ListenableFuture ikeyAsync = mock(ListenableFuture.class);
+ final static String keyId = "keyID";
+ final static String keyId2 = "keyID2";
+ final static String keyId3 = "keyID3";
+
+
+ /*
+ * Tests the capacity limit of CachingKeyResolver by adding more keys
+ * than the cache limit and verifying that least recently used entity is evicted.
+ */
+ @Test
+ public void KeyVault_CapacityLimitOfCachingKeyResolver()
+ {
+ IKeyResolver mockedKeyResolver = mock(IKeyResolver.class);
+ CachingKeyResolver resolver = new CachingKeyResolver(2, mockedKeyResolver);
+
+ when(mockedKeyResolver.resolveKeyAsync(keyId)).thenReturn(ikeyAsync);
+ when(mockedKeyResolver.resolveKeyAsync(keyId2)).thenReturn(ikeyAsync);
+ when(mockedKeyResolver.resolveKeyAsync(keyId3)).thenReturn(ikeyAsync);
+
+ resolver.resolveKeyAsync(keyId);
+ resolver.resolveKeyAsync(keyId2);
+ resolver.resolveKeyAsync(keyId3);
+
+ resolver.resolveKeyAsync(keyId2);
+ resolver.resolveKeyAsync(keyId3);
+ resolver.resolveKeyAsync(keyId);
+ resolver.resolveKeyAsync(keyId3);
+
+ verify(mockedKeyResolver, times(1)).resolveKeyAsync(keyId2);
+ verify(mockedKeyResolver, times(1)).resolveKeyAsync(keyId3);
+ verify(mockedKeyResolver, times(2)).resolveKeyAsync(keyId);
+ }
+
+ /*
+ * Tests the behavior of CachingKeyResolver when resolving key throws
+ * and validate that the failed entity is not added to the cache.
+ */
+ @Test
+ public void KeyVault_CachingKeyResolverThrows()
+ {
+ IKeyResolver mockedKeyResolver = mock(IKeyResolver.class);
+ CachingKeyResolver resolver = new CachingKeyResolver(10, mockedKeyResolver);
+
+ // First throw exception and for the second call return a value
+ when(mockedKeyResolver.resolveKeyAsync(keyId))
+ .thenThrow(new RuntimeException("test"))
+ .thenReturn(ikeyAsync);
+
+ try {
+ resolver.resolveKeyAsync(keyId);
+ assertFalse("Should have thrown an exception.", true);
+ }
+ catch (UncheckedExecutionException e) {
+ assertTrue("RuntimeException is expected.", e.getCause() instanceof RuntimeException);
+ }
+
+ resolver.resolveKeyAsync(keyId);
+ resolver.resolveKeyAsync(keyId);
+
+ verify(mockedKeyResolver, times(2)).resolveKeyAsync(keyId);
+ }
+}
diff --git a/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultClientIntegrationTestBase.java b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultClientIntegrationTestBase.java
new file mode 100755
index 000000000000..dad23b7d49d6
--- /dev/null
+++ b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultClientIntegrationTestBase.java
@@ -0,0 +1,163 @@
+/**
+ *
+ * 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.test;
+
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+import com.microsoft.rest.credentials.ServiceClientCredentials;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.microsoft.aad.adal4j.AuthenticationContext;
+import com.microsoft.aad.adal4j.AuthenticationResult;
+import com.microsoft.aad.adal4j.ClientCredential;
+import com.microsoft.azure.keyvault.KeyVaultClient;
+import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;
+
+public class KeyVaultClientIntegrationTestBase {
+
+ /**
+ * The client instance that should be used on tests.
+ */
+ protected static KeyVaultClient keyVaultClient;
+
+ /**
+ * Primary vault URI, used for keys and secrets tests.
+ */
+ public static String getVaultUri() {
+ return getLiveVaultUri1();
+ }
+
+ /**
+ * Secondary vault URI, used to verify ability to transparently authenticate
+ * against a different resource.
+ */
+ public static String getSecondaryVaultUri() {
+ return getLiveVaultUri2();
+ }
+
+ private static String getLiveVaultUri1() {
+ return getenvOrDefault("keyvault.vaulturi", "https://javasdktestvault.vault.azure.net");
+ }
+
+ private static String getLiveVaultUri2() {
+ return getenvOrDefault("keyvault.vaulturi.alt", "https://javasdktestvault2.vault.azure.net");
+ }
+
+ private static String getenvOrDefault(String varName, String defValue) {
+ String value = System.getenv(varName);
+ return value != null ? value : defValue;
+ }
+
+ protected static void createKeyVaultClient() throws Exception {
+ keyVaultClient = new KeyVaultClient(createTestCredentials());
+ }
+
+ private static ServiceClientCredentials createTestCredentials() throws Exception {
+ return new KeyVaultCredentials() {
+
+ @Override
+ public String doAuthenticate(String authorization, String resource, String scope) {
+ try {
+ AuthenticationResult authResult = getAccessToken(authorization, resource);
+ return authResult.getAccessToken();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ };
+ }
+
+ private static AuthenticationResult getAccessToken(String authorization, String resource) throws Exception {
+
+ String clientId = System.getenv("arm.clientid");
+
+ if (clientId == null) {
+ throw new Exception("Please inform arm.clientid in the environment settings.");
+ }
+
+ String clientKey = System.getenv("arm.clientkey");
+ String username = System.getenv("arm.username");
+ String password = System.getenv("arm.password");
+
+ AuthenticationResult result = null;
+ ExecutorService service = null;
+ try {
+ service = Executors.newFixedThreadPool(1);
+ AuthenticationContext context = new AuthenticationContext(authorization, false, service);
+
+ Future future = null;
+
+ if (clientKey != null && password == null) {
+ ClientCredential credentials = new ClientCredential(clientId, clientKey);
+ future = context.acquireToken(resource, credentials, null);
+ }
+
+ if (password != null && clientKey == null) {
+ future = context.acquireToken(resource, clientId, username, password, null);
+ }
+
+ if (future == null) {
+ throw new Exception("Missing or ambiguous credentials - please inform exactly one of arm.clientkey or arm.password in the environment settings.");
+ }
+
+ result = future.get();
+ } finally {
+ service.shutdown();
+ }
+
+ if (result == null) {
+ throw new RuntimeException("authentication result was null");
+ }
+ return result;
+ }
+
+ protected static ObjectWriter jsonWriter;
+ protected static ObjectReader jsonReader;
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ createKeyVaultClient();
+ jsonWriter = new ObjectMapper().writer().withDefaultPrettyPrinter();
+ jsonReader = new ObjectMapper().reader();
+ }
+
+ @AfterClass
+ public static void cleanup() throws Exception {
+ }
+
+ @Before
+ public void beforeTest() throws Exception {
+ //setupTest(getClass().getSimpleName() + "-" + "??");
+ }
+
+ @After
+ public void afterTest() throws Exception {
+ //resetTest(getClass().getSimpleName() + "-" + "??");
+ }
+
+}
\ No newline at end of file
diff --git a/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultKeyResolverBCProviderTest.java b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultKeyResolverBCProviderTest.java
new file mode 100755
index 000000000000..813b4c3ee5ad
--- /dev/null
+++ b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultKeyResolverBCProviderTest.java
@@ -0,0 +1,293 @@
+//
+//Copyright © Microsoft Corporation, 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
+//
+//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+//OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+//ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
+//PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
+//
+//See the Apache License, Version 2.0 for the specific language
+//governing permissions and limitations under the License.
+
+package com.microsoft.azure.keyvault.extensions.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+import java.security.Provider;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.apache.commons.codec.binary.Base64;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.extensions.KeyVaultKeyResolver;
+import com.microsoft.azure.keyvault.models.KeyBundle;
+import com.microsoft.azure.keyvault.models.SecretBundle;
+import com.microsoft.azure.keyvault.requests.CreateKeyRequest;
+import com.microsoft.azure.keyvault.requests.SetSecretRequest;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyType;
+
+public class KeyVaultKeyResolverBCProviderTest extends KeyVaultClientIntegrationTestBase {
+
+ private Provider _provider = null;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ try {
+ _provider = (Provider) Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance();
+ } catch (ClassNotFoundException ex) {
+ throw new RuntimeException(ex.getMessage());
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex.getMessage());
+ } catch (InstantiationException ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ private static final String KEY_NAME = "JavaExtensionKey";
+ private static final String SECRET_NAME = "JavaExtensionSecret";
+
+ private static final Base64 _base64 = new Base64(-1, null, true);
+
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Key() throws InterruptedException, ExecutionException
+ {
+ try {
+ // Create a key on a vault.
+ CreateKeyRequest request = new CreateKeyRequest.Builder(getVaultUri(), KEY_NAME, JsonWebKeyType.RSA).build();
+ KeyBundle bundle = keyVaultClient.createKey(request);
+
+ if ( bundle != null )
+ {
+ try
+ {
+ // ctor with client
+ KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient, _provider );
+
+ Future baseKeyFuture = resolver.resolveKeyAsync( bundle.keyIdentifier().baseIdentifier() );
+ Future versionKeyFuture = resolver.resolveKeyAsync( bundle.keyIdentifier().identifier() );
+
+ IKey baseKey = baseKeyFuture.get();
+ IKey versionKey = versionKeyFuture.get();
+
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+ }
+ finally
+ {
+ // Delete the key
+ keyVaultClient.deleteKey( getVaultUri(), KEY_NAME );
+ }
+ }
+ }
+ catch ( Exception ex )
+ {
+ Assert.fail(ex.getMessage());
+ }
+ }
+
+ /*
+ * Test resolving a key from a 128bit secret encoded as base64 in a vault using various KeyVaultKeyResolver constructors.
+ */
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Secret128Base64() throws InterruptedException, ExecutionException
+ {
+ // Arrange
+ byte[] keyBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x1F, (byte) 0xA6, (byte) 0x8B, 0x0A, (byte) 0x81, 0x12, (byte) 0xB4, 0x47, (byte) 0xAE, (byte) 0xF3, 0x4B, (byte) 0xD8, (byte) 0xFB, 0x5A, 0x7B, (byte) 0x82, (byte) 0x9D, 0x3E, (byte) 0x86, 0x23, 0x71, (byte) 0xD2, (byte) 0xCF, (byte) 0xE5 };
+
+ try {
+
+ SetSecretRequest request = new SetSecretRequest.Builder(getVaultUri(), SECRET_NAME, _base64.encodeAsString(keyBytes)).withContentType("application/octet-stream").build();
+ SecretBundle secretBundle = keyVaultClient.setSecret( request );
+
+ if ( secretBundle != null )
+ {
+ try {
+ // ctor with client
+ KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient );
+
+ IKey baseKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().baseIdentifier() ).get();
+ IKey versionKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().identifier() ).get();
+
+ // Check for correct key identifiers
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+
+ // Ensure key operations give the expected results
+ byte[] encrypted = null;
+
+ try {
+ encrypted = baseKey.wrapKeyAsync(CEK, "A128KW").get().getLeft();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ try {
+ encrypted = versionKey.wrapKeyAsync(CEK, "A128KW").get().getLeft();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+ finally
+ {
+ // Delete the secret
+ keyVaultClient.deleteSecret( getVaultUri(), SECRET_NAME );
+ }
+ }
+ }
+ catch ( Exception ex ) {
+ Assert.fail(ex.getMessage());
+ }
+ }
+
+ /*
+ * Test resolving a key from a 128bit secret encoded as base64 in a vault using various KeyVaultKeyResolver constructors.
+ */
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Secret192Base64() throws InterruptedException, ExecutionException
+ {
+ // Arrange
+ byte[] keyBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { (byte) 0x96, 0x77, (byte) 0x8B, 0x25, (byte) 0xAE, 0x6C, (byte) 0xA4, 0x35, (byte) 0xF9, 0x2B, 0x5B, (byte) 0x97, (byte) 0xC0, 0x50, (byte) 0xAE, (byte) 0xD2, 0x46, (byte) 0x8A, (byte) 0xB8, (byte) 0xA1, 0x7A, (byte) 0xD8, 0x4E, 0x5D };
+
+ try {
+ SetSecretRequest request = new SetSecretRequest.Builder(getVaultUri(), SECRET_NAME, _base64.encodeAsString(keyBytes)).withContentType("application/octet-stream").build();
+ SecretBundle secretBundle = keyVaultClient.setSecret( request );
+
+ if ( secretBundle != null )
+ {
+ try
+ {
+ // ctor with client
+ KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient, _provider );
+
+ IKey baseKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().baseIdentifier() ).get();
+ IKey versionKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().identifier() ).get();
+
+ // Check for correct key identifiers
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+
+ // Ensure key operations give the expected results
+ byte[] encrypted = null;
+
+ try {
+ encrypted = baseKey.wrapKeyAsync(CEK, "A192KW").get().getLeft();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ try {
+ encrypted = versionKey.wrapKeyAsync(CEK, "A192KW").get().getLeft();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+ finally
+ {
+ // Delete the key
+ keyVaultClient.deleteSecret( getVaultUri(), SECRET_NAME );
+ }
+ }
+ } catch (Exception ex) {
+ Assert.fail(ex.getMessage());
+ }
+ }
+
+ /*
+ * Test resolving a key from a 256bit secret encoded as base64 in a vault using various KeyVaultKeyResolver constructors.
+ */
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Secret256Base64() throws InterruptedException, ExecutionException
+ {
+ // Arrange
+ byte[] keyBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x64, (byte) 0xE8, (byte) 0xC3, (byte) 0xF9, (byte) 0xCE, 0x0F, 0x5B, (byte) 0xA2, 0x63, (byte) 0xE9, 0x77, 0x79, 0x05, (byte) 0x81, (byte) 0x8A, 0x2A, (byte) 0x93, (byte) 0xC8, 0x19, 0x1E, 0x7D, 0x6E, (byte) 0x8A, (byte) 0xE7 };
+
+ try {
+ SetSecretRequest request = new SetSecretRequest.Builder(getVaultUri(), SECRET_NAME, _base64.encodeAsString(keyBytes)).withContentType("application/octet-stream").build();
+ SecretBundle secretBundle = keyVaultClient.setSecret( request );
+
+ if ( secretBundle != null )
+ {
+ try
+ {
+ // ctor with client
+ KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient, _provider );
+
+ IKey baseKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().baseIdentifier() ).get();
+ IKey versionKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().identifier() ).get();
+
+ // Check for correct key identifiers
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+
+ // Ensure key operations give the expected results
+ byte[] encrypted = null;
+
+ try {
+ encrypted = baseKey.wrapKeyAsync(CEK, "A256KW").get().getLeft();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ try {
+ encrypted = versionKey.wrapKeyAsync(CEK, "A256KW").get().getLeft();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+ finally
+ {
+ // Delete the key
+ keyVaultClient.deleteSecret( getVaultUri(), SECRET_NAME );
+ }
+ }
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+ }
+}
diff --git a/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultKeyResolverDefaultProviderTest.java b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultKeyResolverDefaultProviderTest.java
new file mode 100755
index 000000000000..62777c9b2610
--- /dev/null
+++ b/azure-keyvault-extensions/src/test/java/com/microsoft/azure/keyvault/extensions/test/KeyVaultKeyResolverDefaultProviderTest.java
@@ -0,0 +1,317 @@
+package com.microsoft.azure.keyvault.extensions.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.concurrent.ExecutionException;
+import javax.crypto.Cipher;
+
+import org.apache.commons.codec.binary.Base64;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.microsoft.azure.keyvault.core.IKey;
+import com.microsoft.azure.keyvault.extensions.KeyVaultKeyResolver;
+import com.microsoft.azure.keyvault.models.KeyBundle;
+import com.microsoft.azure.keyvault.models.SecretBundle;
+import com.microsoft.azure.keyvault.requests.CreateKeyRequest;
+import com.microsoft.azure.keyvault.requests.SetSecretRequest;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyType;
+
+//
+//Copyright © Microsoft Corporation, 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
+//
+//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+//OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+//ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
+//PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
+//
+//See the Apache License, Version 2.0 for the specific language
+//governing permissions and limitations under the License.
+
+public class KeyVaultKeyResolverDefaultProviderTest extends KeyVaultClientIntegrationTestBase {
+
+ private static boolean hasUnlimitedCrypto() {
+ try {
+ return Cipher.getMaxAllowedKeyLength("RC5") >= 256;
+ } catch (NoSuchAlgorithmException e) {
+ return false;
+ }
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ private static final boolean _unlimited = hasUnlimitedCrypto();
+
+
+ private static final String KEY_NAME = "JavaExtensionKey";
+ private static final String SECRET_NAME = "JavaExtensionSecret";
+
+ private static final Base64 _base64 = new Base64(-1, null, true);
+
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Key() throws InterruptedException, ExecutionException
+ {
+ try {
+ // Create a key on a vault.
+ CreateKeyRequest request = new CreateKeyRequest.Builder(getVaultUri(), KEY_NAME, JsonWebKeyType.RSA).build();
+ KeyBundle keyBundle = keyVaultClient.createKey(request);
+
+ try
+ {
+ // ctor with client
+ final KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient );
+
+ IKey baseKey = resolver.resolveKeyAsync( keyBundle.keyIdentifier().baseIdentifier() ).get();
+ IKey versionKey = resolver.resolveKeyAsync( keyBundle.keyIdentifier().identifier() ).get();
+
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+ }
+ finally
+ {
+ // Delete the key
+ keyVaultClient.deleteKey( getVaultUri(), KEY_NAME );
+ }
+ } catch(Exception ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ /*
+ * Test resolving a key from a 128bit secret encoded as base64 in a vault using various KeyVaultKeyResolver constructors.
+ */
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Secret128Base64() throws InterruptedException, ExecutionException
+ {
+ // Arrange
+ byte[] keyBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x1F, (byte) 0xA6, (byte) 0x8B, 0x0A, (byte) 0x81, 0x12, (byte) 0xB4, 0x47, (byte) 0xAE, (byte) 0xF3, 0x4B, (byte) 0xD8, (byte) 0xFB, 0x5A, 0x7B, (byte) 0x82, (byte) 0x9D, 0x3E, (byte) 0x86, 0x23, 0x71, (byte) 0xD2, (byte) 0xCF, (byte) 0xE5 };
+
+ try {
+ SetSecretRequest request = new SetSecretRequest.Builder(getVaultUri(), SECRET_NAME, _base64.encodeAsString(keyBytes)).withContentType("application/octet-stream").build();
+ SecretBundle secretBundle = keyVaultClient.setSecret(request);
+
+ if ( secretBundle != null )
+ {
+ try
+ {
+ // ctor with client
+ KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient );
+
+ IKey baseKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().baseIdentifier() ).get();
+ IKey versionKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().identifier() ).get();
+
+ // Check for correct key identifiers
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+
+ // Ensure key operations give the expected results
+ byte[] encrypted = null;
+
+ try {
+ encrypted = baseKey.wrapKeyAsync(CEK, "A128KW").get().getLeft();
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ try {
+ encrypted = versionKey.wrapKeyAsync(CEK, "A128KW").get().getLeft();
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+ finally
+ {
+ // Delete the key
+ keyVaultClient.deleteSecret( getVaultUri(), SECRET_NAME );
+ }
+ }
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+ }
+
+ /*
+ * Test resolving a key from a 128bit secret encoded as base64 in a vault using various KeyVaultKeyResolver constructors.
+ */
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Secret192Base64() throws InterruptedException, ExecutionException
+ {
+ // Arrange
+ byte[] keyBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { (byte) 0x96, 0x77, (byte) 0x8B, 0x25, (byte) 0xAE, 0x6C, (byte) 0xA4, 0x35, (byte) 0xF9, 0x2B, 0x5B, (byte) 0x97, (byte) 0xC0, 0x50, (byte) 0xAE, (byte) 0xD2, 0x46, (byte) 0x8A, (byte) 0xB8, (byte) 0xA1, 0x7A, (byte) 0xD8, 0x4E, 0x5D };
+
+ try {
+ SetSecretRequest request = new SetSecretRequest.Builder(getVaultUri(), SECRET_NAME, _base64.encodeAsString(keyBytes)).withContentType("application/octet-stream").build();
+ SecretBundle secretBundle = keyVaultClient.setSecret( request );
+
+ if ( secretBundle != null )
+ {
+ try
+ {
+ // ctor with client
+ KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient );
+
+ IKey baseKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().baseIdentifier() ).get();
+ IKey versionKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().identifier() ).get();
+
+ // Check for correct key identifiers
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+
+ // Ensure key operations give the expected results
+ byte[] encrypted = null;
+
+ try {
+ encrypted = baseKey.wrapKeyAsync(CEK, "A192KW").get().getLeft();
+
+ if (!_unlimited) fail("Expected ExecutionException");
+ } catch (ExecutionException e) {
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!_unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+
+ if ( _unlimited ) {
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ try {
+ encrypted = versionKey.wrapKeyAsync(CEK, "A192KW").get().getLeft();
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+ }
+ finally
+ {
+ // Delete the key
+ keyVaultClient.deleteSecret( getVaultUri(), SECRET_NAME );
+ }
+ }
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+ }
+
+ /*
+ * Test resolving a key from a 256bit secret encoded as base64 in a vault using various KeyVaultKeyResolver constructors.
+ */
+ @Test
+ public void KeyVault_KeyVaultKeyResolver_Secret256Base64() throws InterruptedException, ExecutionException
+ {
+ // Arrange
+ byte[] keyBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ byte[] CEK = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+ byte[] EK = { 0x64, (byte) 0xE8, (byte) 0xC3, (byte) 0xF9, (byte) 0xCE, 0x0F, 0x5B, (byte) 0xA2, 0x63, (byte) 0xE9, 0x77, 0x79, 0x05, (byte) 0x81, (byte) 0x8A, 0x2A, (byte) 0x93, (byte) 0xC8, 0x19, 0x1E, 0x7D, 0x6E, (byte) 0x8A, (byte) 0xE7 };
+
+ try {
+ SetSecretRequest request = new SetSecretRequest.Builder(getVaultUri(), SECRET_NAME, _base64.encodeAsString(keyBytes)).withContentType("application/octet-stream").build();
+ SecretBundle secretBundle = keyVaultClient.setSecret( request );
+
+ if ( secretBundle != null )
+ {
+ try
+ {
+ // ctor with client
+ KeyVaultKeyResolver resolver = new KeyVaultKeyResolver( keyVaultClient );
+
+ IKey baseKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().baseIdentifier() ).get();
+ IKey versionKey = resolver.resolveKeyAsync( secretBundle.secretIdentifier().identifier() ).get();
+
+ // Check for correct key identifiers
+ Assert.assertEquals( baseKey.getKid(), versionKey.getKid() );
+
+ // Ensure key operations give the expected results
+ byte[] encrypted = null;
+
+ try {
+ encrypted = baseKey.wrapKeyAsync(CEK, "A256KW").get().getLeft();
+
+ if (!_unlimited) fail("Expected ExecutionException");
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ // In the limited case, the failure should be InvalidKeyException
+ // In the unlimited case, this should not fail
+ if (!_unlimited) {
+ Throwable cause = e.getCause();
+ if (cause == null || !(cause instanceof InvalidKeyException)) fail("ExecutionException");
+ } else {
+ fail("ExecutionException");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ if ( _unlimited ) {
+ // Assert
+ assertArrayEquals(EK, encrypted);
+
+ try {
+ encrypted = versionKey.wrapKeyAsync(CEK, "A256KW").get().getLeft();
+ } catch (InterruptedException e) {
+ fail("InterrupedException");
+ } catch (ExecutionException e) {
+ fail("ExecutionException");
+ } catch (NoSuchAlgorithmException e) {
+ fail("NoSuchAlgorithmException");
+ }
+
+ // Assert
+ assertArrayEquals(EK, encrypted);
+ }
+ }
+ finally
+ {
+ // Delete the key
+ keyVaultClient.deleteSecret( getVaultUri(), SECRET_NAME );
+ }
+ }
+ } catch ( Exception ex ) {
+ fail(ex.getMessage());
+ }
+ }
+}
diff --git a/azure-keyvault-webkey/pom.xml b/azure-keyvault-webkey/pom.xml
new file mode 100644
index 000000000000..f39ebfeff52a
--- /dev/null
+++ b/azure-keyvault-webkey/pom.xml
@@ -0,0 +1,115 @@
+
+
+ 4.0.0
+
+ com.microsoft.azure
+ azure-keyvault-parent
+ 1.0.0-beta6-SNAPSHOT
+ ../pom.xml
+
+
+ azure-keyvault-webkey
+ jar
+
+ Microsoft Azure SDK for Key Vault WebKey
+ This package contains Microsoft Azure Key Vault WebKey library.
+ https://github.com/Azure/azure-sdk-for-java
+
+
+
+ The MIT License (MIT)
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+
+ scm:git:https://github.com/Azure/azure-sdk-for-java
+ scm:git:git@github.com:Azure/azure-sdk-for-java.git
+ HEAD
+
+
+
+ UTF-8
+
+
+
+
+
+ microsoft
+ Microsoft
+
+
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ commons-codec
+ commons-codec
+
+
+ com.google.guava
+ guava
+ 20.0
+
+
+
+
+ junit
+ junit
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ true
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ 1.7
+ 1.7
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.8
+
+ com.microsoft.schemas._2003._10.serialization;
+ /**
+
* Copyright (c) Microsoft Corporation. All rights reserved.
+
* Licensed under the MIT License. See License.txt in the project root for
+
* license information.
+
*/]]>
+
+
+
+
+
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/Base64UrlJsonDeserializer.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/Base64UrlJsonDeserializer.java
new file mode 100644
index 000000000000..9418b15a9673
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/Base64UrlJsonDeserializer.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.webkey;
+
+import java.io.IOException;
+
+import org.apache.commons.codec.binary.Base64;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+/**
+ * The base64 URL JSON deserializer.
+ */
+public class Base64UrlJsonDeserializer extends JsonDeserializer {
+
+ static final Base64 BASE64 = new Base64(-1, null, true);
+
+ @Override
+ public byte[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+ String text = jp.getText();
+ if (text != null) {
+ return BASE64.decode(text);
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/Base64UrlJsonSerializer.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/Base64UrlJsonSerializer.java
new file mode 100644
index 000000000000..eac3d33e26c7
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/Base64UrlJsonSerializer.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.webkey;
+
+import java.io.IOException;
+
+import org.apache.commons.codec.binary.Base64;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+/**
+ * The base64 URL JSON serializer.
+ */
+public class Base64UrlJsonSerializer extends JsonSerializer {
+
+ static final Base64 BASE64 = new Base64(-1, null, true);
+
+ @Override
+ public void serialize(byte[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
+ String text;
+ if (value == null) {
+ text = null;
+ } else if (value.length == 0) {
+ text = "";
+ } else {
+ text = BASE64.encodeAsString(value);
+ }
+ jgen.writeString(text);
+ }
+
+}
\ No newline at end of file
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKey.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKey.java
new file mode 100755
index 000000000000..4e6ad1fd67d9
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKey.java
@@ -0,0 +1,813 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.webkey;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.base.Objects;
+
+/**
+ * As of http://tools.ietf.org/html/draft-ietf-jose-json-web-key-18.
+ */
+@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY, setterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
+public class JsonWebKey {
+
+ /**
+ * Key Identifier.
+ */
+ private String kid;
+
+ /**
+ * Key type, usually RSA. Possible values include: 'EC', 'RSA', 'RSA-HSM',
+ * 'oct'.
+ */
+ private JsonWebKeyType kty;
+
+ /**
+ * The keyOps property.
+ */
+ private List keyOps;
+
+ /**
+ * RSA modulus.
+ */
+ private byte[] n;
+
+ /**
+ * RSA public exponent.
+ */
+ private byte[] e;
+
+ /**
+ * RSA private exponent.
+ */
+ private byte[] d;
+
+ /**
+ * RSA Private Key Parameter.
+ */
+ private byte[] dp;
+
+ /**
+ * RSA Private Key Parameter.
+ */
+ private byte[] dq;
+
+ /**
+ * RSA Private Key Parameter.
+ */
+ private byte[] qi;
+
+ /**
+ * RSA secret prime.
+ */
+ private byte[] p;
+
+ /**
+ * RSA secret prime, with p < q.
+ */
+ private byte[] q;
+
+ /**
+ * Symmetric key.
+ */
+ private byte[] k;
+
+ /**
+ * HSM Token, used with Bring Your Own Key.
+ */
+ private byte[] t;
+
+ /**
+ * Key Identifier.
+ *
+ * @return the kid value.
+ */
+ @JsonProperty("kid")
+ public String kid() {
+ return this.kid;
+ }
+
+ /**
+ * Set the key identifier value.
+ *
+ * @param kid the key identifier
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withKid(String kid) {
+ this.kid = kid;
+ return this;
+ }
+
+ /**
+ * Key type, usually RSA. Possible values include: 'EC', 'RSA', 'RSA-HSM',
+ * 'oct'.
+ *
+ * @return the key type.
+ */
+ @JsonProperty("kty")
+ public JsonWebKeyType kty() {
+ return this.kty;
+ }
+
+ /**
+ * Set the key type value.
+ *
+ * @param kty the key type
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withKty(JsonWebKeyType kty) {
+ this.kty = kty;
+ return this;
+ }
+
+ /**
+ * Get the key operations.
+ *
+ * @return the key operations.
+ */
+ @JsonProperty("key_ops")
+ public List keyOps() {
+ return this.keyOps;
+ }
+
+ /**
+ * Set the key operations value.
+ *
+ * @param keyOps the key operations value to set
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withKeyOps(List keyOps) {
+ this.keyOps = keyOps;
+ return this;
+ }
+
+ /**
+ * Get the RSA modulus value.
+ *
+ * @return the RSA modulus value.
+ */
+ @JsonProperty("n")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] n() {
+ return this.n;
+ }
+
+ /**
+ * Set the RSA modulus value.
+ *
+ * @param n the RSA modulus value to set
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withN(byte[] n) {
+ this.n = n;
+ return this;
+ }
+
+ /**
+ * Get the RSA public exponent value.
+ * @return the RSA public exponent value.
+ */
+ @JsonProperty("e")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] e() {
+ return this.e;
+ }
+
+ /**
+ * Set the RSA public exponent value.
+ *
+ * @param e RSA public exponent value to set
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withE(byte[] e) {
+ this.e = e;
+ return this;
+ }
+
+ /**
+ * Get the RSA private exponent value.
+ * @return the RSA private exponent value.
+ */
+ @JsonProperty("d")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] d() {
+ return this.d;
+ }
+
+ /**
+ * Set RSA private exponent value.
+ *
+ * @param d the RSA private exponent value to set.
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withD(byte[] d) {
+ this.d = d;
+ return this;
+ }
+
+ /**
+ * Get the RSA Private Key Parameter value.
+ * @return the RSA Private Key Parameter value.
+ */
+ @JsonProperty("dp")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] dp() {
+ return this.dp;
+ }
+
+ /**
+ * Set RSA Private Key Parameter value.
+ * @param dp the RSA Private Key Parameter value to set.
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withDp(byte[] dp) {
+ this.dp = dp;
+ return this;
+ }
+
+ /**
+ * Get the RSA Private Key Parameter value.
+ * @return the RSA Private Key Parameter value.
+ */
+ @JsonProperty("dq")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] dq() {
+ return this.dq;
+ }
+
+ /**
+ * Set RSA Private Key Parameter value .
+ * @param dq the RSA Private Key Parameter value to set.
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withDq(byte[] dq) {
+ this.dq = dq;
+ return this;
+ }
+
+ /**
+ * Get the RSA Private Key Parameter value.
+ * @return the RSA Private Key Parameter value.
+ */
+ @JsonProperty("qi")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] qi() {
+ return this.qi;
+ }
+
+ /**
+ * Set RSA Private Key Parameter value.
+ * @param qi the RSA Private Key Parameter value to set.
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withQi(byte[] qi) {
+ this.qi = qi;
+ return this;
+ }
+
+ /**
+ * Get the RSA secret prime value.
+ * @return the RSA secret prime value.
+ */
+ @JsonProperty("p")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] p() {
+ return this.p;
+ }
+
+ /**
+ * Set the RSA secret prime value.
+ * @param p the RSA secret prime value.
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withP(byte[] p) {
+ this.p = p;
+ return this;
+ }
+
+ /**
+ * Get RSA secret prime, with p < q value.
+ * @return the RSA secret prime, with p < q value.
+ */
+ @JsonProperty("q")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] q() {
+ return this.q;
+ }
+
+ /**
+ * Set the RSA secret prime, with p < q value.
+ * @param q the the RSA secret prime, with p < q value to be set.
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withQ(byte[] q) {
+ this.q = q;
+ return this;
+ }
+
+ /**
+ * Get Symmetric key value.
+ * @return the symmetric key value.
+ */
+ @JsonProperty("k")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] k() {
+ return this.k;
+ }
+
+ /**
+ * Set the Symmetric key value.
+ * @param k the symmetric key value to set.
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withK(byte[] k) {
+ this.k = k;
+ return this;
+ }
+
+ /**
+ * Get HSM Token value, used with Bring Your Own Key.
+ * @return HSM Token, used with Bring Your Own Key.
+ */
+ @JsonProperty("key_hsm")
+ @JsonSerialize(using = Base64UrlJsonSerializer.class)
+ @JsonDeserialize(using = Base64UrlJsonDeserializer.class)
+ public byte[] t() {
+ return this.t;
+ }
+
+ /**
+ * Set HSM Token value, used with Bring Your Own Key.
+ * @param t HSM Token value to set, used with Bring Your Own Key
+ * @return the JsonWebKey object itself.
+ */
+ public JsonWebKey withT(byte[] t) {
+ this.t = t;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ return mapper.writeValueAsString(this);
+ } catch (JsonGenerationException e) {
+ throw new IllegalStateException(e);
+ } catch (JsonMappingException e) {
+ throw new IllegalStateException(e);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Get the RSA public key spec value.
+ *
+ * @return the RSA public key spec value
+ */
+ private RSAPublicKeySpec getRSAPublicKeySpec() {
+
+ return new RSAPublicKeySpec(toBigInteger(n), toBigInteger(e));
+ }
+
+ /**
+ * Get the RSA private key spec value.
+ *
+ * @return the RSA private key spec value
+ */
+ private RSAPrivateKeySpec getRSAPrivateKeySpec() {
+
+ return new RSAPrivateCrtKeySpec(toBigInteger(n), toBigInteger(e), toBigInteger(d), toBigInteger(p),
+ toBigInteger(q), toBigInteger(dp), toBigInteger(dq), toBigInteger(qi));
+ }
+
+ /**
+ * Get the RSA public key value.
+ *
+ * @param provider the Java security provider.
+ * @return the RSA public key value
+ */
+ private PublicKey getRSAPublicKey(Provider provider) {
+
+ try {
+ RSAPublicKeySpec publicKeySpec = getRSAPublicKeySpec();
+ KeyFactory factory = provider != null ? KeyFactory.getInstance("RSA", provider) : KeyFactory.getInstance("RSA");
+
+ return factory.generatePublic(publicKeySpec);
+ } catch (GeneralSecurityException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Get the RSA private key value.
+ *
+ * @param provider the Java security provider.
+ * @return the RSA private key value
+ */
+ private PrivateKey getRSAPrivateKey(Provider provider) {
+
+ try {
+ RSAPrivateKeySpec privateKeySpec = getRSAPrivateKeySpec();
+ KeyFactory factory = provider != null ? KeyFactory.getInstance("RSA", provider) : KeyFactory.getInstance("RSA");
+
+ return factory.generatePrivate(privateKeySpec);
+ } catch (GeneralSecurityException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Verifies if the key is an RSA key.
+ */
+ private void checkRSACompatible() {
+ if (!JsonWebKeyType.RSA.equals(kty) && !JsonWebKeyType.RSA_HSM.equals(kty)) {
+ throw new UnsupportedOperationException("Not an RSA key");
+ }
+ }
+
+ private static byte[] toByteArray(BigInteger n) {
+ byte[] result = n.toByteArray();
+ if (result[0] == 0) {
+ // The leading zero is used to let the number positive. Since RSA
+ // parameters are always positive, we remove it.
+ return Arrays.copyOfRange(result, 1, result.length);
+ }
+ return result;
+ }
+
+ private static BigInteger toBigInteger(byte[] b) {
+ if (b[0] < 0) {
+ // RSA parameters are always positive numbers, so if the first byte
+ // is negative, we need to add a leading zero
+ // to make the entire BigInteger positive.
+ byte[] temp = new byte[1 + b.length];
+ System.arraycopy(b, 0, temp, 1, b.length);
+ b = temp;
+ }
+ return new BigInteger(b);
+ }
+
+ /**
+ * Converts RSA key pair to JSON web key.
+ * @param keyPair RSA key pair
+ * @return the JSON web key, converted from RSA key pair.
+ */
+ public static JsonWebKey fromRSA(KeyPair keyPair) {
+
+ RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyPair.getPrivate();
+ JsonWebKey key = null;
+
+ if (privateKey != null) {
+
+ key = new JsonWebKey()
+ .withKty(JsonWebKeyType.RSA)
+ .withN(toByteArray(privateKey.getModulus()))
+ .withE(toByteArray(privateKey.getPublicExponent()))
+ .withD(toByteArray(privateKey.getPrivateExponent()))
+ .withP(toByteArray(privateKey.getPrimeP()))
+ .withQ(toByteArray(privateKey.getPrimeQ()))
+ .withDp(toByteArray(privateKey.getPrimeExponentP()))
+ .withDq(toByteArray(privateKey.getPrimeExponentQ()))
+ .withQi(toByteArray(privateKey.getCrtCoefficient()));
+ } else {
+
+ RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
+
+ key = new JsonWebKey()
+ .withKty(JsonWebKeyType.RSA)
+ .withN(toByteArray(publicKey.getModulus()))
+ .withE(toByteArray(publicKey.getPublicExponent()))
+ .withD(null)
+ .withP(null)
+ .withQ(null)
+ .withDp(null)
+ .withDq(null)
+ .withQi(null);
+ }
+
+ return key;
+ }
+
+ /**
+ * Converts JSON web key to RSA key pair.
+ * @return RSA key pair
+ */
+ public KeyPair toRSA() {
+ return this.toRSA(false);
+ }
+
+ /**
+ * Converts JSON web key to RSA key pair and include the private key if set to true.
+ * @param includePrivateParameters true if the RSA key pair should include the private key. False otherwise.
+ * @return RSA key pair
+ */
+ public KeyPair toRSA(boolean includePrivateParameters) {
+ return toRSA(includePrivateParameters, null);
+ }
+
+ /**
+ * Converts JSON web key to RSA key pair and include the private key if set to true.
+ * @param provider the Java security provider.
+ * @param includePrivateParameters true if the RSA key pair should include the private key. False otherwise.
+ * @return RSA key pair
+ */
+ public KeyPair toRSA(boolean includePrivateParameters, Provider provider) {
+
+ // Must be RSA
+ checkRSACompatible();
+
+ if (includePrivateParameters) {
+ return new KeyPair(getRSAPublicKey(provider), getRSAPrivateKey(provider));
+ } else {
+ return new KeyPair(getRSAPublicKey(provider), null);
+ }
+ }
+
+ /**
+ * Converts AES key to JSON web key.
+ * @param secretKey AES key
+ * @return the JSON web key, converted from AES key.
+ */
+ public static JsonWebKey fromAes(SecretKey secretKey) {
+ if (secretKey == null) {
+ return null;
+ }
+
+ return new JsonWebKey()
+ .withK(secretKey.getEncoded())
+ .withKty(JsonWebKeyType.OCT);
+ }
+
+ /**
+ * Converts JSON web key to AES key.
+ * @return AES key
+ */
+ public SecretKey toAes() {
+ if (k == null) {
+ return null;
+ }
+
+ SecretKey secretKey = new SecretKeySpec(k, "AES");
+ return secretKey;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof JsonWebKey) {
+ return this.equals((JsonWebKey) obj);
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Indicates whether some other {@link JsonWebKey} is "equal to" this one.
+ * @param jwk the other {@link JsonWebKey} to compare with.
+ * @return true if this {@link JsonWebKey} is the same as the jwk argument; false otherwise.
+ */
+ public boolean equals(JsonWebKey jwk) {
+ if (jwk == null) {
+ return false;
+ }
+
+ if (!Objects.equal(kid, jwk.kid)) {
+ return false;
+ }
+
+ if (!Objects.equal(kty, jwk.kty)) {
+ return false;
+ }
+
+ if (!Objects.equal(keyOps, jwk.keyOps)) {
+ return false;
+ }
+
+ if (!Arrays.equals(k, jwk.k)) {
+ return false;
+ }
+
+ // Public parameters
+ if (!Arrays.equals(n, jwk.n)) {
+ return false;
+ }
+ if (!Arrays.equals(e, jwk.e)) {
+ return false;
+ }
+
+ // Private parameters
+ if (!Arrays.equals(d, jwk.d)) {
+ return false;
+ }
+ if (!Arrays.equals(dp, jwk.dp)) {
+ return false;
+ }
+ if (!Arrays.equals(dq, jwk.dq)) {
+ return false;
+ }
+ if (!Arrays.equals(qi, jwk.qi)) {
+ return false;
+ }
+ if (!Arrays.equals(p, jwk.p)) {
+ return false;
+ }
+ if (!Arrays.equals(q, jwk.q)) {
+ return false;
+ }
+
+ // HSM token
+ if (!Arrays.equals(t, jwk.t)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Verifies whether the {@link JsonWebKey} has private key.
+ * @return true if the {@link JsonWebKey} has private key; false otherwise.
+ */
+ public boolean hasPrivateKey() {
+
+ if (JsonWebKeyType.OCT.equals(kty)) {
+ return k != null;
+ }
+
+ else if (JsonWebKeyType.RSA.equals(kty) || JsonWebKeyType.RSA_HSM.equals(kty)) {
+ return (d != null && dp != null && dq != null && qi != null && p != null && q != null);
+ }
+
+ return false;
+ }
+
+ /**
+ * Verifies whether the {@link JsonWebKey} is valid.
+ * @return true if the {@link JsonWebKey} is valid; false otherwise.
+ */
+ @JsonIgnore
+ public boolean isValid() {
+ if (kty == null) {
+ return false;
+ }
+
+ if (keyOps != null) {
+ final Set set = new HashSet(JsonWebKeyOperation.ALL_OPERATIONS);
+ for (int i = 0; i < keyOps.size(); i++) {
+ if (!set.contains(keyOps.get(i))) {
+ return false;
+ }
+ }
+ }
+
+ if (JsonWebKeyType.OCT.equals(kty)) {
+ return isValidOctet();
+ }
+
+ else if (JsonWebKeyType.RSA.equals(kty)) {
+ return isValidRsa();
+ }
+
+ else if (JsonWebKeyType.RSA_HSM.equals(kty)) {
+ return isValidRsaHsm();
+ }
+ return false;
+ }
+
+ private boolean isValidOctet() {
+ if (k != null) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isValidRsa() {
+ if (n == null || e == null) {
+ return false;
+ }
+
+ return hasPrivateKey()
+ || (d == null && dp == null && dq == null && qi == null && p == null && q == null);
+ }
+
+ private boolean isValidRsaHsm() {
+ // MAY have public key parameters
+ if ((n == null && e != null) || (n != null && e == null)) {
+ return false;
+ }
+
+ // no private key
+ if (hasPrivateKey()) {
+ return false;
+ }
+
+ // MUST have ( T || ( N && E ) )
+ boolean tokenParameters = t != null;
+ boolean publicParameters = (n != null && e != null);
+
+ if (tokenParameters && publicParameters) {
+ return false;
+ }
+
+ return (tokenParameters || publicParameters);
+ }
+
+ /**
+ * Clear key materials.
+ */
+ public void clearMemory() {
+ zeroArray(k); k = null;
+ zeroArray(n); n = null;
+ zeroArray(e); e = null;
+ zeroArray(d); d = null;
+ zeroArray(dp); dp = null;
+ zeroArray(dq); dq = null;
+ zeroArray(qi); qi = null;
+ zeroArray(p); p = null;
+ zeroArray(q); q = null;
+ zeroArray(t); t = null;
+ }
+
+ private static void zeroArray(byte[] bytes) {
+ if (bytes != null) {
+ Arrays.fill(bytes, (byte) 0);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = 48313; // setting it to a random prime number
+ if (kid != null) {
+ hashCode += kid.hashCode();
+ }
+
+ if (JsonWebKeyType.OCT.equals(kty)) {
+ hashCode += hashCode(k);
+ }
+
+ else if (JsonWebKeyType.RSA.equals(kty)) {
+ hashCode += hashCode(n);
+ }
+
+ else if (JsonWebKeyType.RSA_HSM.equals(kty)) {
+ hashCode += hashCode(t);
+ }
+
+ return hashCode;
+ }
+
+ private static int hashCode(byte[] obj) {
+ int hashCode = 0;
+
+ if (obj == null || obj.length == 0) {
+ return 0;
+ }
+
+ for (int i = 0; i < obj.length; i++) {
+ hashCode = (hashCode << 3) | (hashCode >> 29) ^ obj[i];
+ }
+ return hashCode;
+ }
+}
\ No newline at end of file
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyEncryptionAlgorithm.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyEncryptionAlgorithm.java
new file mode 100755
index 000000000000..67e5e99dd08c
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyEncryptionAlgorithm.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.webkey;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Defines values for JsonWebKeyEncryptionAlgorithm.
+ */
+public final class JsonWebKeyEncryptionAlgorithm {
+ /** Static value RSA-OAEP for JsonWebKeyEncryptionAlgorithm. */
+ public static final JsonWebKeyEncryptionAlgorithm RSA_OAEP = new JsonWebKeyEncryptionAlgorithm("RSA-OAEP");
+
+ /** Static value RSA1_5 for JsonWebKeyEncryptionAlgorithm. */
+ public static final JsonWebKeyEncryptionAlgorithm RSA1_5 = new JsonWebKeyEncryptionAlgorithm("RSA1_5");
+
+ private String value;
+
+ /**
+ * Creates a custom value for JsonWebKeyEncryptionAlgorithm.
+ * @param value the custom value
+ */
+ public JsonWebKeyEncryptionAlgorithm(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JsonWebKeyEncryptionAlgorithm)) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ JsonWebKeyEncryptionAlgorithm rhs = (JsonWebKeyEncryptionAlgorithm) obj;
+ if (value == null) {
+ return rhs.value == null;
+ } else {
+ return value.equals(rhs.value);
+ }
+ }
+
+ /**
+ * All the JWK encryption algorithms.
+ */
+ public static final List ALL_ALGORITHMS =
+ Collections.unmodifiableList(Arrays.asList(RSA_OAEP, RSA1_5));
+}
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyOperation.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyOperation.java
new file mode 100755
index 000000000000..9dbb9d30fce6
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyOperation.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.webkey;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Defines values for JsonWebKeyOperation.
+ */
+public final class JsonWebKeyOperation {
+ /** Static value encrypt for JsonWebKeyOperation. */
+ public static final JsonWebKeyOperation ENCRYPT = new JsonWebKeyOperation("encrypt");
+
+ /** Static value decrypt for JsonWebKeyOperation. */
+ public static final JsonWebKeyOperation DECRYPT = new JsonWebKeyOperation("decrypt");
+
+ /** Static value sign for JsonWebKeyOperation. */
+ public static final JsonWebKeyOperation SIGN = new JsonWebKeyOperation("sign");
+
+ /** Static value verify for JsonWebKeyOperation. */
+ public static final JsonWebKeyOperation VERIFY = new JsonWebKeyOperation("verify");
+
+ /** Static value wrapKey for JsonWebKeyOperation. */
+ public static final JsonWebKeyOperation WRAP_KEY = new JsonWebKeyOperation("wrapKey");
+
+ /** Static value unwrapKey for JsonWebKeyOperation. */
+ public static final JsonWebKeyOperation UNWRAP_KEY = new JsonWebKeyOperation("unwrapKey");
+
+ private String value;
+
+ /**
+ * Creates a custom value for JsonWebKeyOperation.
+ * @param value the custom value
+ */
+ public JsonWebKeyOperation(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JsonWebKeyOperation)) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ JsonWebKeyOperation rhs = (JsonWebKeyOperation) obj;
+ if (value == null) {
+ return rhs.value == null;
+ } else {
+ return value.equals(rhs.value);
+ }
+ }
+
+ /**
+ * All the JWK operations.
+ */
+ public static final List ALL_OPERATIONS =
+ Collections.unmodifiableList(Arrays.asList(ENCRYPT, DECRYPT, SIGN, VERIFY, WRAP_KEY, UNWRAP_KEY));
+}
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeySignatureAlgorithm.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeySignatureAlgorithm.java
new file mode 100755
index 000000000000..5e532c10cd29
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeySignatureAlgorithm.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.webkey;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Defines values for JsonWebKeySignatureAlgorithm.
+ */
+public final class JsonWebKeySignatureAlgorithm {
+ /** Static value RS256 for JsonWebKeySignatureAlgorithm. */
+ public static final JsonWebKeySignatureAlgorithm RS256 = new JsonWebKeySignatureAlgorithm("RS256");
+
+ /** Static value RS384 for JsonWebKeySignatureAlgorithm. */
+ public static final JsonWebKeySignatureAlgorithm RS384 = new JsonWebKeySignatureAlgorithm("RS384");
+
+ /** Static value RS512 for JsonWebKeySignatureAlgorithm. */
+ public static final JsonWebKeySignatureAlgorithm RS512 = new JsonWebKeySignatureAlgorithm("RS512");
+
+ /** Static value RSNULL for JsonWebKeySignatureAlgorithm. */
+ public static final JsonWebKeySignatureAlgorithm RSNULL = new JsonWebKeySignatureAlgorithm("RSNULL");
+
+ private String value;
+
+ /**
+ * Creates a custom value for JsonWebKeySignatureAlgorithm.
+ * @param value the custom value
+ */
+ public JsonWebKeySignatureAlgorithm(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JsonWebKeySignatureAlgorithm)) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ JsonWebKeySignatureAlgorithm rhs = (JsonWebKeySignatureAlgorithm) obj;
+ if (value == null) {
+ return rhs.value == null;
+ } else {
+ return value.equals(rhs.value);
+ }
+ }
+
+ /**
+ * All the JWK signature algorithms.
+ */
+ public static final List ALL_ALGORITHMS =
+ Collections.unmodifiableList(Arrays.asList(RS256, RS384, RS512, RSNULL));
+}
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyType.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyType.java
new file mode 100755
index 000000000000..8a7c9dbffbc8
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/JsonWebKeyType.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault.webkey;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Defines values for JsonWebKeyType.
+ */
+public final class JsonWebKeyType {
+ /** Static value EC for JsonWebKeyType. */
+ public static final JsonWebKeyType EC = new JsonWebKeyType("EC");
+
+ /** Static value RSA for JsonWebKeyType. */
+ public static final JsonWebKeyType RSA = new JsonWebKeyType("RSA");
+
+ /** Static value RSA-HSM for JsonWebKeyType. */
+ public static final JsonWebKeyType RSA_HSM = new JsonWebKeyType("RSA-HSM");
+
+ /** Static value oct for JsonWebKeyType. */
+ public static final JsonWebKeyType OCT = new JsonWebKeyType("oct");
+
+ private String value;
+
+ /**
+ * Creates a custom value for JsonWebKeyType.
+ * @param value the custom value
+ */
+ public JsonWebKeyType(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JsonWebKeyType)) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ JsonWebKeyType rhs = (JsonWebKeyType) obj;
+ if (value == null) {
+ return rhs.value == null;
+ } else {
+ return value.equals(rhs.value);
+ }
+ }
+
+ /**
+ * All the JWK key types.
+ */
+ public static final List ALL_TYPES =
+ Collections.unmodifiableList(Arrays.asList(EC, RSA, RSA_HSM, OCT));
+}
diff --git a/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/package-info.java b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/package-info.java
new file mode 100755
index 000000000000..6768bb504520
--- /dev/null
+++ b/azure-keyvault-webkey/src/main/java/com/microsoft/azure/keyvault/webkey/package-info.java
@@ -0,0 +1,8 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+
+/**
+ * This package contains the classes for key vault JSON web key.
+ */
+package com.microsoft.azure.keyvault.webkey;
diff --git a/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/AesValidationTests.java b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/AesValidationTests.java
new file mode 100644
index 000000000000..3d1ed2b07c77
--- /dev/null
+++ b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/AesValidationTests.java
@@ -0,0 +1,92 @@
+package com.microsoft.azure.keyvault.webkey.test;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.azure.keyvault.webkey.JsonWebKey;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyOperation;
+
+public class AesValidationTests {
+ private static final String TRANSFORMATION = "AES";
+
+ @Test
+ public void aesKeyValidation() throws Exception {
+ KeyGenerator keyGen = KeyGenerator.getInstance(TRANSFORMATION);
+ keyGen.init(256);
+
+ SecretKey skey = keyGen.generateKey();
+ JsonWebKey key = serializeDeserialize(skey);
+ Assert.assertTrue(key.hasPrivateKey());
+ Assert.assertTrue(key.isValid());
+
+ SecretKey secretKey = key.toAes();
+ encryptDecrypt(secretKey);
+
+ // Compare equal JSON web keys
+ JsonWebKey sameKey = JsonWebKey.fromAes(skey);
+ Assert.assertEquals(key, key);
+ Assert.assertEquals(key, sameKey);
+ Assert.assertEquals(key.hashCode(), sameKey.hashCode());
+ }
+
+ @Test
+ public void invalidKeyOps() throws Exception {
+ JsonWebKey key = getAes();
+ key.withKeyOps(Arrays.asList(JsonWebKeyOperation.ENCRYPT, new JsonWebKeyOperation("foo")));
+ Assert.assertFalse(key.isValid());
+ }
+
+ @Test
+ public void octHashCode() throws Exception {
+ JsonWebKey key = getAes();
+
+ // Compare hash codes for unequal JWK that would not map to the same hash
+ Assert.assertNotEquals(key.hashCode(), new JsonWebKey().withK(key.k()).hashCode());
+ Assert.assertNotEquals(key.hashCode(), new JsonWebKey().withKty(key.kty()).hashCode());
+
+ // Compare hash codes for unequal JWK that would map to the same hash
+ Assert.assertEquals(key.hashCode(), new JsonWebKey().withK(key.k()).withKty(key.kty()).hashCode());
+ }
+
+ private static JsonWebKey getAes() throws Exception {
+ KeyGenerator keyGen = KeyGenerator.getInstance(TRANSFORMATION);
+ keyGen.init(256);
+
+ SecretKey skey = keyGen.generateKey();
+ return JsonWebKey.fromAes(skey);
+ }
+
+ private static JsonWebKey serializeDeserialize(SecretKey skey) throws Exception {
+ JsonWebKey webKey = JsonWebKey.fromAes(skey);
+ String serializedKey = webKey.toString();
+ ObjectMapper mapper = new ObjectMapper();
+ return mapper.readValue(serializedKey, JsonWebKey.class);
+ }
+
+ private static void encryptDecrypt(SecretKey key) throws Exception {
+ byte[] plaintext = new byte[10];
+ new Random().nextBytes(plaintext);
+ byte[] cipherText = encrypt(key, plaintext);
+ Assert.assertArrayEquals(decrypt(key, cipherText), plaintext);
+ }
+
+ private static byte[] encrypt(SecretKey key, byte[] plaintext) throws Exception {
+ Cipher cipher = Cipher.getInstance(TRANSFORMATION);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ return cipher.doFinal(plaintext);
+ }
+
+ private static byte[] decrypt(SecretKey key, byte[] ciphertext) throws Exception {
+ Cipher cipher = Cipher.getInstance(TRANSFORMATION);
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ return cipher.doFinal(ciphertext);
+ }
+}
diff --git a/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/ClearMemoryTests.java b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/ClearMemoryTests.java
new file mode 100644
index 000000000000..f28801584059
--- /dev/null
+++ b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/ClearMemoryTests.java
@@ -0,0 +1,56 @@
+package com.microsoft.azure.keyvault.webkey.test;
+
+import java.util.Random;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.microsoft.azure.keyvault.webkey.JsonWebKey;
+
+public class ClearMemoryTests {
+
+ @Test
+ public void clearMemory()
+ {
+ JsonWebKey key = new JsonWebKey()
+ .withD(getRandomByte())
+ .withDp(getRandomByte())
+ .withDq(getRandomByte())
+ .withE(getRandomByte())
+ .withK(getRandomByte())
+ .withN(getRandomByte())
+ .withP(getRandomByte())
+ .withQ(getRandomByte())
+ .withQi(getRandomByte())
+ .withT(getRandomByte());
+ key.clearMemory();
+ Assert.assertNull(key.d());
+ Assert.assertNull(key.dp());
+ Assert.assertNull(key.dq());
+ Assert.assertNull(key.e());
+ Assert.assertNull(key.k());
+ Assert.assertNull(key.n());
+ Assert.assertNull(key.p());
+ Assert.assertNull(key.q());
+ Assert.assertNull(key.qi());
+ Assert.assertNull(key.t());
+
+ // Compare it with a newly created JsonWebKey with no properties set.
+ JsonWebKey key2 = new JsonWebKey();
+ Assert.assertTrue(key2.equals(key));
+ }
+
+ @Test
+ public void clearNullMemory()
+ {
+ JsonWebKey key = new JsonWebKey();
+ key.clearMemory();
+ }
+
+ private static byte[] getRandomByte() {
+ byte[] bytes = new byte[10];
+ new Random().nextBytes(bytes);
+ return bytes;
+ }
+
+}
diff --git a/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/RsaHsmValidationTests.java b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/RsaHsmValidationTests.java
new file mode 100644
index 000000000000..816db50104ae
--- /dev/null
+++ b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/RsaHsmValidationTests.java
@@ -0,0 +1,45 @@
+package com.microsoft.azure.keyvault.webkey.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.azure.keyvault.webkey.JsonWebKey;
+
+public class RsaHsmValidationTests {
+
+ String keyWithoutT = "{\"kid\":\"key_id\",\"kty\":\"RSA-HSM\",\"key_ops\":[\"encrypt\",\"decrypt\"],\"n\":\"1_6ZtP288hEkKML-L6nFyZh1PD1rmAgwbbwjEvTSDK_008BYWhjp_6ULy9BhWtRIytNkPkm9gzaBTrCpp-vyDXPGa836Htp-w8u5JmxoUZchJh576m3m-8ZYWTmZSAp5SpruyKAmLSxPJHEWPXQntnmuTMjb9HBT9Ltrwc0ZDk-jsMLYunDJrNmrRUxQgb0zQ_Tl5fJjj8j-0KVx2RXtbfWFvf5fRdBYyP3m0aUpoopQPwtXszD2LcSKMJ_TnmnvMWr8MOA5aRlBaGdBk7zBgRafvDPam3Q2AvFA9mfcAVncpfZ3JFm73VARw6MofXtRqOHtZ7y4oNbY95xXwU2r6w\",\"e\":\"AQAB\"}";
+ String keyWithT = "{\"kid\":\"key_id\",\"kty\":\"RSA-HSM\",\"key_ops\":[\"encrypt\",\"decrypt\"],\"key_hsm\":\"T-TOKEN\"}";
+
+ @Test
+ public void rsaHsmValidation() throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonWebKey keyNoT = mapper.readValue(keyWithoutT, JsonWebKey.class);
+ JsonWebKey keyT = mapper.readValue(keyWithT, JsonWebKey.class);
+
+ Assert.assertTrue(keyNoT.isValid());
+ Assert.assertFalse(keyNoT.hasPrivateKey());
+
+ Assert.assertTrue(keyT.isValid());
+ Assert.assertFalse(keyT.hasPrivateKey());
+ }
+
+ @Test
+ public void rsaHsmHashCode() throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonWebKey keyNoT = mapper.readValue(keyWithoutT, JsonWebKey.class);
+ JsonWebKey keyT = mapper.readValue(keyWithT, JsonWebKey.class);
+
+ Assert.assertNotEquals(keyT.hashCode(), keyNoT.hashCode());
+
+ // Compare hash codes for unequal JWK that would not map to the same hash
+ Assert.assertNotEquals(keyT.hashCode(), new JsonWebKey().withKid(keyT.kid()).withT(keyT.t()).hashCode());
+ Assert.assertNotEquals(keyT.hashCode(), new JsonWebKey().withKid(keyT.kid()).withKty(keyT.kty()).hashCode());
+ Assert.assertNotEquals(keyNoT.hashCode(), new JsonWebKey().hashCode());
+
+ // Compare hash codes for unequal JWK that would map to the same hash
+ Assert.assertEquals(keyT.hashCode(),
+ new JsonWebKey().withKid(keyT.kid()).withKty(keyT.kty()).withT(keyT.t()).hashCode());
+ Assert.assertEquals(keyNoT.hashCode(), new JsonWebKey().withKid(keyT.kid()).hashCode());
+ }
+}
diff --git a/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/RsaValidationTests.java b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/RsaValidationTests.java
new file mode 100644
index 000000000000..cb5bcb3de228
--- /dev/null
+++ b/azure-keyvault-webkey/src/test/java/com/microsoft/azure/keyvault/webkey/test/RsaValidationTests.java
@@ -0,0 +1,126 @@
+package com.microsoft.azure.keyvault.webkey.test;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableMap;
+import com.microsoft.azure.keyvault.webkey.JsonWebKey;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyOperation;
+
+public class RsaValidationTests {
+
+ private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding";
+
+ @Test
+ public void rsaPublicKeyValidation() throws Exception {
+ for(String keyStr : keys.values())
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonWebKey key = mapper.readValue(keyStr, JsonWebKey.class);
+ Assert.assertTrue(key.hasPrivateKey());
+ Assert.assertTrue(key.isValid());
+
+ KeyPair keyPair = key.toRSA();
+ validateRsaKey(keyPair, key);
+ Assert.assertNull(keyPair.getPrivate());
+
+ // Compare equal JSON web keys
+ JsonWebKey sameKey = mapper.readValue(keyStr, JsonWebKey.class);
+ Assert.assertEquals(key, key);
+ Assert.assertEquals(key, sameKey);
+ Assert.assertEquals(key.hashCode(), sameKey.hashCode());
+ }
+ }
+
+ @Test
+ public void rsaPrivateKeyValidation() throws Exception {
+ for(String keyStr : keys.values())
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonWebKey key = mapper.readValue(keyStr, JsonWebKey.class);
+
+ KeyPair keyPairWithPrivate = key.toRSA(true);
+ validateRsaKey(keyPairWithPrivate, key);
+ encryptDecrypt(keyPairWithPrivate.getPublic(), keyPairWithPrivate.getPrivate());
+ }
+ }
+
+ @Test
+ public void rsaHashCode() throws Exception {
+
+ String keyStr = (String) keys.values().toArray()[0];
+ ObjectMapper mapper = new ObjectMapper();
+ JsonWebKey key = mapper.readValue(keyStr, JsonWebKey.class);
+
+ // Compare hash codes for unequal JWK that would not map to the same hash
+ Assert.assertNotEquals(key.hashCode(), new JsonWebKey().withKid(key.kid()).withN(key.n()).hashCode());
+ Assert.assertNotEquals(key.hashCode(), new JsonWebKey().withKid(key.kid()).withKty(key.kty()).hashCode());
+ Assert.assertNotEquals(key.hashCode(), new JsonWebKey().withKid(key.kid()).withT(key.t()).hashCode());
+
+ // Compare hash codes for unequal JWK that would map to the same hash
+ Assert.assertEquals(key.hashCode(),
+ new JsonWebKey().withN(key.n()).withKty(key.kty()).withKid(key.kid()).hashCode());
+ }
+
+ private static void encryptDecrypt(PublicKey publicKey, PrivateKey privateKey) throws Exception {
+ byte[] plaintext = new byte[10];
+ new Random().nextBytes(plaintext);
+ byte[] cipherText = encrypt(publicKey, plaintext);
+ if(privateKey != null) {
+ Assert.assertArrayEquals(decrypt(privateKey, cipherText), plaintext);
+ }
+ }
+
+ private static byte[] encrypt(PublicKey key, byte[] plaintext) throws Exception {
+ Cipher cipher = Cipher.getInstance(TRANSFORMATION);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ return cipher.doFinal(plaintext);
+ }
+
+ private static byte[] decrypt(PrivateKey key, byte[] ciphertext) throws Exception {
+ Cipher cipher = Cipher.getInstance(TRANSFORMATION);
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ return cipher.doFinal(ciphertext);
+ }
+
+ private static void validateRsaKey(KeyPair keyPair, JsonWebKey key) throws Exception {
+ JsonWebKey jsonWebKey = JsonWebKey.fromRSA(keyPair);
+ boolean includePrivateKey = keyPair.getPrivate() != null;
+ KeyPair keyPair2 = jsonWebKey.toRSA(includePrivateKey);
+
+ Assert.assertTrue(includePrivateKey == jsonWebKey.hasPrivateKey());
+
+ PublicKey publicKey = keyPair2.getPublic();
+ PrivateKey privateKey = keyPair2.getPrivate();
+
+ if(includePrivateKey) {
+ Assert.assertNotNull(privateKey);
+
+ // set the missing properties to compare the keys
+ jsonWebKey.withKeyOps(new ArrayList(key.keyOps()));
+ jsonWebKey.withKid(new String(key.kid()));
+ Assert.assertEquals(jsonWebKey, key);
+ Assert.assertEquals(key.hashCode(), jsonWebKey.hashCode());
+ }
+
+ encryptDecrypt(publicKey, privateKey);
+ }
+
+ Map keys = ImmutableMap.builder()
+ .put(512, "{\"kty\":\"RSA\",\"n\":\"uOXIpiH9L0h_byTuP3fcMvKbfS85eTKvxW2skw4oIU2TM3ceFvlDwDK4gKHl4qE4z18bz0qrv9ElstOrT96piQ\",\"e\":\"AQAB\",\"d\":\"And2KMA5uQ1r9MwuvZCODi0D2lcFvz7oBbenyxqmuhTYfdGcuGE9FZg5V6ZcNwBK_eYGZqSwL1Gh2EmzG6AxwQ\",\"dp\":\"CEh8kzQnCRK97NKQeV_wGgWsLYlmgis7Cms85_DIqwE\",\"dq\":\"TAi0G0iE5pvMpiEN2y189hjSRSqE6Unc1lXaE3hcnWE\",\"qi\":\"2HhNqW3QBv1R_iEpu44KVMQs0DdnY5oWp1lH6hgPhXU\",\"p\":\"5BblSoMJmO5Afa-urQFzFpBfACt1175NMUs4tHUYEkE\",\"q\":\"z4Xdf_FU-51wTkW5mFJ6QoDK-GrkMXSdct9hdW26NUk\",\"key_ops\":[\"wrapKey\",\"unwrapKey\",\"encrypt\",\"decrypt\",\"sign\",\"verify\"],\"kid\":\"key_id\"}")
+ .put(1024, "{\"kty\":\"RSA\",\"n\":\"zicSNMeAUYwp6V6UQlJ8gW04o6O4ZJBIefsLnV6-to1YkzgDu6vDBWb83DcDgB2x63W-ZVK23F4dcJcULu1VM-jX83Sfg0b_ZrugiiXCnZ4iidLNcY5QOS1dSHjfI1eWH6QdLPSIE3sHk-BILrIXqoyIJH-LFxzMu--4bDlej2M\",\"e\":\"AQAB\",\"d\":\"A4h7F2YT6bhG2TXcJ9OiFQj6LFPLmG2gnSnGssiQHDDWXWLB-mvT-9O4CBr2ETJxFvsw0cVV8CqGXQrTaodGxOuCGNmYoczodvlhUBJyMBxAI2or5eZUF9jRiECvigoxNVWKsqWxypvq_X1pMfQbh9ot7F6KOJAEg6wlLTc-fIE\",\"dp\":\"v2JbDaZfi3OCCLMtNMjOxfNsBOPb1IqerGux4IR17fLIzG6JlcyaR4uasILdjE4VufqnppZ6FIlFCZUiyIP0GQ\",\"dq\":\"m6NTbNOxN2qnont_qttyqg6WvOA6zWK55-ZnX8hShmlv0ySgtw1PfOWso3wpRMHAujTOfUSeI14DgOLHLNkKtQ\",\"qi\":\"HOcBZfyxW1dSnghCvdTuKL3jLSww6k_v0jhYET32gyKe8od7uxP7w0dXZ8al4zQ3xGxrip9y7jJi0pjG-Z4uGw\",\"p\":\"6dlyTUBrwxLyLbr0X3yqmNu3VrHSt2zbW8jueZFWXPELlbuQ6EKrHoR39BM8MSjFN5PfZbsBhcqNBkqhitj6xw\",\"q\":\"4a4DOrnZt4423myMKmhgDINvIdNmLCHG0aE8UWcSPKO6RFhzHX46NJSoOuk9gvccMKEXOpcJC6P8b8ypN-OKhQ\",\"key_ops\":[\"wrapKey\",\"unwrapKey\",\"encrypt\",\"decrypt\",\"sign\",\"verify\"],\"kid\":\"key_id\"}")
+ .put(2048, "{\"kty\":\"RSA\",\"n\":\"rZ8pnmXkhfmmgNWVVdtNcYy2q0OAcCGIpeFzsN9URqJsiBEiWQfxlUxFTbM4kVWPqjauKt6byvApBGEeMA7Qs8kxwRVP-BD4orXRe9VPgliM92rH0UxQWHmCHUe7G7uUAFPwbiDVhWuFzELxNa6Kljg6Z9DuUKoddmQvlYWj8uSunofCtDi_zzlZKGYTOYJma5IYScHNww1yjLp8-b-Be2UdHbrPkCv6Nuwi6MVIKjPpEeRQgfefRmxDBJQKY3OfydMXZmEwukYXVkUcdIP8XwG2OxnfdRK0oAo0NDebNNVuT89k_3AyZLTr1KbDmx1nnjwa8uB8k-uLtcOC9igbTw\",\"e\":\"AQAB\",\"d\":\"H-z7hy_vVJ9yeZBMtIvt8qpQUK_J51STPwV085otcgud72tPKJXoW2658664ASl9kGwbnLBwb2G3-SEunuGqiNS_PGUB3niob6sFSUMRKsPDsB9HfPoOcCZvwZiWFGRqs6C7vlR1TuJVqRjKJ_ffbf4K51oo6FZPspx7j4AShLAwLUSQ60Ld5QPuxYMYZIMpdVbMVIVHJ26pR4Y18e_0GYmEGnbF5N0HkwqQmfmTiIK5aoGnD3GGgqHeHmWBwh6_WAq90ITLcX_zBeqQUgBSj-Z5v61SroO9Eang36T9mMoYrcPpYwemtAOb4HhQYDj8dCCfbeOcVmvZ9UJKWCX2oQ\",\"dp\":\"HW87UpwPoj3lPI9B9K1hJFeuGgarpakvtHuk1HpZ5hXWFGAJiXoWRV-jvYyjoM2k7RpSxPyuuFFmYHcIxiGFp2ES4HnP0BIhKVa2DyugUxIEcMK53C43Ub4mboJPZTSC3sapKgAmA2ue624sapWmshTPpx9qnUP2Oj3cSMkgMGE\",\"dq\":\"RhwEwb5FYio0GS2tmul8FAYsNH7JDehwI1yUApnTiakhSenFetml4PYyVkKR4csgLZEi3RY6J3R8Tg-36zrZuF7hxhVJn80L5_KETSpfEI3jcrXMVg4SRaMsWLY9Ahxflt2FJgUnHOmWRLmP6_hmaTcxxSACjbyUd_HhwNavD5E\",\"qi\":\"wYPZ4lKIslA1w3FaAzQifnNLABYXXUZ_KAA3a8T8fuxkdE4OP3xIFX7WHhnmBd6uOFiEcGoeq2jNQqDg91rV5661-5muQKcvp4uUsNId5rQw9EZw-kdDcwMtVFTEBfvVuyp83X974xYAHn1Jd8wWohSwrpi1QuH5cQMR5Fm6I1A\",\"p\":\"74Ot7MgxRu4euB31UWnGtrqYPjJmvbjYESS43jfDfo-s62ggV5a39P_YPg6oosgtGHNw0QDxunUOXNu9iriaYPf_imptRk69bKN8Nrl727Y-AaBYdLf1UZuwz8X07FqHAH5ghYpk79djld8QvkUUJLpx6rzcW8BJLTOi46DtzZE\",\"q\":\"uZJu-qenARIt28oj_Jlsk-p_KLnqdczczZfbRDd7XNp6csGLa8R0EyYqUB4xLWELQZsX4tAu9SaAO62tuuEy5wbOAmOVrq2ntoia1mGQSJdoeVq6OqtN300xVnaBc3us0rm8C6-824fEQ1PWXoulXLKcSqBhFT-hQahsYi-kat8\",\"key_ops\":[\"wrapKey\",\"unwrapKey\",\"encrypt\",\"decrypt\",\"sign\",\"verify\"],\"kid\":\"key_id\"}")
+ .put(3072, "{\"kty\":\"RSA\",\"n\":\"03u6K67VN18OzIRZdvCC8F9iOVojF-0kk03JQ7rfwumQMqgxLYOmLkrqLcyJV69XYt32LeEesuwuz_zJbQo9gg4T1pnKJSb-l5xoH1rfnihdc9PyMAH___d_zv3Zg9vdusg668eO1oqS5DtAe517suzwhcMIyCsFNx4aBxCDiPlEwzYISwMQHylt-4d6mbFsqJoGK14WqxTOyv0mLoeeDPs9gmQulGbyjYdZJgqjeRBMuHpXgjs_eMwHuqYmWr-jmbRMzBJpKoAgAJkDxkJzJ7wdf4Bq9HrutVspXqw9ZWh4ImIq65Rm5Mx3JDlUNdlYB0jMyDHpuwAZfr8shACty2d5bvlMnk7aYKngCbX2ZSm6BFInA4mz1eey9Iz8uxnfyEjwaYJCFRDy44P_8aymW4tsLoLYgWnF9NodxcLVbhJjBqsipYiUbvW6PUUB4SVtql4yI3EEcZsFFVAVOnms1sXGXK8vm9V9KU1RSWqF268jMD8s-QHg3a1WmooX6sw5\",\"e\":\"AQAB\",\"d\":\"WKU3m6DcmamcK-jcEUluMTBiHTUlmZ1a4-3Ki7vUmEBLo5gxiOjyatwW_dyKwzjpkbUFQCTpN8ldM-w7SBvvPUkGUsFC5MDMHaO_V0lBi2tTBL6V-T6VXmcRaSOpnaY28liErhkHS_Fo8gbOGCKiW5UKmp7uWu0BciGJemWXJP6LLqJC5qJhixZUFgcrQioHKELrjBkTumFt7tMewokxHDLhjPrONYFTcTSHDzWNYS0OY5NQg_OuvsUTBk8nq4lA2GSQqXyM-B2gbwG6pLSwccwu0x3Fd8qurxg6TSGQAjh69Iyb9ZwiHMsx3XLV95Jmqc0rcEbCzLZUBxX3daGjshw3Yd3pzEXqM8Mz-58p835VPhSMlZB_yvtP72o2QiKybhq1ob5Ygt7hqlqe08K5StN2rzJJoFkwivhfC3_KDX7XSLEK9PzqPaTOkkJu7y7tJgi6aC6Fq-X3fgeLy20LsBKV_SF4Zd323IZ713iGJFJo0f4mDUXfQmU3wrILk40L\",\"dp\":\"V5SlApD1a0ng5XrzEmOV2EVKVLcS7Z2j1WYLVa4BMxSsi8zJal_v8nllEN8ylDTWKCZt6Dg3fcHtOWKYGe7e2fBMwSsKcjPI2aFVHjI18ZMbC1m6eHWK81zlTQ-ZhgiRMXQvsRCX6Qt8PPvqfV4j-YILYfgJbQ_DRYEfJzq9JCQjFwGUiSoZvOBl9jQMM1u4NmOnvodwf8Jk4Oi1DC65U-CjOC7D07eDPNv74Pog6h6x3u7Z9S-ITvP1NX4h0_ot\",\"dq\":\"rg2IrHzp59w8nZbtd4NDk_stRB8xT6T2pxpH3LhNhEbLrmy0sF4Xemm8frlgRWeEn9dUV2nzveorEJF57bZ3cclEqBGtD72y_IRPZTPgDcYhc9l4xKJkJJuA3yWcQ6eHZHjLAZHi9PszYvFiUx1veHU2S_f7aGKjO14n05wb9r-YUmIKt7AVwK94HksflvNIREa867E2OL1lIJiX3azkyMgTnSHvi0bwgdIGp6uPdDwVW_qvvUmlFinDWflgq58\",\"qi\":\"Dw0f0UwU2KN98stNeuk2UVtG-GyKjCxSSYocGBlShsXzxeLn2faLSkkqhUVicW4o2PmedPDpxanDW2Gl7osamaPb25CodPS3JJxeHWrJ6hGBfKqvJnysZ-0zL8wVzwuNLc3VL-jlCudFfGK03MBapA9h3qjAFFhHZRgLH8y64MimARfh2gLldZ0FgNF9zB4yxmVzvpOng4XRJGzSBKdf9QbuL60Tia2rWR7QU2GtbrXlp4KiNZspZuzmBLZPaa82\",\"p\":\"3lnk-l3lG3ahUzPzhInjwTJEDRrAt0YMhpLmO444TNs0MD__RxRQO8EAhLGCuKaNJmKOg-D5-Fup34KBAcFKw1vCh06PNxoIbHmcY1KwrlA3M_47pK74sK532429sM2N0JH9ti4QjtcD85__THeS6I5g8x8xdSH6sm6ubOiUWUQ96fN10pDv-9D7PuoHGEGlndvsRE0GwWmBIjCnIbxXN4kQsE5YXbrY_WTdPXxwTb8F6Cqc2WXIuhZLlSqd8NjD\",\"q\":\"83zNQcd3dTEpO-j6e7hHeKYghVBhIViD6bXDzD3IX--maTnllGMD-xxHNzOURwl_VzwWo1Al_QQSKDMeEnNDXhSU50qbdhdyVDyRXQuR2Fb9hN5SACX-SiPgfs-2buJVZh8JD-VFSI7ou6eMQ9h-uIGnhoxH3vCs7dJgy-mHGPsvqTypaIo3LHGfM21z8h0yqgyYwaanv5UllaustjvRFId_2oWqNtrn6q410s9W5-6Q6xqkrW2m_lUffu7ViRdT\",\"key_ops\":[\"wrapKey\",\"unwrapKey\",\"encrypt\",\"decrypt\",\"sign\",\"verify\"],\"kid\":\"key_id\"}")
+ .put(4096, "{\"kty\":\"RSA\",\"n\":\"mmpRerSZYY4Xx_s89Qn3NMAmJOW0TXtddwjdTedA2CITP_BQW9Q6K7ZEKcAk5W8KwfvAYEIDkWN0iKtoSiBmTJxgCqpDI2MO1D_JJXFP6Tovbtgj1FJ8Ai90w04wmxoCdS9mFC2tE51qUWO7frJpTGrZqVAB8UMH031c3pUPzWedGRvKwj7J-Awtg_IoByaK-qoyRlwfqm8WpHjg6R6Fn1aJY3Fp62l1F3XGayUgqoJmg0_YzYxKpz9WDqIJo15sbyQEpTG6kRybD8T5O8908JU2d3KPp7GOKDNpai5wdaK50QyvaU3BtvKI35IaK367FSVPEZPEoAGgUBCoLXx8N16XHVgjspSMV6NnjBEoehr4xU3nw4cZ-09yZSXJv5FGKmg4pkJGCHQwUfA3XlWNZSPYIgBByyjpMe6gJt_RDBhkkYGVddkwn4HPlMIk3Gi9wzMLuVcLNVeq5k4Us3YsaXdSPI6LSfoosu7mi8qm2JMYlFzbB9_FaxJWqgHlTRSiXX0XNuHPMJoBHtKwh_7VXxiosim8EvszF_Is1ttF77l5lC198slQ5zsZ2XM90Ln9UV04kAyI1jEegDiW37uVSikt-VKyVKSZg5lgmp16CevLnqD2g_YD6fJMmbU4QmeVELhZeQc7Z_XGH7lM1bSeiAJ0dKlDKDURnA0h2LQfquM\",\"e\":\"AQAB\",\"d\":\"D_CvEz5WzGihW9Y7p1qtV5deWKtoaXc1YXcGIWdLR68nfY-OkWw0dRQOWqD92LwVyDX3g02ilfzw_WAfFp0xnPGnmHJAbAQVy83_MwuiIYQNfCEj0bnnbfJS2LaBngFEBQTXl3hU8ulqcuxwtoDZuIxvMQ3pUBaIqvRjWeGEDW2Hch1vA45ScHYRXMWVYZJBAToAkUgr8f7LFOoa4vXGUCSGxOqNnJejrBWkXfsp3BrfVOmGipwo42BOae71lRUc7HwzXo-Q9YSWcpJK3Y8U60umoRNacQfgkkB8aVGnRP1_YRfbeRYQdpT4PDFrh4Hq83aJKwSuD4vGGNMfXqgIdSWhREajFDN653gDIIrt1BPh-snE9HIr0QWJmGQTlKTFfXMEoHx6mxJgUmzZSdQ9BkfCYyInpevh2piUrdpoAEEBapYyTmEHetutMm6cpPd4EK7-yHf3f1k1Rx-HIkiN-pLPiy6x6sRS-272pRNJUjEyRr7QIxgv2rVmQpFd3HZIsmTA9e5HnEH88pbwzqckWeA8nCpe6vr9uJ5MkIMaZq1Exw2bL8TjezbQdRvFm6eO25ECBE_YRuTm72hWfkn1Aocz5_RrSvW6gjwXpgTB6ScNyDrrmo9Kz8DQA7uvRvwhS48fceGGqEt_02qtj_FY1e8Q-XLVsPz-oafqbrTPI0E\",\"dp\":\"D9PGN8qEoUjBFIDKfuilcKwpU25pLnGsgnlzXxORZYB2T1y_DzHVXoSFkcOcFfn2L-AWFSUQmFlt37ULSoSTi2J5KzeydzXfkz4CauzqyEEyv1Uu_FBM6ZDb14ZkYoS8B_vWx7ow99fopwwObs5LH9vtGmiAJczVTNuwUQd_8uRXsWdoy2Ku8XLmNBaxvpXjzbs3ooKIw450PWB1qk455OrQ0k2dqrbY5VlOjgBEk317yCamGbPy2AgC4EnXnAZ0qJ5gN-mJNbjBCjkS0MImMWphJCrXkKMxl1OURKW_ujb7B5EGXcTmJuFxu8uE6_SxDrhmbCfdrwnfVdQXIGyGsw\",\"dq\":\"xEmqiGWKIuuyMX3wElvw2E_qJfuJ58lyAqQOYrM8ROsk4iaV9yc9G57pHsLRdiCYYrYDoisi96LdJ6kScAcS8j5TAuAdHq2riI0MOd-lZr6I4S_3pnjO3SuHYmCoFagnpIo7QM9-l2ZguDrfCjs7PtQZqMWSg-ncHYrHDsbynhe9GPdes01u4XZ3Y2xoYBDJX2iCXVNKJBUeYwlLd01p4eE1O_UkI8GdxQDMOr0ifOjWa9HtmY13Q8yvWoDtA4UX9Ec83mB3F2RWi4b-0C1pxSifCzeo4VZ0uOZ_aR4ZKfx7npWseE6F-Ue2vPx3qnfZQAkXaqJPsR15ZU0ZtJqAEQ\",\"qi\":\"fzpgNvwBpXBjLkqVkKnGD20kTR1lnMfXKJHk_iGE3UY7FVRSGXiUWpRWo-Gh0Lq8jJVXddX3looqv-v_9uKHja2JkHToWSkJajRznFHvz1pMfs7d3Nr4puumuNxJC1rgktnOIK4eikNxxHJ5Rs6TeQOwWxRbmywMiEeUQAwVvgaaF91g8FmNUE4C2BCpav-1fKkr_ydo1j4AgcSaCcKuywPBvp2Fznf4UcND_1vyZVKhSBbqbu6ql8vb9zEo3E8AKsrn9REji0BnA5kHk1Ps7GiQcMSCdazwBq1kw3DYD5Mt4CuyOdg6Btg-MVDXLLS0Dw0VEvcPhi7ypUlpl0RWcQ\",\"p\":\"uFaIjld13k5EkpQtTJ6zw9Zq5QJwaVBu1RiyXTdji8ysU6rxk07HAsUt049BuKqFv2jdKVDsdL25WkIao93hstdl8Kl_7XQX491_1np1hW-NvapNUYo5UUn-SeT4zseoIu8n-GarEAI00U8Xj2M4pewd82zlCQHTCXZiwbWGF2XMfPqvpYhFtEoMyJUf8z6qCvcZgp-neJJNbLgesspHke8--GwYN-QjrUynkmUGZ14BQdnLsmNLeaWY7A92sLSOFYVK8XnXSzOUld2P5JCgTenS5Na5UpuaY1K8od8rci3TE23Gtma5VhqBiPOFgPXmlkpkBe1uRn84iV5avYQfdw\",\"q\":\"1nHaNzR3mE6cyzPqsqNxT_FDDzMXHCmxW8cO_9GzmFBW6MhNArPEIV9BFAo-NRjDKMYKPin67MlyiLCMN-TWTayeNeuvw_WYwKfI_t9xuyf1nsW-TsNoK4n2d0kwoB5OEH9pAtQKv9rSZl4WULePldJBF4lPBhQb0lmRu-HB_SRskZe8CdDcm-gjwLhoP76gstWN5PNzgrPTpxBC6tHdWD-ZbkzIGWzCjxNHAnJkUAEsy3FVllCtO4pMVXz3zupaVzmDlUQ34weWXqkA-C7QgUPNoCD_M7PTNJKQpnTwlgk1Jvn8v4FDrpmYvv5l8B9swMPtlIi9xADuuEg8gO5i9Q\",\"key_ops\":[\"wrapKey\",\"unwrapKey\",\"encrypt\",\"decrypt\",\"sign\",\"verify\"],\"kid\":\"key_id\"}")
+ .build();
+}
diff --git a/azure-keyvault/pom.xml b/azure-keyvault/pom.xml
new file mode 100755
index 000000000000..66bad0f465a2
--- /dev/null
+++ b/azure-keyvault/pom.xml
@@ -0,0 +1,116 @@
+
+
+ 4.0.0
+
+ com.microsoft.azure
+ azure-keyvault-parent
+ 1.0.0-beta6-SNAPSHOT
+ ../pom.xml
+
+
+ azure-keyvault
+ jar
+
+ Microsoft Azure SDK for Key Vault
+ This package contains Microsoft Azure Key Vault SDK.
+ https://github.com/Azure/azure-sdk-for-java
+
+
+
+ The MIT License (MIT)
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+
+ scm:git:https://github.com/Azure/azure-sdk-for-java
+ scm:git:git@github.com:Azure/azure-sdk-for-java.git
+ HEAD
+
+
+
+ UTF-8
+
+
+
+
+
+ microsoft
+ Microsoft
+
+
+
+
+
+
+ com.microsoft.azure
+ azure-client-runtime
+
+
+ com.microsoft.azure
+ azure-keyvault-webkey
+ 1.0.0-beta6-SNAPSHOT
+
+
+
+
+ junit
+ junit
+ test
+
+
+ com.microsoft.azure
+ azure-client-authentication
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ true
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ 1.7
+ 1.7
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.8
+
+ com.microsoft.schemas._2003._10.serialization;
+ /**
+
* Copyright (c) Microsoft Corporation. All rights reserved.
+
* Licensed under the MIT License. See License.txt in the project root for
+
* license information.
+
*/]]>
+
+
+
+
+
diff --git a/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/CertificateIdentifier.java b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/CertificateIdentifier.java
new file mode 100755
index 000000000000..c78460edcfde
--- /dev/null
+++ b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/CertificateIdentifier.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault;
+
+/**
+ * The certificate identifier.
+ */
+public final class CertificateIdentifier extends ObjectIdentifier {
+
+ /**
+ * Verify whether the identifier is for certificate.
+ * @param identifier the certificate identifier
+ * @return true if the identifier is the certificate identifier. False otherwise.
+ */
+ public static boolean isCertificateIdentifier(String identifier) {
+ return ObjectIdentifier.isObjectIdentifier("certificates", identifier);
+ }
+
+ /**
+ * Constructor.
+ * @param vault The vault url
+ * @param name the certificate name
+ */
+ public CertificateIdentifier(String vault, String name) {
+ this(vault, name, "");
+ }
+
+ /**
+ * Constructor.
+ * @param vault the vault url
+ * @param name the certificate name
+ * @param version the certificate version
+ */
+ public CertificateIdentifier(String vault, String name, String version) {
+ super(vault, "certificates", name, version);
+ }
+
+ /**
+ * Constructor.
+ * @param identifier the certificate identifier
+ */
+ public CertificateIdentifier(String identifier) {
+ super("certificates", identifier);
+ }
+}
diff --git a/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/CertificateOperationIdentifier.java b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/CertificateOperationIdentifier.java
new file mode 100755
index 000000000000..ed88be41ab01
--- /dev/null
+++ b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/CertificateOperationIdentifier.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * The certificate operation identifier.
+ */
+public final class CertificateOperationIdentifier extends ObjectIdentifier {
+
+ /**
+ * Verifies whether the identifier belongs to a key vault certificate operation.
+ * @param identifier the key vault certificate operation identifier.
+ * @return true if the identifier belongs to a key vault certificate operation. False otherwise.
+ */
+ public static boolean isCertificateOperationIdentifier(String identifier) {
+ identifier = verifyNonEmpty(identifier, "identifier");
+
+ URI baseUri;
+ try {
+ baseUri = new URI(identifier);
+ } catch (URISyntaxException e) {
+ return false;
+ }
+
+ // Path is of the form "/certificates/[name]/pending"
+ String[] segments = baseUri.getPath().split("/");
+ if (segments.length != 4) {
+ return false;
+ }
+
+ if (!(segments[1]).equals("certificates")) {
+ return false;
+ }
+
+ if (!(segments[3]).equals("pending")) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Constructor.
+ * @param vault the vault url
+ * @param name the name of certificate
+ * @param version the certificate version
+ */
+ public CertificateOperationIdentifier(String vault, String name, String version) {
+ super(vault, "certificates", name, "pending");
+ }
+
+ /**
+ * Constructor.
+ * @param identifier the key vault certificate operation identifier.
+ */
+ public CertificateOperationIdentifier(String identifier) {
+ super("certificates", identifier);
+ if (!version().equals("pending")) {
+ throw new IllegalArgumentException(
+ String.format("Invalid CertificateOperationIdentifier: {0}", identifier));
+ }
+ }
+}
diff --git a/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/IssuerIdentifier.java b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/IssuerIdentifier.java
new file mode 100755
index 000000000000..6d50e9c6c049
--- /dev/null
+++ b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/IssuerIdentifier.java
@@ -0,0 +1,106 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.InvalidParameterException;
+
+/**
+ * The issuer identifier.
+ */
+public final class IssuerIdentifier extends ObjectIdentifier {
+
+ /**
+ * Verifies whether the identifier belongs to a key vault issuer.
+ * @param identifier the key vault issuer identifier.
+ * @return true if the identifier belongs to a key vault issuer. False otherwise.
+ */
+ public static boolean isIssuerIdentifier(String identifier) {
+ identifier = verifyNonEmpty(identifier, "identifier");
+
+ URI baseUri;
+ try {
+ baseUri = new URI(identifier);
+ } catch (URISyntaxException e) {
+ return false;
+ }
+
+ String[] segments = baseUri.getPath().split("/");
+ if (segments.length != 4 || segments[1] != "certificates" || segments[2] != "issuers") {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Constructor.
+ * @param vault the vault url.
+ * @param name the name of issuer.
+ */
+ public IssuerIdentifier(String vault, String name) {
+ vault = verifyNonEmpty(vault, "vault");
+
+ name = verifyNonEmpty(name, "name");
+
+ URI baseUri;
+ try {
+ baseUri = new URI(vault);
+ } catch (URISyntaxException e) {
+ throw new InvalidParameterException(String.format("Invalid ObjectIdentifier: %s. Not a valid URI", vault));
+ }
+
+ this.name = name;
+ this.version = null;
+ this.vault = String.format("%s://%s", baseUri.getScheme(), getFullAuthority(baseUri));
+
+ baseIdentifier = String.format("%s/%s/%s", this.vault, "certificates/issuers", this.name);
+ identifier = baseIdentifier;
+ }
+
+ /**
+ * Constructor.
+ * @param identifier the key vault issuer identifier.
+ */
+ public IssuerIdentifier(String identifier) {
+
+ identifier = verifyNonEmpty(identifier, "identifier");
+
+ URI baseUri;
+ try {
+ baseUri = new URI(identifier);
+ } catch (URISyntaxException e) {
+ throw new InvalidParameterException(
+ String.format("Invalid ObjectIdentifier: %s. Not a valid URI", identifier));
+ }
+
+ // Path is of the form "/collection/name[/version]"
+ String[] segments = baseUri.getPath().split("/");
+ if (segments.length != 4) {
+ throw new InvalidParameterException(String
+ .format("Invalid ObjectIdentifier: %s. Bad number of segments: %d", identifier, segments.length));
+ }
+
+ if (!segments[1].equals("certificates")) {
+ throw new InvalidParameterException(
+ String.format("Invalid ObjectIdentifier: %s. Segment [1] should be '%s', found '%s'", identifier,
+ "certificates", segments[1]));
+ }
+ if (!segments[2].equals("issuers")) {
+ throw new InvalidParameterException(
+ String.format("Invalid ObjectIdentifier: %s. Segment [2] should be '%s', found '%s'", identifier,
+ "issuers", segments[2]));
+ }
+
+ name = segments[3];
+ version = "";
+ vault = String.format("%s://%s", baseUri.getScheme(), getFullAuthority(baseUri));
+ baseIdentifier = String.format("%s/%s/%s", vault, "certificates/issuers", name);
+ this.identifier = baseIdentifier;
+ }
+}
diff --git a/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyIdentifier.java b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyIdentifier.java
new file mode 100755
index 000000000000..67dcd6f35b83
--- /dev/null
+++ b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyIdentifier.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault;
+
+/**
+ * The Key Vault key identifier.
+ */
+public final class KeyIdentifier extends ObjectIdentifier {
+
+ /**
+ * Verifies whether the identifier belongs to a key vault key.
+ * @param identifier the key vault key identifier.
+ * @return true if the identifier belongs to a key vault key. False otherwise.
+ */
+ public static boolean isKeyIdentifier(String identifier) {
+ return ObjectIdentifier.isObjectIdentifier("keys", identifier);
+ }
+
+ /**
+ * Constructor.
+ * @param vault the vault url.
+ * @param name the name of key.
+ */
+ public KeyIdentifier(String vault, String name) {
+ this(vault, name, "");
+ }
+
+ /**
+ * Constructor.
+ * @param vault the vault url.
+ * @param name the name of key.
+ * @param version the key version.
+ */
+ public KeyIdentifier(String vault, String name, String version) {
+ super(vault, "keys", name, version);
+ }
+
+ /**
+ * Constructor.
+ * @param identifier the key vault key identifier.
+ */
+ public KeyIdentifier(String identifier) {
+ super("keys", identifier);
+ }
+}
diff --git a/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyVaultClient.java b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyVaultClient.java
new file mode 100755
index 000000000000..0d6f8c287997
--- /dev/null
+++ b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyVaultClient.java
@@ -0,0 +1,1753 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.keyvault;
+
+import java.util.List;
+
+import com.google.common.base.Joiner;
+import com.microsoft.azure.AzureClient;
+import com.microsoft.azure.ListOperationCallback;
+import com.microsoft.azure.PagedList;
+import com.microsoft.azure.keyvault.models.BackupKeyResult;
+import com.microsoft.azure.keyvault.models.CertificateBundle;
+import com.microsoft.azure.keyvault.models.CertificateIssuerItem;
+import com.microsoft.azure.keyvault.models.CertificateItem;
+import com.microsoft.azure.keyvault.models.CertificateOperation;
+import com.microsoft.azure.keyvault.models.CertificatePolicy;
+import com.microsoft.azure.keyvault.models.Contacts;
+import com.microsoft.azure.keyvault.models.IssuerBundle;
+import com.microsoft.azure.keyvault.models.KeyBundle;
+import com.microsoft.azure.keyvault.models.KeyItem;
+import com.microsoft.azure.keyvault.models.KeyOperationResult;
+import com.microsoft.azure.keyvault.models.KeyVerifyResult;
+import com.microsoft.azure.keyvault.models.SecretBundle;
+import com.microsoft.azure.keyvault.models.SecretItem;
+import com.microsoft.azure.keyvault.requests.CreateCertificateRequest;
+import com.microsoft.azure.keyvault.requests.CreateKeyRequest;
+import com.microsoft.azure.keyvault.requests.ImportCertificateRequest;
+import com.microsoft.azure.keyvault.requests.ImportKeyRequest;
+import com.microsoft.azure.keyvault.requests.MergeCertificateRequest;
+import com.microsoft.azure.keyvault.requests.SetCertificateIssuerRequest;
+import com.microsoft.azure.keyvault.requests.SetSecretRequest;
+import com.microsoft.azure.keyvault.requests.UpdateCertificateIssuerRequest;
+import com.microsoft.azure.keyvault.requests.UpdateCertificateOperationRequest;
+import com.microsoft.azure.keyvault.requests.UpdateCertificatePolicyRequest;
+import com.microsoft.azure.keyvault.requests.UpdateCertificateRequest;
+import com.microsoft.azure.keyvault.requests.UpdateKeyRequest;
+import com.microsoft.azure.keyvault.requests.UpdateSecretRequest;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyEncryptionAlgorithm;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeySignatureAlgorithm;
+import com.microsoft.rest.RestClient;
+import com.microsoft.rest.ServiceFuture;
+import com.microsoft.rest.ServiceCallback;
+import com.microsoft.rest.ServiceResponse;
+import com.microsoft.rest.credentials.ServiceClientCredentials;
+import com.microsoft.rest.protocol.SerializerAdapter;
+
+import okhttp3.OkHttpClient;
+import okhttp3.ResponseBody;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.http.GET;
+import retrofit2.http.Header;
+import retrofit2.http.Headers;
+import retrofit2.http.Path;
+import retrofit2.http.Query;
+import rx.Observable;
+import rx.functions.Func1;
+
+/**
+ * Initializes a new instance of the KeyVaultClient class.
+ */
+public final class KeyVaultClient {
+
+ private KeyVaultClientImpl innerKeyVaultClient;
+
+ /** The Retrofit service to perform REST calls. */
+ private KeyVaultClientService service;
+
+ /**
+ * Gets the {@link AzureClient} used for long running operations.
+ *
+ * @return the azure client;
+ */
+ public AzureClient getAzureClient() {
+ return innerKeyVaultClient.getAzureClient();
+ }
+
+ /**
+ * Gets Client Api Version.
+ *
+ * @return the apiVersion value.
+ */
+ public String apiVersion() {
+ return innerKeyVaultClient.apiVersion();
+ }
+
+ /**
+ * Gets Gets or sets the preferred language for the response.
+ *
+ * @return the acceptLanguage value.
+ */
+ public String acceptLanguage() {
+ return innerKeyVaultClient.acceptLanguage();
+ }
+
+ /**
+ * Sets Gets or sets the preferred language for the response.
+ *
+ * @param acceptLanguage the acceptLanguage value.
+ */
+ public void withAcceptLanguage(String acceptLanguage) {
+ innerKeyVaultClient.withAcceptLanguage(acceptLanguage);
+ }
+
+ /**
+ * Gets Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30.
+ *
+ * @return the longRunningOperationRetryTimeout value.
+ */
+ public int longRunningOperationRetryTimeout() {
+ return innerKeyVaultClient.longRunningOperationRetryTimeout();
+ }
+
+ /**
+ * Sets Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30.
+ *
+ * @param longRunningOperationRetryTimeout the longRunningOperationRetryTimeout value.
+ */
+ public void withLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout) {
+ innerKeyVaultClient.withLongRunningOperationRetryTimeout(longRunningOperationRetryTimeout);
+ }
+
+ /**
+ * Gets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.
+ *
+ * @return the generateClientRequestId value.
+ */
+ public boolean generateClientRequestId() {
+ return innerKeyVaultClient.generateClientRequestId();
+ }
+
+ /**
+ * Sets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.
+ *
+ * @param generateClientRequestId the generateClientRequestId value.
+ */
+ public void withGenerateClientRequestId(boolean generateClientRequestId) {
+ innerKeyVaultClient.withGenerateClientRequestId(generateClientRequestId);
+ }
+
+ /**
+ * @return the {@link RestClient} instance.
+ */
+ public RestClient restClient() {
+ return innerKeyVaultClient.restClient();
+ }
+
+ /**
+ * @return the Retrofit instance.
+ */
+ public Retrofit retrofit() {
+ return innerKeyVaultClient.retrofit();
+ }
+
+ /**
+ * @return the HTTP client.
+ */
+ public OkHttpClient httpClient() {
+ return innerKeyVaultClient.httpClient();
+ }
+
+ /**
+ * @return the adapter to a Jackson {@link com.fasterxml.jackson.databind.ObjectMapper}.
+ */
+ public SerializerAdapter> serializerAdapter() {
+ return innerKeyVaultClient.serializerAdapter();
+ }
+
+ /**
+ * Initializes an instance of KeyVaultClient client.
+ *
+ * @param credentials the management credentials for Azure
+ */
+ public KeyVaultClient(ServiceClientCredentials credentials) {
+ innerKeyVaultClient = new KeyVaultClientImpl(credentials);
+ initializeService();
+ }
+
+ /**
+ * Initializes an instance of KeyVaultClient client.
+ *
+ * @param restClient the REST client to connect to Azure.
+ */
+ public KeyVaultClient(RestClient restClient) {
+ innerKeyVaultClient = new KeyVaultClientImpl(restClient);
+ initializeService();
+ }
+
+ /**
+ * Gets the User-Agent header for the client.
+ *
+ * @return the user agent string.
+ */
+ public String userAgent() {
+ return innerKeyVaultClient.userAgent();
+ }
+
+ private void initializeService() {
+ service = innerKeyVaultClient.restClient().retrofit().create(KeyVaultClientService.class);
+ }
+
+ /**
+ * The interface defining all the services for KeyVaultClient to be
+ * used by Retrofit to perform actually REST calls.
+ */
+ interface KeyVaultClientService {
+ @Headers({ "Content-Type: application/json; charset=utf-8", "Accept: application/pkcs10", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getPendingCertificateSigningRequest" })
+ @GET("certificates/{certificate-name}/pending")
+ Observable> getPendingCertificateSigningRequest(@Path("certificate-name") String certificateName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+ }
+
+ /**
+ * Creates a new key, stores it, then returns key parameters and attributes to the client. The create key operation can be used to create any key type in Azure Key Vault. If the named key already exists, Azure Key Vault creates a new version of the key. Authorization: Requires the keys/create permission.
+ *
+ * @param createKeyRequest the grouped properties for creating a key request
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle createKey(CreateKeyRequest createKeyRequest) {
+ return innerKeyVaultClient.createKey(
+ createKeyRequest.vaultBaseUrl(),
+ createKeyRequest.keyName(),
+ createKeyRequest.keyType(),
+ createKeyRequest.keySize(),
+ createKeyRequest.keyOperations(),
+ createKeyRequest.keyAttributes(),
+ createKeyRequest.tags());
+ }
+
+ /**
+ * Creates a new key, stores it, then returns key parameters and attributes to the client. The create key operation can be used to create any key type in Azure Key Vault. If the named key already exists, Azure Key Vault creates a new version of the key. Authorization: Requires the keys/create permission.
+ *
+ * @param createKeyRequest the grouped properties for creating a key request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture createKeyAsync(CreateKeyRequest createKeyRequest, ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.createKeyAsync(
+ createKeyRequest.vaultBaseUrl(),
+ createKeyRequest.keyName(),
+ createKeyRequest.keyType(),
+ createKeyRequest.keySize(),
+ createKeyRequest.keyOperations(),
+ createKeyRequest.keyAttributes(),
+ createKeyRequest.tags(),
+ serviceCallback);
+ }
+
+ /**
+ * Imports an externally created key, stores it, and returns key parameters and attributes to the client. The import key operation may be used to import any key type into an Azure Key Vault. If the named key already exists, Azure Key Vault creates a new version of the key. Authorization: requires the keys/import permission.
+ *
+ * @param importKeyRequest the grouped properties for importing a key request
+ *
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle importKey(ImportKeyRequest importKeyRequest) {
+ return innerKeyVaultClient.importKey(
+ importKeyRequest.vaultBaseUrl(),
+ importKeyRequest.keyName(),
+ importKeyRequest.key(),
+ importKeyRequest.isHsm(),
+ importKeyRequest.keyAttributes(),
+ importKeyRequest.tags());
+ }
+
+ /**
+ * Imports an externally created key, stores it, and returns key parameters and attributes to the client. The import key operation may be used to import any key type into an Azure Key Vault. If the named key already exists, Azure Key Vault creates a new version of the key. Authorization: requires the keys/import permission.
+ *
+ * @param importKeyRequest the grouped properties for importing a key request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture importKeyAsync(ImportKeyRequest importKeyRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.importKeyAsync(
+ importKeyRequest.vaultBaseUrl(),
+ importKeyRequest.keyName(),
+ importKeyRequest.key(),
+ importKeyRequest.isHsm(),
+ importKeyRequest.keyAttributes(),
+ importKeyRequest.tags(),
+ serviceCallback);
+ }
+
+ /**
+ * Deletes a key of any type from storage in Azure Key Vault. The delete key operation cannot be used to remove individual versions of a key. This operation removes the cryptographic material associated with the key, which means the key is not usable for Sign/Verify, Wrap/Unwrap or Encrypt/Decrypt operations. Authorization: Requires the keys/delete permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle deleteKey(String vaultBaseUrl, String keyName) {
+ return innerKeyVaultClient.deleteKey(vaultBaseUrl, keyName);
+ }
+
+ /**
+ * Deletes a key of any type from storage in Azure Key Vault. The delete key operation cannot be used to remove individual versions of a key. This operation removes the cryptographic material associated with the key, which means the key is not usable for Sign/Verify, Wrap/Unwrap or Encrypt/Decrypt operations. Authorization: Requires the keys/delete permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture deleteKeyAsync(String vaultBaseUrl, String keyName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.deleteKeyAsync(vaultBaseUrl, keyName, serviceCallback);
+ }
+
+ /**
+ * The update key operation changes specified attributes of a stored key and can be applied to any key type and key version stored in Azure Key Vault. The cryptographic material of a key itself cannot be changed. In order to perform this operation, the key must already exist in the Key Vault. Authorization: requires the keys/update permission.
+ *
+ * @param updateKeyRequest the grouped properties for updating a key request
+ *
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle updateKey(UpdateKeyRequest updateKeyRequest) {
+ return innerKeyVaultClient.updateKey(
+ updateKeyRequest.vaultBaseUrl(),
+ updateKeyRequest.keyName(),
+ updateKeyRequest.keyVersion(),
+ updateKeyRequest.keyOperations(),
+ updateKeyRequest.keyAttributes(),
+ updateKeyRequest.tags());
+ }
+
+ /**
+ * The update key operation changes specified attributes of a stored key and can be applied to any key type and key version stored in Azure Key Vault. The cryptographic material of a key itself cannot be changed. In order to perform this operation, the key must already exist in the Key Vault. Authorization: requires the keys/update permission.
+ *
+ * @param updateKeyRequest the grouped properties for updating a key request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture updateKeyAsync(UpdateKeyRequest updateKeyRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.updateKeyAsync(
+ updateKeyRequest.vaultBaseUrl(),
+ updateKeyRequest.keyName(),
+ updateKeyRequest.keyVersion(),
+ updateKeyRequest.keyOperations(),
+ updateKeyRequest.keyAttributes(),
+ updateKeyRequest.tags(),
+ serviceCallback);
+ }
+
+ /**
+ * Gets the public part of a stored key. The get key operation is applicable to all key types. If the requested key is symmetric, then no key material is released in the response. Authorization: Requires the keys/get permission.
+ *
+ * @param keyIdentifier The full key identifier
+ *
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle getKey(String keyIdentifier) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.getKey(id.vault, id.name, id.version == null ? "" : id.version);
+ }
+
+ /**
+ * Gets the public part of a stored key. The get key operation is applicable to all key types. If the requested key is symmetric, then no key material is released in the response. Authorization: Requires the keys/get permission.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getKeyAsync(String keyIdentifier, final ServiceCallback serviceCallback) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.getKeyAsync(id.vault, id.name, id.version == null ? "" : id.version, serviceCallback);
+ }
+
+ /**
+ * Gets the public part of a stored key. The get key operation is applicable to all key types. If the requested key is symmetric, then no key material is released in the response. Authorization: Requires the keys/get permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle getKey(String vaultBaseUrl, String keyName) {
+ return innerKeyVaultClient.getKey(vaultBaseUrl, keyName, "");
+ }
+
+ /**
+ * Gets the public part of a stored key. The get key operation is applicable to all key types. If the requested key is symmetric, then no key material is released in the response. Authorization: Requires the keys/get permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getKeyAsync(String vaultBaseUrl, String keyName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getKeyAsync(vaultBaseUrl, keyName, "", serviceCallback);
+ }
+
+ /**
+ *Gets the public part of a stored key. The get key operation is applicable to all key types. If the requested key is symmetric, then no key material is released in the response. Authorization: Requires the keys/get permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param keyVersion The version of the key
+ *
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle getKey(String vaultBaseUrl, String keyName, String keyVersion) {
+ return innerKeyVaultClient.getKey(vaultBaseUrl, keyName, keyVersion);
+ }
+
+ /**
+ * Gets the public part of a stored key. The get key operation is applicable to all key types. If the requested key is symmetric, then no key material is released in the response. Authorization: Requires the keys/get permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param keyVersion The version of the key
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getKeyAsync(String vaultBaseUrl, String keyName, String keyVersion, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getKeyAsync(vaultBaseUrl, keyName, keyVersion, serviceCallback);
+ }
+
+ /**
+ * Retrieves a list of individual key versions with the same key name. The full key identifier, attributes, and tags are provided in the response. Authorization: Requires the keys/list permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ *
+ * @return the PagedList<KeyItem> if successful.
+ */
+ public PagedList listKeyVersions(final String vaultBaseUrl, final String keyName) {
+ return innerKeyVaultClient.getKeyVersions(vaultBaseUrl, keyName);
+ }
+
+ /**
+ * Retrieves a list of individual key versions with the same key name. The full key identifier, attributes, and tags are provided in the response. Authorization: Requires the keys/list permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listKeyVersionsAsync(final String vaultBaseUrl, final String keyName, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getKeyVersionsAsync(vaultBaseUrl, keyName, serviceCallback);
+ }
+ /**
+ * Retrieves a list of individual key versions with the same key name. The full key identifier, attributes, and tags are provided in the response. Authorization: Requires the keys/list permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ *
+ * @return the PagedList<KeyItem> if successful.
+ */
+ public PagedList listKeyVersions(final String vaultBaseUrl, final String keyName, final Integer maxresults) {
+ return innerKeyVaultClient.getKeyVersions(vaultBaseUrl, keyName, maxresults);
+ }
+
+ /**
+ * Retrieves a list of individual key versions with the same key name. The full key identifier, attributes, and tags are provided in the response. Authorization: Requires the keys/list permission.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listKeyVersionsAsync(final String vaultBaseUrl, final String keyName, final Integer maxresults, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getKeyVersionsAsync(vaultBaseUrl, keyName, maxresults, serviceCallback);
+ }
+
+ /**
+ * List keys in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ *
+ * @return the PagedList<KeyItem> if successful.
+ */
+ public PagedList listKeys(final String vaultBaseUrl) {
+ return innerKeyVaultClient.getKeys(vaultBaseUrl);
+ }
+
+ /**
+ * List keys in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listKeysAsync(final String vaultBaseUrl, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getKeysAsync(vaultBaseUrl, serviceCallback);
+ }
+ /**
+ * List keys in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ *
+ * @return the PagedList<KeyItem> if successful.
+ */
+ public PagedList listKeys(final String vaultBaseUrl, final Integer maxresults) {
+ return innerKeyVaultClient.getKeys(vaultBaseUrl, maxresults);
+ }
+
+ /**
+ * List keys in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listKeysAsync(final String vaultBaseUrl, final Integer maxresults, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getKeysAsync(vaultBaseUrl, maxresults, serviceCallback);
+ }
+
+ /**
+ * Requests that a backup of the specified key be downloaded to the client.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ *
+ * @return the BackupKeyResult if successful.
+ */
+ public BackupKeyResult backupKey(String vaultBaseUrl, String keyName) {
+ return innerKeyVaultClient.backupKey(vaultBaseUrl, keyName);
+ }
+
+ /**
+ * Requests that a backup of the specified key be downloaded to the client.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyName The name of the key
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture backupKeyAsync(String vaultBaseUrl, String keyName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.backupKeyAsync(vaultBaseUrl, keyName, serviceCallback);
+ }
+
+ /**
+ * Restores the backup key in to a vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyBundleBackup the backup blob associated with a key bundle
+ *
+ * @return the KeyBundle if successful.
+ */
+ public KeyBundle restoreKey(String vaultBaseUrl, byte[] keyBundleBackup) {
+ return innerKeyVaultClient.restoreKey(vaultBaseUrl, keyBundleBackup);
+ }
+
+ /**
+ * Restores the backup key in to a vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param keyBundleBackup the backup blob associated with a key bundle
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture restoreKeyAsync(String vaultBaseUrl, byte[] keyBundleBackup, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.restoreKeyAsync(vaultBaseUrl, keyBundleBackup, serviceCallback);
+ }
+
+ /**
+ * Encrypts an arbitrary sequence of bytes using an encryption key that is stored in a key vault.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the content to be encrypted
+ *
+ * @return the KeyOperationResult if successful.
+ */
+ public KeyOperationResult encrypt(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.encrypt(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value);
+ }
+
+ /**
+ * Encrypts an arbitrary sequence of bytes using an encryption key that is stored in a key vault.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the content to be encrypted
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture encryptAsync(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value, final ServiceCallback serviceCallback) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.encryptAsync(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value, serviceCallback);
+ }
+
+ /**
+ * Decrypts a single block of encrypted data.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the content to be decrypted
+ *
+ * @return the KeyOperationResult if successful.
+ */
+ public KeyOperationResult decrypt(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.decrypt(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value);
+ }
+
+ /**
+ * Decrypts a single block of encrypted data.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the content to be decrypted
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture decryptAsync(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value, final ServiceCallback serviceCallback) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.decryptAsync(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value, serviceCallback);
+ }
+
+ /**
+ * Creates a signature from a digest using the specified key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the content to be signed
+ *
+ * @return the KeyOperationResult if successful.
+ */
+ public KeyOperationResult sign(String keyIdentifier, JsonWebKeySignatureAlgorithm algorithm, byte[] value) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.sign(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value);
+ }
+
+ /**
+ * Creates a signature from a digest using the specified key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the content to be signed
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture signAsync(String keyIdentifier, JsonWebKeySignatureAlgorithm algorithm, byte[] value, final ServiceCallback serviceCallback) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.signAsync(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value, serviceCallback);
+ }
+
+ /**
+ * Verifies a signature using the specified key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm The signing/verification algorithm. For more information on possible algorithm types, see JsonWebKeySignatureAlgorithm.
+ * @param digest The digest used for signing
+ * @param signature The signature to be verified
+ *
+ * @return the KeyVerifyResult if successful.
+ */
+ public KeyVerifyResult verify(String keyIdentifier, JsonWebKeySignatureAlgorithm algorithm, byte[] digest, byte[] signature) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.verify(id.vault, id.name, id.version == null ? "" : id.version, algorithm, digest, signature);
+ }
+
+ /**
+ * Verifies a signature using the specified key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm The signing/verification algorithm. For more information on possible algorithm types, see JsonWebKeySignatureAlgorithm.
+ * @param digest The digest used for signing
+ * @param signature The signature to be verified
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture verifyAsync(String keyIdentifier, JsonWebKeySignatureAlgorithm algorithm, byte[] digest, byte[] signature, final ServiceCallback serviceCallback) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.verifyAsync(id.vault, id.name, id.version == null ? "" : id.version, algorithm, digest, signature, serviceCallback);
+ }
+
+ /**
+ * Wraps a symmetric key using the specified key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the key to be wrapped
+ *
+ * @return the KeyOperationResult if successful.
+ */
+ public KeyOperationResult wrapKey(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.wrapKey(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value);
+ }
+
+ /**
+ * Wraps a symmetric key using the specified key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the key to be wrapped
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture wrapKeyAsync(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value, final ServiceCallback serviceCallback) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.wrapKeyAsync(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value, serviceCallback);
+ }
+
+ /**
+ * Unwraps a symmetric key using the specified key in the vault that has initially been used for wrapping the key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the key to be unwrapped
+ *
+ * @return the KeyOperationResult if successful.
+ */
+ public KeyOperationResult unwrapKey(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.unwrapKey(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value);
+ }
+
+ /**
+ * Unwraps a symmetric key using the specified key in the vault that has initially been used for wrapping the key.
+ *
+ * @param keyIdentifier The full key identifier
+ * @param algorithm algorithm identifier
+ * @param value the key to be unwrapped
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture unwrapKeyAsync(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value, final ServiceCallback serviceCallback) {
+ KeyIdentifier id = new KeyIdentifier(keyIdentifier);
+ return innerKeyVaultClient.unwrapKeyAsync(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value, serviceCallback);
+ }
+
+ /**
+ * Sets a secret in the specified vault.
+ *
+ * @param setSecretRequest the grouped properties for setting a secret request
+ *
+ * @return the SecretBundle if successful.
+ */
+ public SecretBundle setSecret(SetSecretRequest setSecretRequest) {
+ return innerKeyVaultClient.setSecret(
+ setSecretRequest.vaultBaseUrl(),
+ setSecretRequest.secretName(),
+ setSecretRequest.value(),
+ setSecretRequest.tags(),
+ setSecretRequest.contentType(),
+ setSecretRequest.secretAttributes());
+ }
+
+ /**
+ * Sets a secret in the specified vault.
+ *
+ * @param setSecretRequest the grouped properties for setting a secret request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture setSecretAsync(SetSecretRequest setSecretRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.setSecretAsync(
+ setSecretRequest.vaultBaseUrl(),
+ setSecretRequest.secretName(),
+ setSecretRequest.value(),
+ setSecretRequest.tags(),
+ setSecretRequest.contentType(),
+ setSecretRequest.secretAttributes(),
+ serviceCallback);
+ }
+
+ /**
+ * Deletes a secret from the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ *
+ * @return the SecretBundle if successful.
+ */
+ public SecretBundle deleteSecret(String vaultBaseUrl, String secretName) {
+ return innerKeyVaultClient.deleteSecret(vaultBaseUrl, secretName);
+ }
+
+ /**
+ * Deletes a secret from the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture deleteSecretAsync(String vaultBaseUrl, String secretName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.deleteSecretAsync(vaultBaseUrl, secretName, serviceCallback);
+ }
+
+ /**
+ * Updates the attributes associated with a specified secret in a given key vault.
+ *
+ * @param updateSecretRequest the grouped properties for updating a secret request
+ *
+ * @return the SecretBundle if successful.
+ */
+ public SecretBundle updateSecret(UpdateSecretRequest updateSecretRequest) {
+ return innerKeyVaultClient.updateSecret(
+ updateSecretRequest.vaultBaseUrl(),
+ updateSecretRequest.secretName(),
+ updateSecretRequest.secretVersion(),
+ updateSecretRequest.contentType(),
+ updateSecretRequest.secretAttributes(),
+ updateSecretRequest.tags());
+ }
+
+ /**
+ * Updates the attributes associated with a specified secret in a given key vault.
+ *
+ * @param updateSecretRequest the grouped properties for updating a secret request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture updateSecretAsync(UpdateSecretRequest updateSecretRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.updateSecretAsync(
+ updateSecretRequest.vaultBaseUrl(),
+ updateSecretRequest.secretName(),
+ updateSecretRequest.secretVersion(),
+ updateSecretRequest.contentType(),
+ updateSecretRequest.secretAttributes(),
+ updateSecretRequest.tags(),
+ serviceCallback);
+ }
+
+ /**
+ * Get a specified secret from a given key vault.
+ *
+ * @param secretIdentifier The URL for the secret.
+ *
+ * @return the SecretBundle if successful.
+ */
+ public SecretBundle getSecret(String secretIdentifier) {
+ SecretIdentifier id = new SecretIdentifier(secretIdentifier);
+ return innerKeyVaultClient.getSecret(id.vault, id.name, id.version == null ? "" : id.version);
+ }
+
+ /**
+ * Get a specified secret from a given key vault.
+ *
+ * @param secretIdentifier The URL for the secret.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getSecretAsync(String secretIdentifier, final ServiceCallback serviceCallback) {
+ SecretIdentifier id = new SecretIdentifier(secretIdentifier);
+ return innerKeyVaultClient.getSecretAsync(id.vault, id.name, id.version == null ? "" : id.version, serviceCallback);
+ }
+
+ /**
+ * Get a specified secret from a given key vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ *
+ * @return the SecretBundle if successful.
+ */
+ public SecretBundle getSecret(String vaultBaseUrl, String secretName) {
+ return innerKeyVaultClient.getSecret(vaultBaseUrl, secretName, "");
+ }
+
+ /**
+ * Get a specified secret from a given key vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getSecretAsync(String vaultBaseUrl, String secretName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getSecretAsync(vaultBaseUrl, secretName, "", serviceCallback);
+ }
+
+ /**
+ * Get a specified secret from a given key vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ * @param secretVersion The version of the secret
+ *
+ * @return the SecretBundle if successful.
+ */
+ public SecretBundle getSecret(String vaultBaseUrl, String secretName, String secretVersion) {
+ return innerKeyVaultClient.getSecret(vaultBaseUrl, secretName, secretVersion == null ? "" : secretVersion);
+ }
+
+ /**
+ * Get a specified secret from a given key vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ * @param secretVersion The version of the secret
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getSecretAsync(String vaultBaseUrl, String secretName, String secretVersion, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getSecretAsync(vaultBaseUrl, secretName, secretVersion == null ? "" : secretVersion, serviceCallback);
+ }
+
+ /**
+ * List secrets in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ *
+ * @return the PagedList<SecretItem> if successful.
+ */
+ public PagedList listSecrets(final String vaultBaseUrl) {
+ return innerKeyVaultClient.getSecrets(vaultBaseUrl);
+ }
+
+ /**
+ * List secrets in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listSecretsAsync(final String vaultBaseUrl, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getSecretsAsync(vaultBaseUrl, serviceCallback);
+ }
+ /**
+ * List secrets in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ *
+ * @return the PagedList<SecretItem> if successful.
+ */
+ public PagedList listSecrets(final String vaultBaseUrl, final Integer maxresults) {
+ return innerKeyVaultClient.getSecrets(vaultBaseUrl, maxresults);
+ }
+
+ /**
+ * List secrets in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listSecretsAsync(final String vaultBaseUrl, final Integer maxresults, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getSecretsAsync(vaultBaseUrl, maxresults, serviceCallback);
+ }
+
+ /**
+ * List the versions of the specified secret.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ *
+ * @return the PagedList<SecretItem> if successful.
+ */
+ public PagedList listSecretVersions(final String vaultBaseUrl, final String secretName) {
+ return innerKeyVaultClient.getSecretVersions(vaultBaseUrl, secretName);
+ }
+
+ /**
+ * List the versions of the specified secret.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listSecretVersionsAsync(final String vaultBaseUrl, final String secretName, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getSecretVersionsAsync(vaultBaseUrl, secretName, serviceCallback);
+ }
+ /**
+ * List the versions of the specified secret.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ *
+ * @return the PagedList<SecretItem> if successful.
+ */
+ public PagedList listSecretVersions(final String vaultBaseUrl, final String secretName, final Integer maxresults) {
+ return innerKeyVaultClient.getSecretVersions(vaultBaseUrl, secretName, maxresults);
+ }
+
+ /**
+ * List the versions of the specified secret.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param secretName The name of the secret in the given vault
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listSecretVersionsAsync(final String vaultBaseUrl, final String secretName, final Integer maxresults, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getSecretVersionsAsync(vaultBaseUrl, secretName, maxresults, serviceCallback);
+ }
+
+ /**
+ * List certificates in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ *
+ * @return the PagedList<CertificateItem> if successful.
+ */
+ public PagedList listCertificates(final String vaultBaseUrl) {
+ return innerKeyVaultClient.getCertificates(vaultBaseUrl);
+ }
+
+ /**
+ * List certificates in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listCertificatesAsync(final String vaultBaseUrl, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificatesAsync(vaultBaseUrl, serviceCallback);
+ }
+ /**
+ * List certificates in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ *
+ * @return the PagedList<CertificateItem> if successful.
+ */
+ public PagedList listCertificates(final String vaultBaseUrl, final Integer maxresults) {
+ return innerKeyVaultClient.getCertificates(vaultBaseUrl, maxresults);
+ }
+
+ /**
+ * List certificates in the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listCertificatesAsync(final String vaultBaseUrl, final Integer maxresults, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificatesAsync(vaultBaseUrl, maxresults, serviceCallback);
+ }
+
+ /**
+ * Deletes a certificate from the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault
+ *
+ * @return the CertificateBundle if successful.
+ */
+ public CertificateBundle deleteCertificate(String vaultBaseUrl, String certificateName) {
+ return innerKeyVaultClient.deleteCertificate(vaultBaseUrl, certificateName);
+ }
+
+ /**
+ * Deletes a certificate from the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture deleteCertificateAsync(String vaultBaseUrl, String certificateName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.deleteCertificateAsync(vaultBaseUrl, certificateName, serviceCallback);
+ }
+
+ /**
+ * Sets the certificate contacts for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param contacts The contacts for the vault certificates.
+ *
+ * @return the Contacts if successful.
+ */
+ public Contacts setCertificateContacts(String vaultBaseUrl, Contacts contacts) {
+ return innerKeyVaultClient.setCertificateContacts(vaultBaseUrl, contacts);
+ }
+
+ /**
+ * Sets the certificate contacts for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param contacts The contacts for the vault certificates.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture setCertificateContactsAsync(String vaultBaseUrl, Contacts contacts, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.setCertificateContactsAsync(vaultBaseUrl, contacts, serviceCallback);
+ }
+
+ /**
+ * Gets the certificate contacts for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ *
+ * @return the Contacts if successful.
+ */
+ public Contacts getCertificateContacts(String vaultBaseUrl) {
+ return innerKeyVaultClient.getCertificateContacts(vaultBaseUrl);
+ }
+
+ /**
+ * Gets the certificate contacts for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getCertificateContactsAsync(String vaultBaseUrl, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateContactsAsync(vaultBaseUrl, serviceCallback);
+ }
+
+ /**
+ * Deletes the certificate contacts for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ *
+ * @return the Contacts if successful.
+ */
+ public Contacts deleteCertificateContacts(String vaultBaseUrl) {
+ return innerKeyVaultClient.deleteCertificateContacts(vaultBaseUrl);
+ }
+
+ /**
+ * Deletes the certificate contacts for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture deleteCertificateContactsAsync(String vaultBaseUrl, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.deleteCertificateContactsAsync(vaultBaseUrl, serviceCallback);
+ }
+
+ /**
+ * List certificate issuers for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ *
+ * @return the PagedList<CertificateIssuerItem> if successful.
+ */
+ public PagedList listCertificateIssuers(final String vaultBaseUrl) {
+ return innerKeyVaultClient.getCertificateIssuers(vaultBaseUrl);
+ }
+
+ /**
+ * List certificate issuers for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listCertificateIssuersAsync(final String vaultBaseUrl, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateIssuersAsync(vaultBaseUrl, serviceCallback);
+ }
+ /**
+ * List certificate issuers for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ *
+ * @return the PagedList<CertificateIssuerItem> if successful.
+ */
+ public PagedList listCertificateIssuers(final String vaultBaseUrl, final Integer maxresults) {
+ return innerKeyVaultClient.getCertificateIssuers(vaultBaseUrl, maxresults);
+ }
+
+ /**
+ * List certificate issuers for the specified vault.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listCertificateIssuersAsync(final String vaultBaseUrl, final Integer maxresults, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateIssuersAsync(vaultBaseUrl, maxresults, serviceCallback);
+ }
+
+ /**
+ * Sets the certificate contacts for the specified vault.
+ *
+ * @param setCertificateIssuerRequest the grouped properties for setting a certificate issuer request
+ *
+ * @return the IssuerBundle if successful.
+ */
+ public IssuerBundle setCertificateIssuer(SetCertificateIssuerRequest setCertificateIssuerRequest) {
+ return innerKeyVaultClient.setCertificateIssuer(
+ setCertificateIssuerRequest.vaultBaseUrl(),
+ setCertificateIssuerRequest.issuerName(),
+ setCertificateIssuerRequest.provider(),
+ setCertificateIssuerRequest.credentials(),
+ setCertificateIssuerRequest.organizationDetails(),
+ setCertificateIssuerRequest.attributes());
+ }
+
+ /**
+ * Sets the certificate contacts for the specified vault.
+ *
+ * @param setCertificateIssuerRequest the grouped properties for setting a certificate issuer request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture setCertificateIssuerAsync(SetCertificateIssuerRequest setCertificateIssuerRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.setCertificateIssuerAsync(
+ setCertificateIssuerRequest.vaultBaseUrl(),
+ setCertificateIssuerRequest.issuerName(),
+ setCertificateIssuerRequest.provider(),
+ setCertificateIssuerRequest.credentials(),
+ setCertificateIssuerRequest.organizationDetails(),
+ setCertificateIssuerRequest.attributes(),
+ serviceCallback);
+ }
+
+ /**
+ * Updates the specified certificate issuer.
+ *
+ * @param updateCertificateIssuerRequest the grouped properties for updating a certificate issuer request
+ *
+ * @return the IssuerBundle if successful.
+ */
+ public IssuerBundle updateCertificateIssuer(UpdateCertificateIssuerRequest updateCertificateIssuerRequest) {
+ return innerKeyVaultClient.updateCertificateIssuer(
+ updateCertificateIssuerRequest.vaultBaseUrl(),
+ updateCertificateIssuerRequest.issuerName(),
+ updateCertificateIssuerRequest.provider(),
+ updateCertificateIssuerRequest.credentials(),
+ updateCertificateIssuerRequest.organizationDetails(),
+ updateCertificateIssuerRequest.attributes());
+ }
+
+ /**
+ * Updates the specified certificate issuer.
+ *
+ * @param updateCertificateIssuerRequest the grouped properties for updating a certificate issuer request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @throws IllegalArgumentException thrown if callback is null
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture updateCertificateIssuerAsync(UpdateCertificateIssuerRequest updateCertificateIssuerRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.updateCertificateIssuerAsync(
+ updateCertificateIssuerRequest.vaultBaseUrl(),
+ updateCertificateIssuerRequest.issuerName(),
+ updateCertificateIssuerRequest.provider(),
+ updateCertificateIssuerRequest.credentials(),
+ updateCertificateIssuerRequest.organizationDetails(),
+ updateCertificateIssuerRequest.attributes(),
+ serviceCallback);
+ }
+
+ /**
+ * Gets the specified certificate issuer.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param issuerName The name of the issuer.
+ *
+ * @return the IssuerBundle if successful.
+ */
+ public IssuerBundle getCertificateIssuer(String vaultBaseUrl, String issuerName) {
+ return innerKeyVaultClient.getCertificateIssuer(vaultBaseUrl, issuerName);
+ }
+
+ /**
+ * Gets the specified certificate issuer.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param issuerName The name of the issuer.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getCertificateIssuerAsync(String vaultBaseUrl, String issuerName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateIssuerAsync(vaultBaseUrl, issuerName, serviceCallback);
+ }
+
+ /**
+ * Deletes the specified certificate issuer.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param issuerName The name of the issuer.
+ *
+ * @return the IssuerBundle if successful.
+ */
+ public IssuerBundle deleteCertificateIssuer(String vaultBaseUrl, String issuerName) {
+ return innerKeyVaultClient.deleteCertificateIssuer(vaultBaseUrl, issuerName);
+ }
+
+ /**
+ * Deletes the specified certificate issuer.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param issuerName The name of the issuer.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture deleteCertificateIssuerAsync(String vaultBaseUrl, String issuerName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.deleteCertificateIssuerAsync(vaultBaseUrl, issuerName, serviceCallback);
+ }
+
+ /**
+ * Creates a new certificate version. If this is the first version, the certificate resource is created.
+ *
+ * @param createCertificateRequest the grouped properties for creating a certificate request
+ *
+ * @return the CertificateOperation if successful.
+ */
+ public CertificateOperation createCertificate(CreateCertificateRequest createCertificateRequest) {
+ return innerKeyVaultClient.createCertificate(
+ createCertificateRequest.vaultBaseUrl(),
+ createCertificateRequest.certificateName(),
+ createCertificateRequest.certificatePolicy(),
+ createCertificateRequest.certificateAttributes(),
+ createCertificateRequest.tags());
+ }
+
+ /**
+ * Creates a new certificate version. If this is the first version, the certificate resource is created.
+ *
+ * @param createCertificateRequest the grouped properties for creating a certificate request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture createCertificateAsync(CreateCertificateRequest createCertificateRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.createCertificateAsync(
+ createCertificateRequest.vaultBaseUrl(),
+ createCertificateRequest.certificateName(),
+ createCertificateRequest.certificatePolicy(),
+ createCertificateRequest.certificateAttributes(),
+ createCertificateRequest.tags(),
+ serviceCallback);
+ }
+
+ /**
+ * Imports a certificate into the specified vault.
+ *
+ * @param importCertificateRequest the grouped properties for importing a certificate request
+ *
+ * @return the CertificateBundle if successful.
+ */
+ public CertificateBundle importCertificate(ImportCertificateRequest importCertificateRequest) {
+ return innerKeyVaultClient.importCertificate(
+ importCertificateRequest.vaultBaseUrl(),
+ importCertificateRequest.certificateName(),
+ importCertificateRequest.base64EncodedCertificate(),
+ importCertificateRequest.password(),
+ importCertificateRequest.certificatePolicy(),
+ importCertificateRequest.certificateAttributes(),
+ importCertificateRequest.tags());
+ }
+
+ /**
+ * Imports a certificate into the specified vault.
+ *
+ * @param importCertificateRequest the grouped properties for importing a certificate request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture importCertificateAsync(ImportCertificateRequest importCertificateRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.importCertificateAsync(
+ importCertificateRequest.vaultBaseUrl(),
+ importCertificateRequest.certificateName(),
+ importCertificateRequest.base64EncodedCertificate(),
+ importCertificateRequest.password(),
+ importCertificateRequest.certificatePolicy(),
+ importCertificateRequest.certificateAttributes(),
+ importCertificateRequest.tags(),
+ serviceCallback);
+ }
+
+ /**
+ * List the versions of a certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ *
+ * @return the PagedList<CertificateItem> if successful.
+ */
+ public PagedList listCertificateVersions(final String vaultBaseUrl, final String certificateName) {
+ return innerKeyVaultClient.getCertificateVersions(vaultBaseUrl, certificateName);
+ }
+
+ /**
+ * List the versions of a certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listCertificateVersionsAsync(final String vaultBaseUrl, final String certificateName, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateVersionsAsync(vaultBaseUrl, certificateName, serviceCallback);
+ }
+ /**
+ * List the versions of a certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ *
+ * @return the PagedList<CertificateItem> if successful.
+ */
+ public PagedList listCertificateVersions(final String vaultBaseUrl, final String certificateName, final Integer maxresults) {
+ return innerKeyVaultClient.getCertificateVersions(vaultBaseUrl, certificateName, maxresults);
+ }
+
+ /**
+ * List the versions of a certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ * @param maxresults Maximum number of results to return in a page. If not specified the service will return up to 25 results.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture> listCertificateVersionsAsync(final String vaultBaseUrl, final String certificateName, final Integer maxresults, final ListOperationCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateVersionsAsync(vaultBaseUrl, certificateName, maxresults, serviceCallback);
+ }
+
+ /**
+ * Gets the policy for a certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault.
+ *
+ * @return the CertificatePolicy if successful.
+ */
+ public CertificatePolicy getCertificatePolicy(String vaultBaseUrl, String certificateName) {
+ return innerKeyVaultClient.getCertificatePolicy(vaultBaseUrl, certificateName);
+ }
+
+ /**
+ * Gets the policy for a certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault.
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getCertificatePolicyAsync(String vaultBaseUrl, String certificateName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificatePolicyAsync(vaultBaseUrl, certificateName, serviceCallback);
+ }
+
+ /**
+ * Updates the policy for a certificate. Set appropriate members in the certificatePolicy that must be updated. Leave others as null.
+ *
+ * @param updateCertificatePolicyRequest the grouped properties for updating a certificate policy request
+ *
+ * @return the CertificatePolicy if successful.
+ */
+ public CertificatePolicy updateCertificatePolicy(UpdateCertificatePolicyRequest updateCertificatePolicyRequest) {
+ return innerKeyVaultClient.updateCertificatePolicy(
+ updateCertificatePolicyRequest.vaultBaseUrl(),
+ updateCertificatePolicyRequest.certificateName(),
+ updateCertificatePolicyRequest.certificatePolicy());
+ }
+
+ /**
+ * Updates the policy for a certificate. Set appropriate members in the certificatePolicy that must be updated. Leave others as null.
+ *
+ * @param updateCertificatePolicyRequest the grouped properties for updating a certificate policy request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture updateCertificatePolicyAsync(UpdateCertificatePolicyRequest updateCertificatePolicyRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.updateCertificatePolicyAsync(
+ updateCertificatePolicyRequest.vaultBaseUrl(),
+ updateCertificatePolicyRequest.certificateName(),
+ updateCertificatePolicyRequest.certificatePolicy(),
+ serviceCallback);
+ }
+
+ /**
+ * Updates the attributes associated with the specified certificate.
+ *
+ * @param updateCertificateRequest the grouped properties for updating a certificate request
+ *
+ * @return the CertificateBundle if successful.
+ */
+ public CertificateBundle updateCertificate(UpdateCertificateRequest updateCertificateRequest) {
+ return innerKeyVaultClient.updateCertificate(
+ updateCertificateRequest.vaultBaseUrl(),
+ updateCertificateRequest.certificateName(),
+ updateCertificateRequest.certificateVersion(),
+ updateCertificateRequest.certificatePolicy(),
+ updateCertificateRequest.certificateAttributes(),
+ updateCertificateRequest.tags());
+ }
+
+ /**
+ * Updates the attributes associated with the specified certificate.
+ *
+ * @param updateCertificateRequest the grouped properties for updating a certificate request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture updateCertificateAsync(UpdateCertificateRequest updateCertificateRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.updateCertificateAsync(
+ updateCertificateRequest.vaultBaseUrl(),
+ updateCertificateRequest.certificateName(),
+ updateCertificateRequest.certificateVersion(),
+ updateCertificateRequest.certificatePolicy(),
+ updateCertificateRequest.certificateAttributes(),
+ updateCertificateRequest.tags(),
+ serviceCallback);
+ }
+
+ /**
+ * Gets information about a specified certificate.
+ *
+ * @param certificateIdentifier The certificate identifier
+ *
+ * @return the CertificateBundle if successful.
+ */
+ public CertificateBundle getCertificate(String certificateIdentifier) {
+ CertificateIdentifier id = new CertificateIdentifier(certificateIdentifier);
+ return innerKeyVaultClient.getCertificate(id.vault, id.name, id.version == null ? "" : id.version);
+ }
+
+ /**
+ * Gets information about a specified certificate.
+ *
+ * @param certificateIdentifier The certificate identifier
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getCertificateAsync(String certificateIdentifier, final ServiceCallback serviceCallback) {
+ CertificateIdentifier id = new CertificateIdentifier(certificateIdentifier);
+ return innerKeyVaultClient.getCertificateAsync(id.vault, id.name, id.version == null ? "" : id.version, serviceCallback);
+ }
+
+ /**
+ * Gets information about a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault
+ *
+ * @return the CertificateBundle if successful.
+ */
+ public CertificateBundle getCertificate(String vaultBaseUrl, String certificateName) {
+ return innerKeyVaultClient.getCertificate(vaultBaseUrl, certificateName, "");
+ }
+
+ /**
+ * Gets information about a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getCertificateAsync(String vaultBaseUrl, String certificateName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateAsync(vaultBaseUrl, certificateName, "", serviceCallback);
+ }
+
+ /**
+ * Gets information about a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault
+ * @param certificateVersion The version of the certificate
+ *
+ * @return the CertificateBundle if successful.
+ */
+ public CertificateBundle getCertificate(String vaultBaseUrl, String certificateName, String certificateVersion) {
+ return innerKeyVaultClient.getCertificate(vaultBaseUrl, certificateName, certificateVersion);
+ }
+
+ /**
+ * Gets information about a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate in the given vault
+ * @param certificateVersion The version of the certificate
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getCertificateAsync(String vaultBaseUrl, String certificateName, String certificateVersion, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateAsync(vaultBaseUrl, certificateName, certificateVersion, serviceCallback);
+ }
+
+ /**
+ * Updates a certificate operation.
+ *
+ * @param updateCertificateOperationRequest the grouped properties for updating a certificate operation request
+ *
+ * @return the CertificateOperation if successful.
+ */
+ public CertificateOperation updateCertificateOperation(UpdateCertificateOperationRequest updateCertificateOperationRequest) {
+ return innerKeyVaultClient.updateCertificateOperation(
+ updateCertificateOperationRequest.vaultBaseUrl(),
+ updateCertificateOperationRequest.certificateName(),
+ updateCertificateOperationRequest.cancellationRequested());
+ }
+
+ /**
+ * Updates a certificate operation.
+ *
+ * @param updateCertificateOperationRequest the grouped properties for updating a certificate operation request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture updateCertificateOperationAsync(UpdateCertificateOperationRequest updateCertificateOperationRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.updateCertificateOperationAsync(
+ updateCertificateOperationRequest.vaultBaseUrl(),
+ updateCertificateOperationRequest.certificateName(),
+ updateCertificateOperationRequest.cancellationRequested(),
+ serviceCallback);
+ }
+
+ /**
+ * Gets the operation associated with a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ *
+ * @return the CertificateOperation if successful.
+ */
+ public CertificateOperation getCertificateOperation(String vaultBaseUrl, String certificateName) {
+ return innerKeyVaultClient.getCertificateOperation(vaultBaseUrl, certificateName);
+ }
+
+ /**
+ * Gets the operation associated with a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getCertificateOperationAsync(String vaultBaseUrl, String certificateName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.getCertificateOperationAsync(vaultBaseUrl, certificateName, serviceCallback);
+ }
+
+ /**
+ * Deletes the operation for a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ *
+ * @return the CertificateOperation if successful.
+ */
+ public CertificateOperation deleteCertificateOperation(String vaultBaseUrl, String certificateName) {
+ return innerKeyVaultClient.deleteCertificateOperation(vaultBaseUrl, certificateName);
+ }
+
+ /**
+ * Deletes the operation for a specified certificate.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture deleteCertificateOperationAsync(String vaultBaseUrl, String certificateName, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.deleteCertificateOperationAsync(vaultBaseUrl, certificateName, serviceCallback);
+ }
+
+ /**
+ * Merges a certificate or a certificate chain with a key pair existing on the server.
+ *
+ * @param mergeCertificateRequest the grouped properties for merging a certificate request
+ *
+ * @return the CertificateBundle if successful.
+ */
+ public CertificateBundle mergeCertificate(MergeCertificateRequest mergeCertificateRequest) {
+ return innerKeyVaultClient.mergeCertificate(
+ mergeCertificateRequest.vaultBaseUrl(),
+ mergeCertificateRequest.certificateName(),
+ mergeCertificateRequest.x509Certificates(),
+ mergeCertificateRequest.certificateAttributes(),
+ mergeCertificateRequest.tags());
+ }
+
+ /**
+ * Merges a certificate or a certificate chain with a key pair existing on the server.
+ *
+ * @param mergeCertificateRequest the grouped properties for merging a certificate request
+ *
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture mergeCertificateAsync(MergeCertificateRequest mergeCertificateRequest, final ServiceCallback serviceCallback) {
+ return innerKeyVaultClient.mergeCertificateAsync(
+ mergeCertificateRequest.vaultBaseUrl(),
+ mergeCertificateRequest.certificateName(),
+ mergeCertificateRequest.x509Certificates(),
+ mergeCertificateRequest.certificateAttributes(),
+ mergeCertificateRequest.tags(),
+ serviceCallback);
+ }
+
+
+ /**
+ * Gets the pending certificate signing request response.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ *
+ * @return the String if successful.
+ */
+ public String getPendingCertificateSigningRequest(String vaultBaseUrl, String certificateName) {
+ return getPendingCertificateSigningRequestWithServiceResponseAsync(vaultBaseUrl, certificateName).toBlocking().single().body();
+ }
+
+ /**
+ * Gets the pending certificate signing request response.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
+ * @return the {@link ServiceFuture} object
+ */
+ public ServiceFuture getPendingCertificateSigningRequestAsync(String vaultBaseUrl, String certificateName, final ServiceCallback serviceCallback) {
+ return ServiceFuture.fromResponse(getPendingCertificateSigningRequestWithServiceResponseAsync(vaultBaseUrl, certificateName), serviceCallback);
+ }
+
+ /**
+ * Gets the pending certificate signing request response.
+ *
+ * @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
+ * @param certificateName The name of the certificate
+ * @return the observable to the String object
+ */
+ private Observable> getPendingCertificateSigningRequestWithServiceResponseAsync(String vaultBaseUrl, String certificateName) {
+ if (vaultBaseUrl == null) {
+ throw new IllegalArgumentException("Parameter vaultBaseUrl is required and cannot be null.");
+ }
+ if (certificateName == null) {
+ throw new IllegalArgumentException("Parameter certificateName is required and cannot be null.");
+ }
+ if (this.apiVersion() == null) {
+ throw new IllegalArgumentException("Parameter this.apiVersion() is required and cannot be null.");
+ }
+ String parameterizedHost = Joiner.on(", ").join("{vaultBaseUrl}", vaultBaseUrl);
+ return service.getPendingCertificateSigningRequest(certificateName, this.apiVersion(), this.acceptLanguage(), parameterizedHost, this.userAgent())
+ .flatMap(new Func1, Observable>>() {
+ @Override
+ public Observable> call(Response response) {
+ try {
+ ServiceResponse clientResponse = new ServiceResponse(response.body().string(), response);
+ return Observable.just(clientResponse);
+ } catch (Throwable t) {
+ return Observable.error(t);
+ }
+ }
+ });
+ }
+}
diff --git a/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyVaultClientImpl.java b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyVaultClientImpl.java
new file mode 100755
index 000000000000..e2d082710b89
--- /dev/null
+++ b/azure-keyvault/src/main/java/com/microsoft/azure/keyvault/KeyVaultClientImpl.java
@@ -0,0 +1,6823 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ *
+ * Code generated by Microsoft (R) AutoRest Code Generator 1.0.0.0
+ * Changes may cause incorrect behavior and will be lost if the code is
+ * regenerated.
+ */
+
+package com.microsoft.azure.keyvault;
+
+import com.google.common.base.Joiner;
+import com.google.common.reflect.TypeToken;
+import com.microsoft.azure.AzureClient;
+import com.microsoft.azure.AzureServiceFuture;
+import com.microsoft.azure.AzureServiceClient;
+import com.microsoft.azure.keyvault.models.BackupKeyResult;
+import com.microsoft.azure.keyvault.models.CertificateAttributes;
+import com.microsoft.azure.keyvault.models.CertificateBundle;
+import com.microsoft.azure.keyvault.models.CertificateCreateParameters;
+import com.microsoft.azure.keyvault.models.CertificateImportParameters;
+import com.microsoft.azure.keyvault.models.CertificateIssuerItem;
+import com.microsoft.azure.keyvault.models.CertificateIssuerSetParameters;
+import com.microsoft.azure.keyvault.models.CertificateIssuerUpdateParameters;
+import com.microsoft.azure.keyvault.models.CertificateItem;
+import com.microsoft.azure.keyvault.models.CertificateMergeParameters;
+import com.microsoft.azure.keyvault.models.CertificateOperation;
+import com.microsoft.azure.keyvault.models.CertificateOperationUpdateParameter;
+import com.microsoft.azure.keyvault.models.CertificatePolicy;
+import com.microsoft.azure.keyvault.models.CertificateUpdateParameters;
+import com.microsoft.azure.keyvault.models.Contacts;
+import com.microsoft.azure.keyvault.models.IssuerAttributes;
+import com.microsoft.azure.keyvault.models.IssuerBundle;
+import com.microsoft.azure.keyvault.models.IssuerCredentials;
+import com.microsoft.azure.keyvault.models.KeyAttributes;
+import com.microsoft.azure.keyvault.models.KeyBundle;
+import com.microsoft.azure.keyvault.models.KeyCreateParameters;
+import com.microsoft.azure.keyvault.models.KeyImportParameters;
+import com.microsoft.azure.keyvault.models.KeyItem;
+import com.microsoft.azure.keyvault.models.KeyOperationResult;
+import com.microsoft.azure.keyvault.models.KeyOperationsParameters;
+import com.microsoft.azure.keyvault.models.KeyRestoreParameters;
+import com.microsoft.azure.keyvault.models.KeySignParameters;
+import com.microsoft.azure.keyvault.models.KeyUpdateParameters;
+import com.microsoft.azure.keyvault.models.KeyVaultErrorException;
+import com.microsoft.azure.keyvault.models.KeyVerifyParameters;
+import com.microsoft.azure.keyvault.models.KeyVerifyResult;
+import com.microsoft.azure.keyvault.models.OrganizationDetails;
+import com.microsoft.azure.keyvault.models.PageImpl;
+import com.microsoft.azure.keyvault.models.SecretAttributes;
+import com.microsoft.azure.keyvault.models.SecretBundle;
+import com.microsoft.azure.keyvault.models.SecretItem;
+import com.microsoft.azure.keyvault.models.SecretSetParameters;
+import com.microsoft.azure.keyvault.models.SecretUpdateParameters;
+import com.microsoft.azure.keyvault.webkey.JsonWebKey;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyEncryptionAlgorithm;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyOperation;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeySignatureAlgorithm;
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyType;
+import com.microsoft.azure.ListOperationCallback;
+import com.microsoft.azure.Page;
+import com.microsoft.azure.PagedList;
+import com.microsoft.rest.credentials.ServiceClientCredentials;
+import com.microsoft.rest.RestClient;
+import com.microsoft.rest.ServiceFuture;
+import com.microsoft.rest.ServiceCallback;
+import com.microsoft.rest.ServiceResponse;
+import com.microsoft.rest.Validator;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import okhttp3.ResponseBody;
+import retrofit2.http.Body;
+import retrofit2.http.GET;
+import retrofit2.http.Header;
+import retrofit2.http.Headers;
+import retrofit2.http.HTTP;
+import retrofit2.http.PATCH;
+import retrofit2.http.Path;
+import retrofit2.http.POST;
+import retrofit2.http.PUT;
+import retrofit2.http.Query;
+import retrofit2.http.Url;
+import retrofit2.Response;
+import rx.functions.Func1;
+import rx.Observable;
+
+/**
+ * Initializes a new instance of the KeyVaultClientImpl class.
+ */
+final class KeyVaultClientImpl extends AzureServiceClient {
+ /** The Retrofit service to perform REST calls. */
+ private KeyVaultClientService service;
+ /** the {@link AzureClient} used for long running operations. */
+ private AzureClient azureClient;
+
+ /**
+ * Gets the {@link AzureClient} used for long running operations.
+ * @return the azure client;
+ */
+ public AzureClient getAzureClient() {
+ return this.azureClient;
+ }
+
+ /** Client API version. */
+ private String apiVersion;
+
+ /**
+ * Gets Client API version.
+ *
+ * @return the apiVersion value.
+ */
+ public String apiVersion() {
+ return this.apiVersion;
+ }
+
+ /** Gets or sets the preferred language for the response. */
+ private String acceptLanguage;
+
+ /**
+ * Gets Gets or sets the preferred language for the response.
+ *
+ * @return the acceptLanguage value.
+ */
+ public String acceptLanguage() {
+ return this.acceptLanguage;
+ }
+
+ /**
+ * Sets Gets or sets the preferred language for the response.
+ *
+ * @param acceptLanguage the acceptLanguage value.
+ * @return the service client itself
+ */
+ public KeyVaultClientImpl withAcceptLanguage(String acceptLanguage) {
+ this.acceptLanguage = acceptLanguage;
+ return this;
+ }
+
+ /** Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30. */
+ private int longRunningOperationRetryTimeout;
+
+ /**
+ * Gets Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30.
+ *
+ * @return the longRunningOperationRetryTimeout value.
+ */
+ public int longRunningOperationRetryTimeout() {
+ return this.longRunningOperationRetryTimeout;
+ }
+
+ /**
+ * Sets Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30.
+ *
+ * @param longRunningOperationRetryTimeout the longRunningOperationRetryTimeout value.
+ * @return the service client itself
+ */
+ public KeyVaultClientImpl withLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout) {
+ this.longRunningOperationRetryTimeout = longRunningOperationRetryTimeout;
+ return this;
+ }
+
+ /** When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true. */
+ private boolean generateClientRequestId;
+
+ /**
+ * Gets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.
+ *
+ * @return the generateClientRequestId value.
+ */
+ public boolean generateClientRequestId() {
+ return this.generateClientRequestId;
+ }
+
+ /**
+ * Sets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.
+ *
+ * @param generateClientRequestId the generateClientRequestId value.
+ * @return the service client itself
+ */
+ public KeyVaultClientImpl withGenerateClientRequestId(boolean generateClientRequestId) {
+ this.generateClientRequestId = generateClientRequestId;
+ return this;
+ }
+
+ /**
+ * Initializes an instance of KeyVaultClient client.
+ *
+ * @param credentials the management credentials for Azure
+ */
+ public KeyVaultClientImpl(ServiceClientCredentials credentials) {
+ this("https://{vaultBaseUrl}", credentials);
+ }
+
+ /**
+ * Initializes an instance of KeyVaultClient client.
+ *
+ * @param baseUrl the base URL of the host
+ * @param credentials the management credentials for Azure
+ */
+ private KeyVaultClientImpl(String baseUrl, ServiceClientCredentials credentials) {
+ super(baseUrl, credentials);
+ initialize();
+ }
+
+ /**
+ * Initializes an instance of KeyVaultClient client.
+ *
+ * @param restClient the REST client to connect to Azure.
+ */
+ public KeyVaultClientImpl(RestClient restClient) {
+ super(restClient);
+ initialize();
+ }
+
+ protected void initialize() {
+ this.apiVersion = "2016-10-01";
+ this.acceptLanguage = "en-US";
+ this.longRunningOperationRetryTimeout = 30;
+ this.generateClientRequestId = true;
+ this.azureClient = new AzureClient(this);
+ initializeService();
+ }
+
+ /**
+ * Gets the User-Agent header for the client.
+ *
+ * @return the user agent string.
+ */
+ @Override
+ public String userAgent() {
+ return String.format("Azure-SDK-For-Java/%s (%s)",
+ getClass().getPackage().getImplementationVersion(),
+ "KeyVaultClient, 2016-10-01");
+ }
+
+ private void initializeService() {
+ service = restClient().retrofit().create(KeyVaultClientService.class);
+ }
+
+ /**
+ * The interface defining all the services for KeyVaultClient to be
+ * used by Retrofit to perform actually REST calls.
+ */
+ interface KeyVaultClientService {
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient createKey" })
+ @POST("keys/{key-name}/create")
+ Observable> createKey(@Path("key-name") String keyName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyCreateParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient importKey" })
+ @PUT("keys/{key-name}")
+ Observable> importKey(@Path("key-name") String keyName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyImportParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient deleteKey" })
+ @HTTP(path = "keys/{key-name}", method = "DELETE", hasBody = true)
+ Observable> deleteKey(@Path("key-name") String keyName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient updateKey" })
+ @PATCH("keys/{key-name}/{key-version}")
+ Observable> updateKey(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyUpdateParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getKey" })
+ @GET("keys/{key-name}/{key-version}")
+ Observable> getKey(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getKeyVersions" })
+ @GET("keys/{key-name}/versions")
+ Observable> getKeyVersions(@Path("key-name") String keyName, @Query("maxresults") Integer maxresults, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getKeys" })
+ @GET("keys")
+ Observable> getKeys(@Query("maxresults") Integer maxresults, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient backupKey" })
+ @POST("keys/{key-name}/backup")
+ Observable> backupKey(@Path("key-name") String keyName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient restoreKey" })
+ @POST("keys/restore")
+ Observable> restoreKey(@Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyRestoreParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient encrypt" })
+ @POST("keys/{key-name}/{key-version}/encrypt")
+ Observable> encrypt(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyOperationsParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient decrypt" })
+ @POST("keys/{key-name}/{key-version}/decrypt")
+ Observable> decrypt(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyOperationsParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient sign" })
+ @POST("keys/{key-name}/{key-version}/sign")
+ Observable> sign(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeySignParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient verify" })
+ @POST("keys/{key-name}/{key-version}/verify")
+ Observable> verify(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyVerifyParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient wrapKey" })
+ @POST("keys/{key-name}/{key-version}/wrapkey")
+ Observable> wrapKey(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyOperationsParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient unwrapKey" })
+ @POST("keys/{key-name}/{key-version}/unwrapkey")
+ Observable> unwrapKey(@Path("key-name") String keyName, @Path("key-version") String keyVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body KeyOperationsParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient setSecret" })
+ @PUT("secrets/{secret-name}")
+ Observable> setSecret(@Path("secret-name") String secretName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body SecretSetParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient deleteSecret" })
+ @HTTP(path = "secrets/{secret-name}", method = "DELETE", hasBody = true)
+ Observable> deleteSecret(@Path("secret-name") String secretName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient updateSecret" })
+ @PATCH("secrets/{secret-name}/{secret-version}")
+ Observable> updateSecret(@Path("secret-name") String secretName, @Path("secret-version") String secretVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body SecretUpdateParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getSecret" })
+ @GET("secrets/{secret-name}/{secret-version}")
+ Observable> getSecret(@Path("secret-name") String secretName, @Path("secret-version") String secretVersion, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getSecrets" })
+ @GET("secrets")
+ Observable> getSecrets(@Query("maxresults") Integer maxresults, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getSecretVersions" })
+ @GET("secrets/{secret-name}/versions")
+ Observable> getSecretVersions(@Path("secret-name") String secretName, @Query("maxresults") Integer maxresults, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getCertificates" })
+ @GET("certificates")
+ Observable> getCertificates(@Query("maxresults") Integer maxresults, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient deleteCertificate" })
+ @HTTP(path = "certificates/{certificate-name}", method = "DELETE", hasBody = true)
+ Observable> deleteCertificate(@Path("certificate-name") String certificateName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient setCertificateContacts" })
+ @PUT("certificates/contacts")
+ Observable> setCertificateContacts(@Body Contacts contacts, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getCertificateContacts" })
+ @GET("certificates/contacts")
+ Observable> getCertificateContacts(@Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient deleteCertificateContacts" })
+ @HTTP(path = "certificates/contacts", method = "DELETE", hasBody = true)
+ Observable> deleteCertificateContacts(@Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getCertificateIssuers" })
+ @GET("certificates/issuers")
+ Observable> getCertificateIssuers(@Query("maxresults") Integer maxresults, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient setCertificateIssuer" })
+ @PUT("certificates/issuers/{issuer-name}")
+ Observable> setCertificateIssuer(@Path("issuer-name") String issuerName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body CertificateIssuerSetParameters parameter, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient updateCertificateIssuer" })
+ @PATCH("certificates/issuers/{issuer-name}")
+ Observable> updateCertificateIssuer(@Path("issuer-name") String issuerName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body CertificateIssuerUpdateParameters parameter, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getCertificateIssuer" })
+ @GET("certificates/issuers/{issuer-name}")
+ Observable> getCertificateIssuer(@Path("issuer-name") String issuerName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient deleteCertificateIssuer" })
+ @HTTP(path = "certificates/issuers/{issuer-name}", method = "DELETE", hasBody = true)
+ Observable> deleteCertificateIssuer(@Path("issuer-name") String issuerName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient createCertificate" })
+ @POST("certificates/{certificate-name}/create")
+ Observable> createCertificate(@Path("certificate-name") String certificateName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body CertificateCreateParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient importCertificate" })
+ @POST("certificates/{certificate-name}/import")
+ Observable> importCertificate(@Path("certificate-name") String certificateName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Body CertificateImportParameters parameters, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getCertificateVersions" })
+ @GET("certificates/{certificate-name}/versions")
+ Observable> getCertificateVersions(@Path("certificate-name") String certificateName, @Query("maxresults") Integer maxresults, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient getCertificatePolicy" })
+ @GET("certificates/{certificate-name}/policy")
+ Observable> getCertificatePolicy(@Path("certificate-name") String certificateName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient updateCertificatePolicy" })
+ @PATCH("certificates/{certificate-name}/policy")
+ Observable> updateCertificatePolicy(@Path("certificate-name") String certificateName, @Body CertificatePolicy certificatePolicy, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);
+
+ @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.keyvault.KeyVaultClient updateCertificate" })
+ @PATCH("certificates/{certificate-name}/{certificate-version}")
+ Observable