Jump to content

Encode String->byte[] e byte[]->String


Ang3lo
 Share

Recommended Posts

Boa noite a todos,

Tenho de passar uma String para o formato byte[] e depois tenho de fazer o contrario, isto para cifrar umas mensagens com o RSA.

Para fazer este trabalho estou a usar os seguintes métodos :

    public static String encodeBASE64(byte[] bytes)
    {
        BASE64Encoder b64 = new BASE64Encoder();
        String aux = b64.encode(bytes);
        return aux;
    }

    public static byte[] decodeBASE64(String text) throws IOException
    {
        BASE64Decoder b64 = new BASE64Decoder();
        byte[] aux = b64.decodeBuffer(text);
        return aux;
    }

O problema é com os espaços e restantes símbolos que são todos "convertido" para /////

Se passar esta String "Olaaaaaa mundoooo !!!!!" para byte[]

e depois voltar a fazer o processo inverso obtenho o seguinte output "Olaaaaaa/mundoooo//////"

Alguém sabe como posso dar a volta a este problema?

Obrigado

Link to comment
Share on other sites

Tens que usar a conversão para Base 64? É que se só precisas de um byte[] para poderes fazer a encriptação RSA, podes usar as funções da classe String, mais especificamente o construtor que recebe byte[] e o método getBytes.

Exemplo:

String test = "ola";
byte [] buffer = test.getBytes("utf-8");
//byte[] para String
String result = new String(buffer, "utf-8");

Já agora, pode ser que te ajude: http://webcache.googleusercontent.com/search?q=cache:eYio3isvp7wJ:72.5.124.102/thread.jspa%3FthreadID%3D5330679%26tstart%3D703+base64encoder+spaces+to+slashes&cd=8&hl=en&ct=clnk

❝The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.❞- John Carmack on software patents

A list  of command line apps

Link to comment
Share on other sites

Tens que usar a conversão para Base 64? É que se só precisas de um byte[] para poderes fazer a encriptação RSA, podes usar as funções da classe String, mais especificamente o construtor que recebe byte[] e o método getBytes.

Exemplo:

String test = "ola";
byte [] buffer = test.getBytes("utf-8");
//byte[] para String
String result = new String(buffer, "utf-8");

Sim realmente tens razão se só precisa de RSA basta isso mesmo, é preciso recorrer ao Base64

I haven’t lost my mind; it’s backed up on DVD somewhere!

Link to comment
Share on other sites

As livrarias que estou a usar são as seguintes:

import sun.misc.BASE64Decoder;

import sun.misc.BASE64Encoder;

O problema dessa solução é o tamanho, porque ao decifrar a mensagem o método queixa-se "Data must not be longer than 128 bytes"

enquanto que quanto uso a solução que coloquei no primeiro post já não acontece isto. Como vou trocar as mensagem em String's tenho de as converter para usar o RSA.

Link to comment
Share on other sites

Se estás a usar a classe Cipher, vê isto para resolver o problema dos 128 bytes: http://stackoverflow.com/questions/295436/java-jce-decrypting-long-message-encrypted-with-rsa

❝The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.❞- John Carmack on software patents

A list  of command line apps

Link to comment
Share on other sites

Mesmo assim gera a mesma excepção. deixo aqui o codigo para verem se estou a fazer alguma coisa mal....

    public static String DecifraMensagem(PrivateKey chavePrivada, String cifra)
    {
        try
        {
            byte[] bytesCifra = null;
            byte[] bytesTextoLimpo = null;
            String textoLimpo = "";
            //bytesCifra = decodeBASE64(cifra);
            bytesCifra = cifra.getBytes("utf-8");

            //parte onde se decifra a mensagem
            Cipher rsacf = Cipher.getInstance("RSA");
            rsacf.init(Cipher.DECRYPT_MODE, chavePrivada);
            rsacf.update(bytesCifra);
            bytesTextoLimpo = rsacf.doFinal();
            //textoLimpo = encodeBASE64(bytesTextoLimpo);
            textoLimpo = new String(bytesTextoLimpo, "utf-8");
            return textoLimpo;
        }

        catch(Exception e)
        {
            System.out.println(e.getMessage());
            return null;
        }
    }

Fiz o debug e o erro acontece no comando "            bytesTextoLimpo = rsacf.doFinal();    "

O "update" o que faz é preencher o objecto Cipher com os dados que lhe vou passando ate fazer o doFinal() certo?

Mas quando faço o doFinal() ele retorna tudo o que esta no objecto?

Obrigado

Link to comment
Share on other sites

De onde vem a String cifra? Que lhe estás a passar?

❝The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.❞- John Carmack on software patents

A list  of command line apps

Link to comment
Share on other sites

A String cifra para efeitos de teste é uma variável de classe que a esta a guardar, que provem do método cifrar.

