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);
Related
I've got an encrypted string in PHP and need to send this in an HTTP request. So I decide to use Base64 encoding and URL encoding. The received is a Java module; but when I use the Base64 decoder, it shows me a completely different string. How can I get the original encrypted string back. I need actually to pick each character from that original string and use its corresponding ASCII code for decryption.
// PHP code
$encrypted = "©’Ÿ£ šd¤¨m";
$base64 = base64_encode($string);
$parameter = urlencode($base64);
// this returns eventually: qZKfo6CaZKSobQ%3D%3D
// Java code
// FYI: the variable "name" is a string that the Java software extracts from the posted data.
String base64 = java.net.URLDecoder.decode(name, "UTF-8");
byte[] bytes = java.util.Base64.getDecoder().decode(base64);
String encrypted = new String(bytes);
// This returns: ������d��m
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!
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.
I have a web application based on Java/Spring that uses Oracle 11g. Currently, the users authenticate via username/password directly against the system table SYS.USER$ on login.
This has to change, so we created a (regular) new table to store all the user data there. We inserted all existing passwords to the newly created table. However, the passwords seem to be encrypted/hashed in a way that's described by this site
One example: Once the user enters XXXXX, the database stores 07E4898C06DEF253.
I want to perform the authentication with the old passwords stored in the new (regular) table. My problem is that I don't know how to verify the existing passwords since I don't know exactly how they have been hashed/encrypted.
I played around with ora_hash and dbms_obfuscation_toolkit.DESDecrypt, but none of these gave me a correct result. I know the correct password for my user and I can see Oracle's generated value for this one, but I can't reproduce the way Oracle generally "handles" the password data.
Is there any way to solve this problem without resetting all passwords?
Adapting the Java implementation you linked to in a comment, which is close but isn't quite using the salt properly:
import java.security.MessageDigest;
import java.util.Formatter;
class Main{
public static String calculateHash(String password) throws Exception{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
String encodedPassword = "S:71752CE0530476A8B2E0DD218AE59CB71B211D7E1DB70EE23BFB23BDFD48";
// Convert password to bytes
byte[] bPassword = password.getBytes("UTF-8");
// Get salt from encoded password
String salt = encodedPassword.substring(42, 62);
System.out.println("Salt is " + salt);
// Convert salt from hex back to bytes
// based on http://stackoverflow.com/a/140861/266304
int len = salt.length();
byte[] bSalt = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
bSalt[i / 2] = (byte) ((Character.digit(salt.charAt(i), 16) << 4)
+ Character.digit(salt.charAt(i+1), 16));
}
// Add converted salt to password bytes
// based on http://stackoverflow.com/a/80503/266304
byte[] bData = new byte[bPassword.length + bSalt.length];
System.arraycopy(bPassword, 0, bData, 0, bPassword.length);
System.arraycopy(bSalt, 0, bData, bPassword.length, bSalt.length);
// Hash the final byte array
crypt.update(bData);
byte bHash[] = crypt.digest();
Formatter formatter = new Formatter();
for (byte b : bHash)
{
formatter.format("%02x", b);
}
System.out.println("Expected " + encodedPassword.substring(2,42));
return formatter.toString().toUpperCase();
}
public static void main(String[] args) throws Exception {
System.out.println("The result is " + calculateHash("ZK3002"));
}
}
Which gives output:
Salt is 1DB70EE23BFB23BDFD48
Expected 71752CE0530476A8B2E0DD218AE59CB71B211D7E
The result is 71752CE0530476A8B2E0DD218AE59CB71B211D7E
The PL/SQL version involves some conversion; dbms_crypto.hash() takes a RAW argument, so you have to convert the plain-text password to RAW, then concatenate the extracted salt - which is already hex. (In the PL/SQL version in Pete Finnigan's blog you may notice that he has an explicit hextoraw call, so I'm simplifying a bit). So the argument passed to dbms_crypto.hash for your example would be the hex (OK, raw) equivalent of ZK3002, which is 5A4B33303032, with the hex salt concatenated to that; so 5A4B333030321DB70EE23BFB23BDFD48.
For the Java version you pass a byte array, but that means you need to convert the salt extracted from the stored password back from hex before tacking it on to the password; and since it's unlikely to have a useful string representation you might as well put it straight into a byte array. So, convert the password to a byte array, convert the salt into a byte array, and stick the two arrays together. That then becomes the value you pass to MessageDigest.
You can compare the hash this produces with the Oracle-hashed version, skipping the initial S: and the embedded salt.
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