
com.identityx.clientSDK.base.KeyHelper Maven / Gradle / Ivy
/*
* 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.io.StringWriter;
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;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
/**
* 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 static final String beginKeyString = "-----BEGIN PUBLIC KEY-----\n\r";
//public static final String endKeyString = "\n\r-----END PUBLIC KEY-----";
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 = null;
//String publicKey = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
//String publicKey = Base64.encodeBase64String(generateCertificate(cn).getEncoded());
byte[] publicBytes = keyPair.getPublic().getEncoded();
try (StringWriter pemStrWriter = new StringWriter()) {
try (PemWriter pemWriter = new PemWriter(pemStrWriter)) {
pemWriter.writeObject(new PemObject("PUBLIC KEY", publicBytes));
pemWriter.flush();
publicKey = pemStrWriter.toString();
}
}
return publicKey;
/*
String publicKey = beginKeyString + Base64.encodeBase64String(x509EncodedPublicKey) + endKeyString;
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/ECB/OAEPWithSHA1AndMGF1Padding");
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