package com.qoppa.internal; import java.io.OutputStream; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; import org.bouncycastle.operator.DigestCalculator; 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; import com.microsoft.azure.keyvault.models.CertificatePolicy; import com.microsoft.azure.keyvault.models.KeyOperationResult; import com.microsoft.azure.keyvault.webkey.JsonWebKeySignatureAlgorithm; import sun.security.x509.X509CertImpl; public class AzureContentSigner implements ContentSigner { private DigestCalculator m_DigestCalculator = new SHA256DigestCalculator(); private KeyVaultClient m_Client; private String m_KeyId; private String m_CertId; public AzureContentSigner(KeyVaultClient client, String keyId, String certId) { m_Client = client; m_KeyId = keyId; m_CertId = certId; } public AzureContentSigner(final String clientId, final String clientPassword, String keyId, String certId) { m_KeyId = keyId; m_CertId = certId; m_Client = new KeyVaultClient(new KeyVaultCredentials() { @Override public String doAuthenticate(String authorization, String resource, String scope) { AuthenticationResult token = getAccessTokenFromClientCredentials(authorization, resource, clientId, clientPassword); return token.getAccessToken(); } private AuthenticationResult getAccessTokenFromClientCredentials(String authorization, String resource, String clientId, String clientKey) { AuthenticationContext context = null; AuthenticationResult result = null; ExecutorService service = null; try { service = Executors.newFixedThreadPool(1); context = new AuthenticationContext(authorization, false, service); ClientCredential credentials = new ClientCredential(clientId, clientKey); Future future = context.acquireToken(resource, credentials, null); result = future.get(); } catch (Exception e) { throw new RuntimeException(e); } finally { service.shutdown(); } if (result == null) { throw new RuntimeException("authentication result was null"); } return result; } }); } @Override public AlgorithmIdentifier getAlgorithmIdentifier() { return new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA"); } @Override public OutputStream getOutputStream() { return m_DigestCalculator.getOutputStream(); } @Override public byte[] getSignature() { KeyOperationResult res = m_Client.sign(m_KeyId, JsonWebKeySignatureAlgorithm.RS256, m_DigestCalculator.getDigest()); return res.result(); } public Certificate getCertificate() throws CertificateException { return new X509CertImpl(m_Client.getCertificate(m_CertId).cer()); } public Certificate[] getCertificateChain() throws CertificateException { // TODO: We need the rest of the chain return new Certificate [] {getCertificate()}; } }