/*
* Demoiselle Framework
* Copyright (C) 2013 SERPRO
* ----------------------------------------------------------------------------
* This file is part of Demoiselle Framework.
*
* Demoiselle Framework is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License version 3
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License version 3
* along with this program; if not, see <http://www.gnu.org/licenses/>
* or write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301, USA.
* ----------------------------------------------------------------------------
* Este arquivo é parte do Framework Demoiselle.
*
* O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou
* modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação
* do Software Livre (FSF).
*
* Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA
* GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou
* APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português
* para maiores detalhes.
*
* Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título
* "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/>
* ou escreva para a Fundação do Software Livre (FSF) Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA.
*/
package br.gov.frameworkdemoiselle.behave.integration.alm.autenticator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.MessageDigest;
public class Cipher {
public static final String ENCONDING = "ISO-8859-1";
/**
* Descriptografa uma mensagem a partir de uma chave
* @param content mensagem a ser descriptografada
* @param key chave
* @return mensagem descriptografada
*/
public static String decript(String content, String key) {
return cript(content, key, 'D');
}
/**
* Criptografa uma mensagem a partir de uma chave
* @param content mensagem a ser criptografada
* @param key chave
* @return mensagem criptografada
*/
public static String cript(String content, String key) {
return cript(content, key, 'C');
}
private static int[] RamdomKey() {
int[] ret = new int[32];
int valor;
int cont = 0;
for (int ct = 0; ct < 32; ct++) {
ret[ct] = 0;
}
while (true) {
valor = (int) (Math.random() * 256);
ret[cont % 32] = (ret[cont % 32] + valor) % 256;
cont++;
if (cont == 3200) {
break;
}
}
return ret;
}
private static String cript(String content, String key, char mode) {
String rt = null;
try {
if (key == null){
throw new RuntimeException("chave vazia");
}
if (content == null){
throw new RuntimeException("conteudo vazio");
}
InputStream in = new ByteArrayInputStream(content.getBytes(ENCONDING));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int[] ch = new int[32];
ch = Transform(stringHexa(makeHash(key, "SHA-256")));
int cont = 0;
String tmp = "";
int op = 1;
if (mode == 'C' || mode == 'c')
op = 1;
else
op = -1;
int x;
int[] valores = new int[32];
String xValores = "";
if (op == 1) { // CIFRAGEM
valores = RamdomKey();
xValores = toString(valores);
for (int pag = 0; pag < 32; pag++) {
x = (ch[pag] + valores[pag]);
if (x > 255) {
x = x - 256;
}
if (x < 0) {
x = x + 256;
}
out.write(x);
}
} else { // DECIFRAGEM
for (int pag = 0; pag < 32; pag++) {
x = in.read();
x = x - ch[pag];
if (x > 255) {
x = x - 256;
}
if (x < 0) {
x = x + 256;
}
valores[pag] = x;
}
xValores = toString(valores);
}
// Calcular nova sequencia da Chave!!!
cont = 0;
tmp = key;
key = toString(ch);
ch = Transform(stringHexa(makeHash(key + tmp, "SHA-256")));
tmp = xValores;
xValores = toString(valores);
valores = Transform(stringHexa(makeHash(xValores + tmp, "SHA-256")));
if (op == 1) {
// Cifragem do arquivo...
while ((x = in.read()) != -1) {
x = (x + ch[cont] + valores[cont]) % 256;
++cont;
out.write(x);
// Calcular nova sequencia da Chave!!!
if (cont > 31) {
cont = 0;
tmp = key;
key = toString(ch);
ch = Transform(stringHexa(makeHash(key + tmp, "SHA-256")));
tmp = xValores;
xValores = toString(valores);
valores = Transform(stringHexa(makeHash(xValores + tmp, "SHA-256")));
}
}
} else {
while ((x = in.read()) != -1) {
x = x - ((ch[cont] + valores[cont]) % 256);
++cont;
if (x < 0) {
x = x + 256;
}
out.write(x);
if (cont > 31) {
cont = 0;
tmp = key;
key = toString(ch);
ch = Transform(stringHexa(makeHash(key + tmp, "SHA-256")));
tmp = xValores;
xValores = toString(valores);
valores = Transform(stringHexa(makeHash(xValores + tmp, "SHA-256")));
}
}
}
in.close();
rt = out.toString(ENCONDING);
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
return rt;
}
private static byte[] makeHash(String content, String algor) {
try {
MessageDigest md = MessageDigest.getInstance(algor);
md.update(content.getBytes(ENCONDING));
return md.digest();
} catch (Exception e) {
throw new RuntimeException("erro makeHash");
}
}
private static String stringHexa(byte[] bytes) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
int parteAlta = ((bytes[i] >> 4) & 0xf) << 4;
int parteBaixa = bytes[i] & 0xf;
if (parteAlta == 0)
s.append('0');
s.append(Integer.toHexString(parteAlta | parteBaixa));
}
if (s.toString().length() != 64) {
throw new RuntimeException("erro com SHA-256");
}
return s.toString();
}
private static int[] Transform(String input) {
int[] ret = new int[32];
int tam = input.length() - 1;
int cont = 0;
for (int ct = 0; ct < tam; ct = ct + 2) {
int valor = 0, valor2 = 0;
char r;
int num, ct2;
char[] car = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
r = input.charAt(ct);
num = 0;
ct2 = 0;
while (ct2 < 16) {
num = (r == car[ct2]) ? ct2 * 16 : 0;
valor = valor + num;
++ct2;
}
r = input.charAt(ct + 1);
num = 0;
ct2 = 0;
while (ct2 < 16) {
num = (r == car[ct2]) ? ct2 : 0;
valor2 = valor2 + num;
++ct2;
}
ret[cont] = valor + valor2;
++cont;
}
return ret;
}
private static String toString(int[] entrada) {
String ret = "";
int tam = entrada.length;
for (int ct = 0; ct < tam; ct++) {
ret = ret + (char) entrada[ct];
}
if (ret.length() != 32) {
throw new RuntimeException("Erro inesperado!");
}
return ret;
}
}