public static String CifraMensagem(PublicKey chavePublica, String textoLimpo)
    {
        try
        {
            //byte[] bytesTextoLimpo = decodeBASE64(textoLimpo);
            byte[] bytesTextoLimpo = textoLimpo.getBytes("utf-8");
            byte[] bytesTextoCifrado = null;
            String textoCifrado = "";

            //parte onde se efectua a cifra do texto limpo
            Cipher rsacf = Cipher.getInstance("RSA");
            rsacf.init(Cipher.ENCRYPT_MODE, chavePublica);
            rsacf.update(bytesTextoLimpo);
            bytesTextoCifrado = rsacf.doFinal();
            //textoCifrado = encodeBASE64(bytesTextoCifrado);
            textoCifrado = new String(bytesTextoCifrado, "utf-8");
            return textoCifrado;
        }

        catch(Exception e)
        {
            System.out.println(e.getMessage());
            return null;
        }
    }

Aqui esta o método que retorna a cifra.

Link to comment
Share on other sites

Bem andava à procura de outra coisa mas tropecei nisto e talvez possa ajudar  😉

Atenção que não precisas de converter para base64 se vais cifrar a informação. Passas a informação em byte[] para cifrar e pronto, depois podes querer é serializar isso para um ficheiro e aí já dá jeito ser em base64.

Tens é de ter cuidado porque para cifrar algo tens de ter em atenção que o tamanho do que podes cifrar está dependente do tamanho da chave que usas:

http://www.owasp.org/index.php/Digital_Signature_Implementation_in_Java#Algorithm_for_Implementing_Digital_signature_using_RSA_Algorithm

A julgar pela excepção, deduzo que estejas a usar 1024 para o tamanho da chave RSA.

Portanto tens de cifrar o que queres em blocos de tamanho máximo ao permitido pela chave (o mesmo para decifrar).

Em base64 funcionou porque a informação que lhe passaste ficou suficientemente mais pequena, mas não vai funcionar a menos que possas garantir que a informação vai ser sempre menor ou igual a 128 (má escolha btw).

Aqui tens um exemplo feito à pressa mas que deve funcionar sem problemas de maior:

	
private static final int RSA_KEY_SIZE = 1024;
private static final int PRIVATE_KEY_LENGTH = 848;
private static final int PUBLIC_KEY_LENGTH = 216;
private static final int MAX_ENCRYPTION_SIZE = 117;
private static final int MAX_DECRYPTION_SIZE = 128;

public static byte[] encrypt(byte[] data, String key) throws IOException,
		NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
		NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
	BASE64Decoder b64d = new BASE64Decoder();
	byte[] keyBytes;
	Key keyObject;

	keyBytes = b64d.decodeBuffer(key);
	KeyFactory keyFacPub = KeyFactory.getInstance("RSA");
	if (key.length() > Keys.PUBLIC_KEY_LENGTH) {
		PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(keyBytes);
		keyObject = keyFacPub.generatePrivate(privSpec);
	} else {
		X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(keyBytes);
		keyObject = keyFacPub.generatePublic(pubSpec);
	}
	Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
	cipher.init(Cipher.ENCRYPT_MODE, keyObject);
	return cipherData(data, cipher, Keys.MAX_ENCRYPTION_SIZE);
}

public static byte[] decrypt(byte[] data, String key)
		throws GeneralSecurityException, IOException {

	Key keyObject;
	byte[] keyBytes = b64decoder.decodeBuffer(key);
	KeyFactory keyFacPub = KeyFactory.getInstance("RSA");
	if (key.length() > Keys.PUBLIC_KEY_LENGTH) {
		PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(keyBytes);
		keyObject = keyFacPub.generatePrivate(privSpec);
	} else {
		X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(keyBytes);
		keyObject = keyFacPub.generatePublic(pubSpec);
	}
	Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
	cipher.init(Cipher.DECRYPT_MODE, keyObject);
	return cipherData(data, cipher, Keys.MAX_DECRYPTION_SIZE));
}

private static byte[] cipherData(byte[] data, Cipher cipher, int dataChunkSize)
		throws IllegalBlockSizeException, BadPaddingException, IOException {
	ByteArrayOutputStream cipherText = new ByteArrayOutputStream();
	byte[] dataBuffer = new byte[dataChunkSize];
	byte[] cipherBuffer = null;

	ByteArrayInputStream dataStream = new ByteArrayInputStream(data);

	while (dataStream.available() > 0) {
		if (dataStream.available() < dataChunkSize) {
			dataBuffer = new byte[dataStream.available()];
			dataStream.read(dataBuffer, 0, dataStream.available());
			cipherBuffer = cipher.doFinal(dataBuffer);
			cipherText.write(cipherBuffer);
			break;
		}

		dataStream.read(dataBuffer, 0, dataChunkSize);
		cipherBuffer = cipher.doFinal(dataBuffer);
		cipherText.write(cipherBuffer);
	}
	return cipherText.toByteArray(); // cipherBuffer;
}

Como podes ver vou cifrando/decifrando tudo até que o bocado que falte cifrar seja mais pequeno e portanto o buffer ajusta-se ao tamanho do ultimo bloco.

Ah e quanto ao problema com as strings e os caracteres marados, experimenta usar o trim(), que agora já não deverá ser preciso mas saber não faz mal a ninguém (o que também não é sempre verdade lol).

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.