All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.identityx.clientSDK.base.KeyHelper Maven / Gradle / Ivy

There is a newer version: 5.6.0.2
Show newest version
/*
* Copyright Daon.
*
* 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.identityx.clientSDK.base;

import com.daon.identityx.rest.model.pojo.Token;
import com.identityx.auth.impl.keys.SharedSecretApiKey;

import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Date;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;


/**
 * Helper class for managing decryption of the shared secret passed back in a {@link Token} object. 
 * When a request for a new token is made, RSA 2048 key pair is generated. The public key wrapped in a X509 certificate is sent over to the server 
 * in order to be used for encrypting the shared secret to be returned.
 * The private key is then used to decrypt the shared secret so it can be used in subsequent calls to the Rest servcies. 
 *
 */
public class KeyHelper {

	private KeyPair keyPair;

	public KeyHelper() throws NoSuchAlgorithmException {
		GenerateKeyPair();
	}
	
	/**
	 * Gets a string containing the base64 encoding of a X509 certificate containing a new public key ready to be used for the creation of a new token.   
	 * @param cn common name to be used for the certificate 
	 * @return
	 * @throws IOException
	 */
	public String getPublicKeyForTokenRequest(String cn) throws IOException {
				
		//String publicKey = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
		String publicKey = Base64.encodeBase64String(generateCertificate(cn).getEncoded());
		return publicKey;
	} 

	
	/**
	 * Creates a {@link SharedSecretApiKey} from a {@link Token} object returned by one of the token services 
	 * @param token {@link Token}
	 * @return {@link SharedSecretApiKey} ready to be used as a credential.
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public SharedSecretApiKey createFromToken(Token token) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { 
		// decrypt the key
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
		byte[] data = Base64.decodeBase64(token.getEncryptedSharedKey());
		byte[] descryptedData = cipher.doFinal(data);
	
		SharedSecretApiKey newApiKey = new SharedSecretApiKey();
		newApiKey.setId(token.getId());
		String base64Decrypted = Base64.encodeBase64String(descryptedData);
		newApiKey.setSecret(base64Decrypted);
			
		return newApiKey;
	}
	
	/**
	 * Generates a new RSA 2048 key pair
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	protected KeyPair GenerateKeyPair() throws NoSuchAlgorithmException {			
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(2048);
		keyPair = keyPairGenerator.generateKeyPair();

		return keyPair;
	}
	
		
	/**
	 * Creates a new X509 certificate
	 * @param cn the common name for the certificate
	 * @return
	 */
	protected Certificate generateCertificate(String cn) {
		
	  try {
		
		  Certificate result;
		  byte publicKeyBytes[] = keyPair.getPublic().getEncoded();
		  
		  SubjectPublicKeyInfo subPkInfo = new SubjectPublicKeyInfo(ASN1Sequence.getInstance(publicKeyBytes));
		  
		  X509v3CertificateBuilder builder = new X509v3CertificateBuilder(
					new X500Name("CN=" + cn),
					BigInteger.valueOf(new SecureRandom().nextLong()),
					new Date(System.currentTimeMillis() - 10000),new Date(System.currentTimeMillis() + 24L * 3600 * 1000),
					new X500Name("CN=" + cn),
					subPkInfo);
		 
		  builder.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(false));			 
		  builder.addExtension(X509Extension.keyUsage,true,new KeyUsage(KeyUsage.dataEncipherment));			 
		  builder.addExtension(X509Extension.extendedKeyUsage,true,new ExtendedKeyUsage(KeyPurposeId.anyExtendedKeyUsage));
			
		  AlgorithmIdentifier sigAlgId=new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");
		  AlgorithmIdentifier digAlgId=new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
		  AsymmetricKeyParameter privateKeyAsymKeyParam=PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
		  ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId,digAlgId).build(privateKeyAsymKeyParam);
					    
		  X509CertificateHolder holder=builder.build(sigGen);
		  result = holder.toASN1Structure();
		 		  
		  //byte publicKeyBytes1[] = xspec.getEncoded();
		  return result;
	  }
	  catch (Exception e) {
		  throw new RuntimeException("Cannot generate X509 certificate",e);
	  }
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy