cookie encryption - java

how to encrypt cookies as it accepts only US-ASCII characters? when i use below code, it generates characters out of US_ASCII. how to limit encrypted characters not to go out of US_ASCII?
key = KeyGenerator.getInstance(algorithm).generateKey();
cipher = Cipher.getInstance("DESede");
messageSource.getMessage("encryption.algorithm",null,localeUtil.getLocale());
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] outputBytes = cipher.doFinal(input.getBytes());

Firstly: don't use String.getBytes without specifying an encoding, preferably something which can handle all of Unicode, such as UTF-8.
Secondly: the code you've given doesn't generate characters at all - it generates bytes. You mustn't treat those bytes as if they're encoded text - they're not. Instead, you should convert them to base64, e.g. with Apache Commons Codec or this public domain code.
Then when you need to decrypt, you simply reverse all the steps - convert back from base64 to binary, decrypt, and then create a string with new String(decryptedBytes, "UTF-8") (or whatever encoding you decided to use).

public static final String CHARSET = "ISO-8859-1";
String text = "Ángel";
String encodedText = new String(Base64.encodeBase64(text.getBytes(CHARSET)));
String decodedText = new String(Base64.decodeBase64(encodedText.getBytes(CHARSET)))
In addition to Jon's answer, you can view the available encodings here:
http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html

Related

Simple encryption of an email address that will be in my querystring

The goal of this is not for security, but for obscurity so the casual user will not be able to determine what the email address is.
I don't want to display an email address in the URL like:
www.example.com/?id=johnsmith#example.com
I would like to encrypt the email address, with the goal of:
the encrypted text should be encodable to be in a querystring
the length should be as short as possible
should not be easily decryptable e.g. using md5
I can decrypt the value back
Can someone suggest an ecryption algorith that would meet the above criteria?
When you talk about encryption you would have bytes, and not characters.
Bu you can encode those bytes as characters using Base64.
For example:
import javax.xml.bind.DatatypeConverter;
// Encrypt if you really need to encrypt it
// I am assuming you have a method that receive a String, encrypt it and return the byte[] encrypted.
// If you don't know how to encrypt, just ask a new question about how to do it in Java.
byte[] b = encrypt( "email#example.com" );
String encoded = DatatypeConverter.printBase64Binary( b );
// Otherwise, just encode it
b = "email.example.com".getBytes(java.nio.charset.StandardCharsets.UTF_8);
encoded = DatatypeConverter.printBase64Binary( b );
If your aim is not to deal with Security aspect of it then you can achieve it through Base64 encoding and decoding of String
final String encodedValue = new BASE64Encoder().encode("johnsmith#example.com".getBytes());
System.out.println("encodedValue = "+encodedValue );
final String decodedValue = new String(new BASE64Decoder().decodeBuffer(encodedValue));
System.out.println("decodedValue = "+decodedValue);

How to decode base64 in java

I am getting a base64encoded xml data in webservice response and I want to decode it in Java .
I tried org.apache.commons.codec.binary.Base64;
byte bytesEncoded[] = base64encodedStringfromWebservice.getBytes();
// Decrypt data on other side, by processing encoded data
byte[] valueDecoded= Base64.decodeBase64(bytesEncoded );
System.out.println("Decoded value is " + new String(valueDecoded));
but still some characters like (< , />) are not getting decoded properly .
Please suggest how to decode it correctly?
The getBytes method from String is platform specific. You need to specify an encoding, and later use that same encoding to decode the string. You can just use UTF8.
You also need to do the steps in reverse order: string -> base64 -> raw utf8 bytes -> base64 -> string
// ENCODE data
byte bytesEncoded[] = base64encodedStringfromWebservice.getBytes("UTF8");
// DECODE data on other side, by processing encoded data
String base64encodedStringfromWebservice = new String(bytesEncoded, "UTF8");
byte[] valueDecoded = Base64.decodeBase64(base64encodedStringfromWebservice);
System.out.println("Decoded value is " + new String(valueDecoded));
Try specifiying the charset you are using. for example, utf-8, and as you can see here: Decoding a Base64 string in Java
byte[] valueDecoded= Base64.decodeBase64(bytesEncoded);
System.out.println("Decoded value is " + new String(valueDecoded, "UTF-8"));

What is the target charset when I encrypt a string with Cipher and Base64.Encoder?

I'm trying to accommodate encrypted tokens in a DSL I'm designing (i.e. I need a char to be used as delimiter). The encoder.encodeToString(...) docs says it uses the ISO-8859-1 charset. But when I encrypt a sampling of texts, it looks like it's not using all of the ISO-8859-1 charset, instead upper/lower-case and some symbols, and not certain punctuation and accented chars. What am I missing about this encodeToString() call and what is the final char domain?
//import java.util.Base64;
//import javax.crypto.Cipher;
//import javax.crypto.SecretKey;
static Cipher cipher;
public static String decrypt(String encryptedText, SecretKey secretKey) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
byte[] encryptedTextByte = decoder.decode(encryptedText);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedByte = cipher.doFinal(encryptedTextByte);
String decryptedText = new String(decryptedByte);
return decryptedText;
}
String has a constructor with charset; otherwise the default OS charset is taken.
new String(decryptedByte, StandardCharsets.ISO_8859_1);
As there often is a mix-up of Latin-1 (ISO-8859-1) with Windows Latin-1 (Windows-1252) you might try "Windows-1252" too.
Base64 is named just so because it uses 64 characters from the ASCII table. The encoding used should not matter as long as it is compatible with ASCII.
If you want to use more than 64 characters you will have to use a different encoding.
Encryption returns bytes, no matter the encryption is.
I personally use the following function to convert from decrypted bytes to string:
public static String getStringFromBytes(byte[] data) {
StringBuilder sb = new StringBuilder();
if (data != null && data.length > 0) {
for (byte b : data) {
sb.append((char) (b));
}
}
return sb.toString();
}
Read the document line carefully:
This method first encodes all input bytes into a base64 encoded byte
array and then constructs a new String by using the encoded byte array
and the ISO-8859-1 charset.
This means 2 things:
Encoding scheme used is Base64, that's the reason you can not getting expected output because ISO-8859-1 is not used as encoding scheme.
ISO-8859-1 is only used as charset reference for constructing String.
Base64 class give your encoders and decoders for the Base64 encoding scheme, so if you are using its encoders and decoders then output will be encoded/decoded using Base64 encoding scheme.
This class consists exclusively of static methods for obtaining
encoders and decoders for the Base64 encoding scheme.
So, what you need is to properly encode your byte array using some encoding scheme - UTF-8 or ISO-8859-1.
I would personally recommend using "UTF-8" because it is widely used + it encodes all ASCII and some Latin character in 1 byte, Unicode other BMP character using 2 byte and Unicode supplementary characters using 4 bytes. So, it is not space consuming for all ASCII and some Latin character + ability to encode all Unicode characters.
There are many ways you can find to encode your String using desired encoding scheme, an example below:
byte[] byteArr = new byte[3];
String decodeText = new String(byteArr);
Charset.forName("UTF-8").encode(decodeText);

Convert byte[] to String Java Android Encryption

I am using the JNCryptor library to encrypt a string before sending it to my server as an encrypted string. Here is my code:
String teststring = "Hello World";
JNCryptor cryptor = new AES256JNCryptor();
byte[] plaintext = teststring.getBytes();
String password = "test";
try {
byte[] ciphertext = cryptor.encryptData(plaintext, password.toCharArray());
String a = new String(ciphertext);
return a;
} catch (CryptorException e) {
// Something went wrong
e.printStackTrace();
return "0";
}
However, when I send my string "a" to the server, it has a bunch of unrecognizable characters. I read an explanation
regarding this:
String is not a suitable container for binary data and ciphertext is
binary data. For any given character encoding not all bytes and byte
sequences represents characters and when an un-representable byte or
sequence is found it is converted to some error character. Obviously
this error character cannot be converted back to a unique byte or byte
sequence (it is a many->one mapping).
Is this advice correct? In that case, how do I convert the byte[] to a string correctly? So that I can readably store it on my server?
There is no standard way for converting from a byte array to a string. You have to encode the byte array. A common way to do this is base64 encoding.
For an explanation of how base64 encoding works: http://en.wikipedia.org/wiki/Base64
Then once it gets to your server, base64 decode it back into your original byte array and store it, done!

String decrypted by vb.net function is different than the original String encrypted by java function

I have an Android app that uses a webservice in an asp.net web application. This web service requires a username and encrypted password.
The problem is that the password decrypted by the vb.net function is not the same that the original password encrypted by the java function.
These are the functions:
java
public String encrypt(String password, String key, String VecI) throws GeneralSecurityException, UnsupportedEncodingException{
byte[] sessionKey = key.getBytes();
byte[] iv = VecI.getBytes() ;
byte[] plaintext = password.getBytes();
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "DES"), new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext);
String resp = ciphertext.toString();
return resp;
}
vb.net
Public Shared Function decrypt(Byval encrypted_password As String, ByVal key As String, ByVal VecI As String) As String
Dim plaintext() As Byte= Convert.FromBase64String(encrypted_password)
Dim keys() As Byte = Encoding.ASCII.GetBytes(key)
Dim memdata As New MemoryStream
Dim transforma As ICryptoTransform
Dim des As New DESCryptoServiceProvider
des.Mode = CipherMode.CBC
transforma = des.CreateEncryptor(keys, Encoding.ASCII.GetBytes(VecI))
Dim encstream As New CryptoStream(memdata, transforma, CryptoStreamMode.Write)
encstream.Write(plaintext, 0, plaintext.Length)
encstream.FlushFinalBlock()
encstream.Close()
Return Encoding.ASCII.GetString(memdata.ToArray)
End Function
Please, help me.
Thank`s.
Server side you're expecting a Base64 encoded string, which you're then converting to a byte array:
Dim plaintext() As Byte= Convert.FromBase64String(encrypted_password)
You should be doing the opposite of this on Android (converting the byte array to a Base64 string). Instead you're just calling toString on a byte[], which definitely won't give you what you want.
You can get the Base64 encoded string from your byte array as follows:
String resp = Base64.encode(cipherText, Base64.DEFAULT);
You can have a look at the Base64 docs for more information. You may have to play around with the flags supplied.
Another thing to consider is the fact that you're expecting everything to be in ASCII encoding. String.getBytes() returns characters encoded using the systems default charset. Passwords may be input using non-ASCII characters, such as é or ¥, and this could introduce subtle bugs. I'd recommend switching everything over to UTF-8 - server-side and client side (that means changing getBytes() to getBytes("UTF-8"), and Encoding.ASCII to Encoding.UTF8).
As an aside, creating a String from a byte array in Java is done using new String(someByteArray, "UTF-8") - or whatever the encoding you're using is.

Categories