Java tutorial
/******************************************************************************* * Copyright Microsoft Open Technologies, Inc. * * 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.aad.adal4j; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.codec.binary.Base64; /** * Credential type containing X509 public certificate and RSA private key. */ public final class MSCAPIAsymmetricKeyCredential { public final static int MIN_KEYSIZE_IN_BITS = 2048; private final String clientId; private final PrivateKey key; private final X509Certificate publicCertificate; /** * Constructor to create credential with client id, private key and public * certificate. * * @param clientId * Identifier of the client requesting the token. * @param key * RSA private key to sign the assertion. * @param publicCertificate * Public certificate used for thumb print. */ private MSCAPIAsymmetricKeyCredential(final String clientId, final PrivateKey key, final X509Certificate publicCertificate) { int KeySize = 0; if (StringHelper.isBlank(clientId)) { throw new IllegalArgumentException("clientId is null or empty"); } if (key == null) { throw new NullPointerException("PrivateKey"); } this.clientId = clientId; this.key = key; // Begin Updates by Rob Reilly 5/19/2016 if (key instanceof RSAPrivateKey) { KeySize = ((RSAPrivateKey) key).getModulus().bitLength(); } else if (key instanceof PrivateKey) { String keyData = key.toString(); Pattern pattern = Pattern.compile("(.*size=)(\\d{4,})(\\sbits)"); Matcher matcher = pattern.matcher(keyData); matcher.find(); KeySize = Integer.parseInt(matcher.group(2)); } if (KeySize < MIN_KEYSIZE_IN_BITS) { throw new IllegalArgumentException("certificate key size must be at least " + MIN_KEYSIZE_IN_BITS); } // End Updates by Rob Reilly 5/19/2016 this.publicCertificate = publicCertificate; } /** * Gets the identifier of the client requesting the token. * * @return string value */ public String getClientId() { return clientId; } /** * Base64 encoded hash of the the public certificate. * * @return base64 endoded string * @throws CertificateEncodingException * @throws NoSuchAlgorithmException */ public String getPublicCertificateHash() throws CertificateEncodingException, NoSuchAlgorithmException { return Base64 .encodeBase64String(MSCAPIAsymmetricKeyCredential.getHash(this.publicCertificate.getEncoded())); } /** * Base64 encoded public certificate. * * @return base64 endoded string * @throws CertificateEncodingException * @throws NoSuchAlgorithmException */ public String getPublicCertificate() throws CertificateEncodingException, NoSuchAlgorithmException { return Base64.encodeBase64String(this.publicCertificate.getEncoded()); } /** * Returns private key of the credential. * * @return private key. */ public Key getKey() { return key; } /** * Static method to create KeyCredential instance. * * @param clientId * Identifier of the client requesting the token. * @param pkcs12Certificate * PKCS12 certificate stream containing public and private key. * Caller is responsible to handling the inputstream. * @param password * certificate password * @return KeyCredential instance * @throws KeyStoreException * @throws NoSuchProviderException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws FileNotFoundException * @throws IOException * @throws UnrecoverableKeyException */ public static MSCAPIAsymmetricKeyCredential create(final String clientId, final InputStream pkcs12Certificate, final String password) throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException { final KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE"); keystore.load(pkcs12Certificate, password.toCharArray()); final Enumeration<String> aliases = keystore.aliases(); final String alias = aliases.nextElement(); final PrivateKey key = (PrivateKey) keystore.getKey(alias, password.toCharArray()); final X509Certificate publicCertificate = (X509Certificate) keystore.getCertificate(alias); return create(clientId, key, publicCertificate); } /** * Static method to create KeyCredential instance. * * @param clientId * Identifier of the client requesting the token. * @param key * RSA private key to sign the assertion. * @param publicCertificate * Public certificate used for thumb print. * @return KeyCredential instance */ public static MSCAPIAsymmetricKeyCredential create(final String clientId, final PrivateKey key, final X509Certificate publicCertificate) { return new MSCAPIAsymmetricKeyCredential(clientId, key, publicCertificate); } private static byte[] getHash(final byte[] inputBytes) throws NoSuchAlgorithmException, CertificateEncodingException { final MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(inputBytes); return md.digest(); } }