package br.com.citframework.util.cripto; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.cert.Certificate; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; public class CriptoSignedUtil { private static final String hexDigits = "0123456789abcdef"; public static SignedInfo generateStringToSend(final String pathJKSPK, final String pathJKSSK, final String txt) throws Exception { final File cert = new File(pathJKSPK); final String alias = "citsmart"; final String pwd = "c3ntr@lit"; final File certSK = new File(pathJKSSK); final String aliasSK = "citsmartcripto"; final String pwdSK = "c3ntr@lit123"; final PrivateKey privateKey = getPrivateKeyFromFile(cert, alias, pwd); final PublicKey publicKey = getPublicKeyFromFile(cert, alias, pwd); final SecretKey secretkey = getSecretKeyFromFile(certSK, aliasSK, pwdSK); final byte[] txtAssinado = createSignature(privateKey, txt.getBytes()); final byte[] txtCripto = cript(publicKey, secretkey, txt.getBytes()); final String hexStrMsg = byteArrayToHexString(txtCripto); final SignedInfo signedInfo = new SignedInfo(); signedInfo.setStrCripto(hexStrMsg); signedInfo.setStrSigned(byteArrayToHexString(txtAssinado)); return signedInfo; } public static String translateStringReceive(final String pathJKSPK, final String pathJKSSK, final String txtCriptoAndSigned, final String txtAssinado) throws Exception { final File cert = new File(pathJKSPK); final String alias = "citsmart"; final String pwd = "c3ntr@lit"; final File certSK = new File(pathJKSSK); final String aliasSK = "citsmartcripto"; final String pwdSK = "c3ntr@lit123"; final PrivateKey privateKey = getPrivateKeyFromFile(cert, alias, pwd); final PublicKey publicKey = getPublicKeyFromFile(cert, alias, pwd); final SecretKey secretkey = getSecretKeyFromFile(certSK, aliasSK, pwdSK); final byte[] txtDecripto = decript(publicKey, privateKey, secretkey, hexStringToByteArray(txtCriptoAndSigned)); if (verifySignature(publicKey, txtDecripto, hexStringToByteArray(txtAssinado))) { return new String(txtDecripto); } else { return "FAIL - ASSINATURA INVALIDA!"; } } public static PrivateKey getPrivateKeyFromFile(final File cert, final String alias, final String password) throws Exception { final KeyStore ks = KeyStore.getInstance("JKS"); final char[] pwd = password.toCharArray(); final InputStream is = new FileInputStream(cert); ks.load(is, pwd); is.close(); final Key key = ks.getKey(alias, pwd); if (key instanceof PrivateKey) { return (PrivateKey) key; } return null; } /** * Extrai a chave p�blica do arquivo. */ public static PublicKey getPublicKeyFromFile(final File cert, final String alias, final String password) throws Exception { final KeyStore ks = KeyStore.getInstance("JKS"); final char[] pwd = password.toCharArray(); final InputStream is = new FileInputStream(cert); ks.load(is, pwd); ks.getKey(alias, pwd); final Certificate c = ks.getCertificate(alias); final PublicKey p = c.getPublicKey(); return p; } /** * Extrai a chave p�blica do arquivo. */ public static SecretKey getSecretKeyFromFile(final File cert, final String alias, final String password) throws Exception { final KeyStore ks = KeyStore.getInstance("JCEKS"); final char[] pwd = password.toCharArray(); final InputStream is = new FileInputStream(cert); ks.load(is, pwd); final Key key = ks.getKey(alias, pwd); if (key instanceof SecretKey) { return (SecretKey) key; } return null; } /** * Retorna a assinatura para o buffer de bytes, usando a chave privada. * * @param key * PrivateKey * @param buffer * Array de bytes a ser assinado. */ public static byte[] createSignature(final PrivateKey key, final byte[] buffer) throws Exception { final Signature sig = Signature.getInstance("MD5withRSA"); sig.initSign(key); sig.update(buffer, 0, buffer.length); return sig.sign(); } /** * Verifica a assinatura para o buffer de bytes, usando a chave p�blica. * * @param key * PublicKey * @param buffer * Array de bytes a ser verficado. * @param sgined * Array de bytes assinado (encriptado) a ser verficado. */ public static boolean verifySignature(final PublicKey key, final byte[] buffer, final byte[] signed) throws Exception { final Signature sig = Signature.getInstance("MD5withRSA"); sig.initVerify(key); sig.update(buffer, 0, buffer.length); return sig.verify(signed); } /** * Converte um array de byte em uma representa��o, em String, de seus * hexadecimais. */ public static String txt2Hexa(final byte[] bytes) { if (bytes == null) { return null; } final String hexDigits = "0123456789abcdef"; final StringBuilder sbuffer = new StringBuilder(); for (final byte b : bytes) { final int j = b & 0xFF; sbuffer.append(hexDigits.charAt(j / 16)); sbuffer.append(hexDigits.charAt(j % 16)); } return sbuffer.toString(); } public static byte[] generateWrapKey(final PublicKey publicKey, final Cipher cipher, final SecretKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException { final byte[] wrappedKey = cipher.wrap(key); return wrappedKey; } public static byte[] cript(final PublicKey publicKey, final SecretKey secretkey, final byte[] msg) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, ShortBufferException, BadPaddingException { final Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, secretkey); final int blockSize = cipher.getBlockSize(); final int outputSize = cipher.getOutputSize(blockSize); byte[] outBytes = new byte[outputSize];; outBytes = cipher.doFinal(msg, 0, msg.length); return outBytes; } public static byte[] decript(final PublicKey publicKey, final PrivateKey privateKey, final SecretKey secretkey, final byte[] msgCripto) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, ShortBufferException, BadPaddingException { final Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, secretkey); final int blockSize = cipher.getBlockSize(); final int outputSize = cipher.getOutputSize(blockSize); byte[] outBytes = new byte[outputSize];; outBytes = cipher.doFinal(msgCripto, 0, msgCripto.length); return outBytes; } /** * Converte o array de bytes em uma representa��o hexadecimal. * * @param input * - O array de bytes a ser convertido. * @return Uma String com a representa��o hexa do array */ public static String byteArrayToHexString(final byte[] b) { final StringBuilder buf = new StringBuilder(); for (final byte element : b) { final int j = element & 0xFF; buf.append(hexDigits.charAt(j / 16)); buf.append(hexDigits.charAt(j % 16)); } return buf.toString(); } /** * Converte uma String hexa no array de bytes correspondente. * * @param hexa * - A String hexa * @return O vetor de bytes * @throws IllegalArgumentException * - Caso a String n�o sej auma representa��o haxadecimal v�lida */ public static byte[] hexStringToByteArray(final String hexa) throws IllegalArgumentException { // verifica se a String possui uma quantidade par de elementos if (hexa.length() % 2 != 0) { throw new IllegalArgumentException("String hexa inv�lida"); } final byte[] b = new byte[hexa.length() / 2]; for (int i = 0; i < hexa.length(); i += 2) { b[i / 2] = (byte) (hexDigits.indexOf(hexa.charAt(i)) << 4 | hexDigits.indexOf(hexa.charAt(i + 1))); } return b; } }