package net.curisit.securis.utils; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import net.curisit.securis.SeCurisException; import net.curisit.securis.beans.LicenseBean; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * digital Signature utilities * * @author roberto */ public class SignatureHelper { private static final Logger LOG = LogManager.getLogger(SignatureHelper.class); private static String AUX = "hEDhryRjs2QRE"; private static SignatureHelper singleton = new SignatureHelper(); private static final String DEFAULT_ALGORITHM = "RSA"; public static final String SIGNATURE_GENERATION_ALGORITHM = "SHA256withRSA"; private SignatureHelper() { } public static SignatureHelper getInstance() { return singleton; } public void prepareSignature(Signature signature, LicenseBean licBean) throws SeCurisException { try { String aux = JsonUtils.toJSON(licBean) + AUX; signature.update(JsonUtils.toJSON(licBean).getBytes("utf-8")); signature.update(AUX.getBytes("utf-8")); } catch (SignatureException | UnsupportedEncodingException e) { throw new SeCurisException("Error generating or validating signature", e); } } public void validateSignature(LicenseBean licBean) throws SeCurisException { Signature signature; try { signature = Signature.getInstance(SIGNATURE_GENERATION_ALGORITHM); signature.initVerify(generatePublicKey()); prepareSignature(signature, licBean); if (signature.verify(Base64.decodeBase64(licBean.getSignature()))) return; } catch (NoSuchAlgorithmException e) { LOG.error("Error validating license for " + licBean, e); } catch (InvalidKeyException e) { LOG.error("Error validating license for " + licBean, e); } catch (InvalidKeySpecException e) { LOG.error("Error validating license for " + licBean, e); } catch (IOException e) { LOG.error("Error validating license for " + licBean, e); } catch (SignatureException e) { LOG.error("Error validating license for " + licBean, e); } throw new SeCurisException("License could not be validated"); } private static final String DEFAULT_PUB_KEY_RESOURCE = "/securis_key.pub"; private PublicKey generatePublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { String pubKeyFilePath = System.getenv("SECURIS_PUBLIC_KEY_FILE"); if (pubKeyFilePath == null) pubKeyFilePath = Params.get(Params.KEYS.PUBLIC_KEY_FILE); String pubKeyBase64 = null; if (pubKeyFilePath != null) { File pubKeyFile = new File(pubKeyFilePath); if (pubKeyFile.exists()) { pubKeyBase64 = FileUtils.readFileToString(pubKeyFile); } } if (pubKeyBase64 == null) { pubKeyBase64 = IOUtils.toString(this.getClass().getResourceAsStream(DEFAULT_PUB_KEY_RESOURCE), "utf-8"); } return generatePublicKey(pubKeyBase64); } private PublicKey generatePublicKey(String pubKeyBase64) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { if (pubKeyBase64.startsWith("-----BEGIN")) { int from = pubKeyBase64.indexOf('\n'); int to = pubKeyBase64.indexOf("-----END", from); pubKeyBase64 = pubKeyBase64.substring(from, to); } KeyFactory keyFactory = KeyFactory.getInstance(DEFAULT_ALGORITHM); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(pubKeyBase64)); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); return publicKey; } private PublicKey generatePublicKey(File pubKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { return generatePublicKey(FileUtils.readFileToString(pubKeyFile)); } public PrivateKey generatePrivateKey(File privateKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { String privKeyBase64 = FileUtils.readFileToString(privateKeyFile); if (privKeyBase64.startsWith("-----BEGIN")) { int from = privKeyBase64.indexOf('\n'); int to = privKeyBase64.indexOf("-----END", from); privKeyBase64 = privKeyBase64.substring(from, to); } KeyFactory keyFactory = KeyFactory.getInstance(DEFAULT_ALGORITHM); PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privKeyBase64)); PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); return privateKey; } public KeyPair generateKeyPair(File privateKeyFile, File publicKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { PublicKey publicKey = generatePublicKey(publicKeyFile); PrivateKey privateKey = generatePrivateKey(privateKeyFile); KeyPair kp = new KeyPair(publicKey, privateKey); return kp; } static { byte[] s = new byte[] { 64, -31, -81, 36, 99, -77, 100, 17, 16, -119, 31, 72, 123, -88, -32, 51, 39, -96, -35, 116, -65, 8, 41, -119, -108, -34, 41, 19, 26, -102, -16, -120, -96, 1, -5, -26, -13, 61, -121, 94, 59, 54, 110, 110, -55, 127, -106 }; AUX = Base64.encodeBase64String(s); } }