Well its embarrassing to ask this question despite having lot of articles related to this in web, but I could not figure it out.I am struck with this one.
I am encrypting a text in Android using AES/CBC/PKCS5 algorithm but I could not decrypt it in windows 8 appstore application.Here is my encryption code
public static String encrypt(String plainText,String password) throws Exception {
// convert key to bytes
byte[] keyBytes = password.getBytes("UTF-8");
// Use the first 16 bytes (or even less if key is shorter)
byte[] keyBytes16 = new byte[16];
System.arraycopy(keyBytes, 0, keyBytes16, 0,
Math.min(keyBytes.length, 16));
// convert plain text to bytes
byte[] plainBytes = plainText.getBytes("UTF-8");
// setup cipher
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes16, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16]; // initialization vector with all 0
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv));
// encrypt
byte[] encrypted = cipher.doFinal(plainBytes);
String encryptedString = Base64.encodeToString(
cipher.doFinal(plainBytes), Base64.NO_WRAP);
// encryptedString
return Base64.encodeToString(encrypted, Base64.NO_WRAP);
}
I am encrypting using the following code in windows 8 application
public string AES_Encrypt(string input, string pass)
{
SymmetricKeyAlgorithmProvider SAP = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
string encrypted = "";
try
{
byte[] test1 = System.Text.Encoding.UTF8.GetBytes(pass);
byte[] test2 = new byte[16];
for (int i = 0; i < test1.Length;i++ )
{
test2[i] = test1[i];
}
CryptographicKey key =
SAP.CreateSymmetricKey(CryptographicBuffer.CreateFromByteArray(test2));
IBuffer Buffer = CryptographicBuffer.CreateFromByteArray(System.Text.Encoding.UTF8.GetBytes(input));
encrypted = CryptographicBuffer.EncodeToBase64String(CryptographicEngine.Encrypt(key, Buffer, null));
return encrypted;
}
catch (Exception ex)
{
return null;
}
}
following is the decryption algo
public string AES_Decrypt(string input, string pass)
{
SymmetricKeyAlgorithmProvider SAP = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
string decrypted = "";
try
{
byte[] test1 = System.Text.Encoding.UTF8.GetBytes(pass);
byte[] test2 = new byte[16];
for (int i = 0; i < test1.Length;i++ )
{
test2[i] = test1[i];
}
CryptographicKey key =
SAP.CreateSymmetricKey(CryptographicBuffer.CreateFromByteArray(test2));
IBuffer Buffer = CryptographicBuffer.DecodeFromBase64String(input);
byte[] Decrypted;
CryptographicBuffer.CopyToByteArray(CryptographicEngine.Decrypt(key, Buffer, null), out Decrypted);
decrypted = System.Text.Encoding.UTF8.GetString(Decrypted, 0, Decrypted.Length);
return decrypted;
}
catch (Exception ex)
{
return null;
}
}
I know that there is something wrong with the IV being generated. If I give the Iv as null, the decryption algorithm generates some result(though it is wrong), If i give some values for IV, it throws an exception such as "Value does not fall within the expected range."
Any help is much appreciated.
I'm not sure about the transformation from Android to Windows but I noticed in the JAva you are using PKCS5 and in C# PKCS7.
Related
I am trying to encrypt in android and decrypt in ios.I am using AES.GCM encryption however when i try to decrypt the package in ios i get Aunthetication faliure message.Below is the code for ios decryption
func decryptData(decryptToData:Data,key:SymmetricKey)->String {
let combinedData = decryptToData // Previous sealed bo
let sealedBoxToOpen = try! AES.GCM.SealedBox(combined: decryptToData)
if let decryptedData = try? AES.GCM.open(sealedBoxToOpen, using: key) {
decryptedString = String(data: decryptedData, encoding: .utf8)!
print(decryptedString ?? "Failed")
} else {
print(CryptoKitError) // Ouch, doSomething() threw an error.
}
}
This is similar to iOS CryptoKit in Java but i am doing the other way around.
This is the android encryption code
public synchronized Map<String, String> encrypt(byte[] rawKey, byte[] rawData, #Nullable byte[] associatedData) throws StashDataEncryptionException {
byte[] rawEncryptionKey = null;
if (rawKey == null) {
SecureRandom secureRandom = new SecureRandom();
byte[] key = new byte[KEY_LENGTH_BYTE];
secureRandom.nextBytes(key);
rawEncryptionKey = key;
} else {
rawEncryptionKey = rawKey;
}
byte[] iv = null;
byte[] encrypted = null;
try {
iv = new byte[IV_LENGTH_BYTE];
secureRandom.nextBytes(iv);
final Cipher cipherEnc = getCipher();
cipherEnc.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(rawEncryptionKey, "AES"), new GCMParameterSpec(TAG_LENGTH_BIT, iv));
if (associatedData != null) {
cipherEnc.updateAAD(associatedData);
}
encrypted = cipherEnc.doFinal(rawData);
String base64Key = Base64.encodeToString(rawEncryptionKey, Base64.DEFAULT);
//concat all of it to a single message
ByteBuffer byteBuffer = ByteBuffer.allocate(1 + iv.length + encrypted.length);
byteBuffer.put((byte) iv.length);
byteBuffer.put(iv);
byteBuffer.put(encrypted);
byte[] cipherMessage = byteBuffer.array();
Map map = new HashMap<String, String>();
map.put(MAP_KEY, base64Key);
map.put(MAP_Byte_CONTENT, cipherMessage);
return map;
} catch (Exception e) {
throw new StashDataEncryptionException("could not encrypt data", e);
}
}
i checked the key,iv and tag lenght.Its same on the ios side as android
Hey there I played very long to day with this and I came up with a working Xcode playground demoing CryptoKit AES-GCM 256 encryption & decryption. I also had this error very often today but could solve it. You can clone my playgrounds repo and try it out, play with it:
https://github.com/Blackjacx/Playgrounds/blob/master/playgrounds/CryptoKit.playground/Contents.swift
Implementations will differ, enough to invalidate authenticated encryption.
Use an enterprise grade, cross platform compatible library like libsodium.
I have an application that encrypts files for storage purposes and decrypts them for uploading to our server. For the most part it works fine and the decrypted files we receive are good files.
However, on a semi-regular basis (one or two files out of a few hundred every few days) the decrypted files are corrupt. It's possible that the original files were corrupt as well and the issue was not in the encrypt/decrypt process, but this has occurred to different users who presumably would have made sure that the files weren't corrupt to begin with, but I don't know how to verify this as I do not have direct contact with our users.
I want to make sure that my code is not the source of the problem, or if there is something I can do to check that the files were safely encrypted/decrypted in the application to make sure all the files we receive are good.
What is strange is that I have an ExceptionManager class that sends me any exceptions that occur, and I do not receive any exceptions when these corrupt files get processed and uploaded, so I have no way of knowing what went wrong.
This is my Encrypt code:
static string aesTransform = "AES/CBC/PKCS5Padding"
public static bool EncryptFile(Context context, string fileLocation, ref string encryptedFileLocation)
{
bool success;
try
{
Log logger = new Log(context);
logger.Debug("starting encryption");
if (File.Exists(fileLocation))
{
encryptedFileLocation = (encryptedFileLocation ?? fileLocation) + ".aes";
using (FileStream fInput = File.Open(fileLocation, FileMode.Open))
using (FileStream fOutput = File.Open(encryptedFileLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
byte[] keyBytes = Encoding.UTF8.GetBytes(encryptKey);
SecretKeySpec key = new SecretKeySpec(keyBytes, 0, keyBytes.Length, "AES");
Cipher cipher = Cipher.GetInstance(aesTransform);
cipher.Init(CipherMode.EncryptMode, key, new IvParameterSpec(new byte[cipher.BlockSize]));
CipherOutputStream cos = new CipherOutputStream(fOutput, cipher);
byte[] buffer = new byte[1024];
int numBytesWritten = 0;
while ((numBytesWritten = fInput.Read(buffer, 0, buffer.Length)) > 0)
{
cos.Write(buffer, 0, numBytesWritten);
}
cos.Flush();
cos.Close();
}
logger.WriteLog(Log.LogType.Misc, fileLocation + " encrypted");
Delete(context, fileLocation);
}
success = true;
}
catch(Exception ex)
{
if (File.Exists(fileLocation) && File.Exists(encryptedFileLocation))
{
Delete(context, encryptedFileLocation);
}
if(encryptedFileLocation.EndsWith(".aes"))
{
encryptedFileLocation = encryptedFileLocation.Remove(encryptedFileLocation.ToUpper().LastIndexOf(".AES"));
}
ex.Data.Add("fileLocation", fileLocation);
ex.Data.Add("encryptedFileLocation", encryptedFileLocation);
ExceptionManager.ManageException(context, ex);
success = false;
}
return success;
}
And this is my Decrypt Code:
static string aesTransform = "AES/CBC/PKCS5Padding"
public static bool DecryptFile(Context context, string fileLocation, ref string decryptedFileLocation)
{
bool decrypted = false;
try
{
if (File.Exists(fileLocation))
{
if(fileLocation.ToUpper().EndsWith(".AES"))
{
decryptedFileLocation = fileLocation.Remove(fileLocation.ToUpper().LastIndexOf(".AES"));
}
else
{
decryptedFileLocation = fileLocation;
}
using (FileStream fInput = File.Open(fileLocation, FileMode.Open))
using (FileStream fOutput = File.Open(decryptedFileLocation, FileMode.OpenOrCreate))
{
FileInfo info = new FileInfo(fileLocation);
byte[] keyBytes = Encoding.UTF8.GetBytes(encryptKey);
SecretKeySpec key = new SecretKeySpec(keyBytes, 0, keyBytes.Length, "AES");
Cipher cipher = Cipher.GetInstance(aesTransform);
cipher.Init(CipherMode.DecryptMode, key, new IvParameterSpec(new byte[cipher.BlockSize]));
CipherInputStream cis = new CipherInputStream(fInput, cipher);
byte[] buffer = new byte[1024];
int numBytesWritten = 0;
while ((numBytesWritten = cis.Read(buffer, 0, buffer.Length)) > 0)
{
fOutput.Write(buffer, 0, numBytesWritten);
}
cis.Close();
decrypted = true;
Log logger = new Log(context);
logger.WriteLog(Log.LogType.Misc, fileLocation + " decrypted");
}
}
}
catch (Exception ex)
{
if (File.Exists(fileLocation) && File.Exists(decryptedFileLocation))
{
Delete(context, decryptedFileLocation);
}
decryptedFileLocation = fileLocation;
ex.Data.Add("fileLocation", fileLocation);
ExceptionManager.ManageException(context, ex);
decrypted = false;
}
return decrypted;
}
The encrypt key is identical for both Encrypt and Decrypt methods, both referencing a static string declared earlier in this class, so the keys match.
I want to send encrypted Sms data by using one key(public) for encryption and this sms wnat to decrypt by using different private key...specifically i want to use RSA algorithm scenario...
So can u tell me how to encrypt and decrypt data by using different keys in android...
I use DES algorithm but its using same key ....
can anybody suggest how to do this.... me blank value.....
`
public String encrypt(String smsbody) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);// initialize key pairs to 512 bits ,you can
// also take 1024 or 2048 bits
KeyPair kp = kpg.genKeyPair();
PublicKey publi = kp.getPublic();
System.out.println(publi.serialVersionUID);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publi);
byte[] src = smsbody.getBytes();// converting source data into byte
// array
byte[] cipherData = cipher.doFinal(src);// use this method to
// finally encrypt data
String srco = new String(cipherData);// converting byte array into
// string
// System.out.println();
// System.out.println("Encrypted data is:-" + srco);
return srco;
} catch (Exception e) {
System.out.println(e.getMessage());
}
return "";
}
public PrivateKey Privatekey() {
try {
kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);// initialize key pairs to 512 bits ,you can
// also take 1024 or 2048 bits
KeyPair kp = kpg.genKeyPair();
privatei = kp.getPrivate();// Generating private key
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return privatei;
}
public String decrypt(String smsbody, PrivateKey privatei) {
try {
Cipher cipheri = Cipher.getInstance("RSA");
cipheri.init(Cipher.DECRYPT_MODE, privatei);// Setting to
// decrypt_mode
System.out.println(smsbody);
byte[] cipherDat = cipheri.doFinal(smsbody.getBytes());// Finally
// decrypting
// data
System.out.println(cipherDat);
String decryptdata = new String(cipherDat);
return decryptdata;
} catch (Exception e) {
System.out.println(e.getMessage());
}
return "";
} `
I am trying this following code but when i use decrypt it will give
Thanks in advance...
public String generateKey(String title, String userName){
char[] hexDigits = "0123456789abcdef".toCharArray();
String source;
String MD5 = null;
byte[] digest = null;
source = title + "balh" + userName ;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
digest = md.digest(source.getBytes("UTF-16"));
StringBuilder sb = new StringBuilder(32);
for (byte b : digest)
{
sb.append(hexDigits[(b >> 4) & 0x0f]);
sb.append(hexDigits[b & 0x0f]);
}
System.out.println("Gened KEY ===="+sb.toString());
return sb.toString();
} catch (Exception e) {
}
return "";
}
I use the same code to generate key in android, and in Servlet. But I get different results. What am I doing wrong? Or if those are not compatible then how to make them.
I used the following method in both server and android client. It worked. But don't know what's the problem I had.
http://mobile.dzone.com/news/android-snippet-making-md5
I am trying to generate a SHA256 hash in android, that I then pass to an ASP.NET Web API web service and compare the hash there. As such, I need to construct a hash in Android, that given the same inputs in ASP.NET will generate an equivalent hash. I'm pulling my hair out trying to figure out what I'm doing wrong.
Here's the Android code:
public String computeHash(String input) throws NoSuchAlgorithmException{
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.reset();
try{
digest.update(input.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e){
e.printStackTrace();
}
byte[] byteData = digest.digest(input.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++){
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
Here's the C# code for the server:
private static string ComputeHash(string input, HashAlgorithm algorithm)
{
Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashedBytes.Length; i++)
{
sb.Append(String.Format("{0:x2}", hashedBytes[i]));
}
return sb.ToString();
}
Your Java code is wrong: you are adding the input bytes twice. If you are calculating this in one go, you need to either call only digest(bytes) or call digest() after update(bytes);
I was looking for a Kotlin version for my Android app.
I could not find one; here is what I came up with:
fun String.getSha256(): String {
val digest = MessageDigest.getInstance("SHA-256").apply { reset() }
val byteData: ByteArray = digest.digest(this.toByteArray())
return StringBuffer().apply {
byteData.forEach {
append(((it.toInt() and 0xff) + 0x100).toString(16).substring(1))
}
}.toString()
}
Migrating OP's solution from the question to an answer:
Here is the corrected Android/Java implementation (based on Nikolay Elenkov's answer):
public String computeHash(String input) throws NoSuchAlgorithmException, UnsupportedEncodingException{
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.reset();
byte[] byteData = digest.digest(input.getBytes("UTF-8"));
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++){
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}