Hi Niranda, I've attached a sample Java class here that you can refer to get the private key and public key. I've written this for signing a JWT but you can use the same code segments for your scenario as well.
Thanks, TharinduE On Fri, Oct 7, 2016 at 8:54 AM, Danushka Fernando <danush...@wso2.com> wrote: > AFAIK SAML Token is signed using the tenant keystore. You can use the > org.wso2.carbon.core.util.KeyStoreManager to achieve that. There are > getDefaultPrivateKey and getDefaultPublicKey which will give you the > default keys of the keystore. > > Thanks & Regards > Danushka Fernando > Senior Software Engineer > WSO2 inc. http://wso2.com/ > Mobile : +94716332729 > > On Thu, Oct 6, 2016 at 5:38 PM, Niranda Perera <nira...@wso2.com> wrote: > >> Hi, >> >> I am trying to create a SAML response manually. This is a special type of >> SAML response named SAML NameIdResponse and I am trying to set a signature >> in it. >> >> I am trying to create a signature element, as mentioned here [1]. >> >> For me to do this, I need to access the private and public keys >> programatically. >> >> Could you please point me to a place where I could extract these >> information? >> >> Best >> >> [1] http://www.programcreek.com/java-api-examples/index.php? >> source_dir=saml-generator-master/src/main/java/com/rackspace >> /saml/SamlAssertionProducer.java >> >> -- >> *Niranda Perera* >> Software Engineer, WSO2 Inc. >> Mobile: +94-71-554-8430 >> Twitter: @n1r44 <https://twitter.com/N1R44> >> https://pythagoreanscript.wordpress.com/ >> >> _______________________________________________ >> Dev mailing list >> Dev@wso2.org >> http://wso2.org/cgi-bin/mailman/listinfo/dev >> >> > > _______________________________________________ > Dev mailing list > Dev@wso2.org > http://wso2.org/cgi-bin/mailman/listinfo/dev > > -- Tharindu Edirisinghe Senior Software Engineer | WSO2 Inc Platform Security Team Blog : tharindue.blogspot.com mobile : +94 775181586
package org.wso2.carbon.jwt.helper; import org.apache.axiom.util.base64.Base64Utils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.core.util.KeyStoreManager; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.service.RealmService; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.util.Calendar; import java.util.concurrent.ConcurrentHashMap; public class JWTHelper { private static Log log = LogFactory.getLog(JWTHelper.class); private static final String SHA256_WITH_RSA = "SHA256withRSA"; private static String signatureAlgorithm = SHA256_WITH_RSA; private static final String NONE = "NONE"; private static volatile long ttl = -1L; private static ConcurrentHashMap<Integer, Key> privateKeys = new ConcurrentHashMap<Integer, Key>(); private static ConcurrentHashMap<Integer, Certificate> publicCerts = new ConcurrentHashMap<Integer, Certificate>(); public static String generateJWT(String tenantDomain) throws Exception { String jwt = buildJWT(tenantDomain); log.info("JWT = " + jwt); return jwt; } /** * Method that generates the JWT. * * @return signed JWT token * @throws Exception */ private static String buildJWT(String tenantDomain) throws Exception { //generating expiring timestamp long currentTime = Calendar.getInstance().getTimeInMillis(); long expireIn = currentTime + 1000 * 60 * getTTL(); String jwtBody; String issuer = "wso2.org/appserver"; int tenantId = getTenantId(tenantDomain); //Sample JWT body //{"iss":"wso2.org/appserver","exp":1448299984841,"tenant_domain":"wso2.com","tenant_id":"1"} StringBuilder jwtBuilder = new StringBuilder(); jwtBuilder.append("{"); jwtBuilder.append("\"iss\":\""); jwtBuilder.append(issuer); jwtBuilder.append("\","); jwtBuilder.append("\"exp\":"); jwtBuilder.append(String.valueOf(expireIn)); jwtBuilder.append(","); jwtBuilder.append("\"tenant_domain\":\""); jwtBuilder.append(tenantDomain); jwtBuilder.append("\","); jwtBuilder.append("\"tenant_id\":\""); jwtBuilder.append(String.valueOf(tenantId)); jwtBuilder.append("\""); jwtBuilder.append("}"); jwtBody = jwtBuilder.toString(); String jwtHeader = null; //if signature algo==NONE, header without cert if (signatureAlgorithm.equals(NONE)) { jwtHeader = "{\"typ\":\"JWT\"}"; } else if (signatureAlgorithm.equals(SHA256_WITH_RSA)) { jwtHeader = addCertToHeader(tenantDomain); } String base64EncodedHeader = Base64Utils.encode(jwtHeader.getBytes()); String base64EncodedBody = Base64Utils.encode(jwtBody.getBytes()); if (signatureAlgorithm.equals(SHA256_WITH_RSA)) { String assertion = base64EncodedHeader + "." + base64EncodedBody; //get the assertion signed byte[] signedAssertion = signJWT(assertion, tenantDomain); log.info("Signed assertion value : " + new String(signedAssertion)); String base64EncodedAssertion = Base64Utils.encode(signedAssertion); return base64EncodedHeader + "." + base64EncodedBody + "." + base64EncodedAssertion; } else { return base64EncodedHeader + "." + base64EncodedBody + "."; } } private static long getTTL() { if (ttl != -1) { return ttl; } synchronized (JWTHelper.class) { if (ttl != -1) { return ttl; } String ttlValue = "15"; //This can be read from a property if (ttlValue != null) { ttl = Long.parseLong(ttlValue); } else { ttl = 15L; } return ttl; } } private static byte[] signJWT(String assertion, String tenantDomain) throws Exception { try { //get tenantId int tenantId = getTenantId(tenantDomain); Key privateKey = null; if (!(privateKeys.containsKey(tenantId))) { //get tenant's key store manager KeyStoreManager tenantKSM = KeyStoreManager.getInstance(tenantId); if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { //derive key store name String ksName = tenantDomain.trim().replace(".", "-"); String jksName = ksName + ".jks"; //obtain private key //TODO: maintain a hash map with tenants' private keys after first initialization privateKey = tenantKSM.getPrivateKey(jksName, tenantDomain); } else { try { privateKey = tenantKSM.getDefaultPrivateKey(); } catch (Exception e) { log.error("Error while obtaining private key for super tenant", e); } } if (privateKey != null) { privateKeys.put(tenantId, privateKey); } } else { privateKey = privateKeys.get(tenantId); } //initialize signature with private key and algorithm Signature signature = Signature.getInstance(signatureAlgorithm); signature.initSign((PrivateKey) privateKey); //update signature with data to be signed byte[] dataInBytes = assertion.getBytes(); signature.update(dataInBytes); //sign the assertion and return the signature byte[] signedInfo = signature.sign(); return signedInfo; } catch (NoSuchAlgorithmException e) { String error = "Signature algorithm not found."; //do not log throw new Exception(error); } catch (InvalidKeyException e) { String error = "Invalid private key provided for the signature"; //do not log throw new Exception(error); } catch (SignatureException e) { String error = "Error in signature"; //do not log throw new Exception(error); } catch (Exception e) { //do not log throw new Exception(e.getMessage()); } } private static int getTenantId(String tenantDomain) throws Exception { try { RealmService realmService = JWTHelperDataHolder.getInstance().getRealmService(); int tenantId = realmService.getTenantManager().getTenantId(tenantDomain); return tenantId; } catch (UserStoreException e) { String error = "Error in obtaining tenantId from Domain"; //do not log throw new Exception(error); } } /** * Helper method to add public certificate to JWT_HEADER to signature verification. * * @param endUserName * @throws Exception */ private static String addCertToHeader(String tenantDomain) throws Exception { try { //get tenantId int tenantId = getTenantId(tenantDomain); Certificate publicCert = null; if (!(publicCerts.containsKey(tenantId))) { //get tenant's key store manager KeyStoreManager tenantKSM = KeyStoreManager.getInstance(tenantId); KeyStore keyStore = null; if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { //derive key store name String ksName = tenantDomain.trim().replace(".", "-"); String jksName = ksName + ".jks"; keyStore = tenantKSM.getKeyStore(jksName); publicCert = keyStore.getCertificate(tenantDomain); } else { publicCert = tenantKSM.getDefaultPrimaryCertificate(); } if (publicCert != null) { publicCerts.put(tenantId, publicCert); } } else { publicCert = publicCerts.get(tenantId); } //generate the SHA-1 thumbprint of the certificate //TODO: maintain a hashmap with tenants' pubkey thumbprints after first initialization MessageDigest digestValue = MessageDigest.getInstance("SHA-1"); byte[] der = publicCert.getEncoded(); digestValue.update(der); byte[] digestInBytes = digestValue.digest(); String publicCertThumbprint = hexify(digestInBytes); String base64EncodedThumbPrint = Base64Utils.encode(publicCertThumbprint.getBytes()); StringBuilder jwtHeader = new StringBuilder(); //Sample header //{"typ":"JWT", "alg":"SHA256withRSA", "x5t":"NmJmOGUxMzZlYjM2ZDRhNTZlYTA1YzdhZTRiOWE0NWI2M2JmOTc1ZA=="} jwtHeader.append("{\"typ\":\"JWT\","); jwtHeader.append("\"alg\":\""); jwtHeader.append(signatureAlgorithm); jwtHeader.append("\","); jwtHeader.append("\"x5t\":\""); jwtHeader.append(base64EncodedThumbPrint); jwtHeader.append("\""); jwtHeader.append("}"); return jwtHeader.toString(); } catch (KeyStoreException e) { String error = "Error in obtaining tenant's keystore"; throw new Exception(error); } catch (CertificateEncodingException e) { String error = "Error in generating public cert thumbprint"; throw new Exception(error); } catch (NoSuchAlgorithmException e) { String error = "Error in generating public cert thumbprint"; throw new Exception(error); } catch (Exception e) { String error = "Error in obtaining tenant's keystore"; throw new Exception(error); } } /** * Helper method to hexify a byte array. * * @param bytes * @return hexadecimal representation */ private static String hexify(byte bytes[]) { char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; StringBuffer buf = new StringBuffer(bytes.length * 2); for (int i = 0; i < bytes.length; ++i) { buf.append(hexDigits[(bytes[i] & 0xf0) >> 4]); buf.append(hexDigits[bytes[i] & 0x0f]); } return buf.toString(); } }
_______________________________________________ Dev mailing list Dev@wso2.org http://wso2.org/cgi-bin/mailman/listinfo/dev