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 am trying to implement rest call with key and secret using md5. I tried a way but its giving me an error,
{"status":"error","message":"Signature mismatch"}.
Please help me, its very urjent!!
this is my md5 method,
private static final String md5(final String parem) {
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest
.getInstance("MD5");
digest.update(parem.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < messageDigest.length; i++) {
String h = Integer.toHexString(0xFF & messageDigest[i]);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
Thanks in advance.
I did try with one of my classes and found only one difference:
Yours:
Input: test
Output: 098f6bcd4621d373cade4e832627b4f6
Mine:
Input: test
Output: 098F6BCD4621D373CADE4E832627B4F6
So only one diff, the uppercase....
if that does not solve it, i would say have a look if your hashing the correct data.
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();
}
I am parsing XML from URL in my application and first of all I shlould verify XML signature. Thus, my question is, is there any simple implementation of signing XML and it's verification on android?
Thanks
Do you mean somethin like this?
Make a request to the webservice that allows you to get the MD5 hash of the XML
Then get the XML
Make a MD5 hash from your XML from inside android
Compare the 2 to verify if you have the entire unmodified XML.
This is a nice string to MD5 converter:
private String md5(String in) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
digest.reset();
digest.update(in.getBytes());
byte[] a = digest.digest();
int len = a.length;
StringBuilder sb = new StringBuilder(len << 1);
for (int i = 0; i < len; i++) {
sb.append(Character.forDigit((a[i] & 0xf0) >> 4, 16));
sb.append(Character.forDigit(a[i] & 0x0f, 16));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
return null;
}
I have a simple android client which needs to 'talk' to a simple C# HTTP listener. I want to provide a basic level of authentication by passing username/password in POST requests.
MD5 hashing is trivial in C# and provides enough security for my needs but I can't seem to find how to do this at the android end.
EDIT: Just to address the concerns raised about MD5 weakness - the C# server runs on the PCs of the users of my android client. In many cases, they'll be accessing the server using wi-fi on their own LANs but, at their own risk, they may choose to access it from the internet. Also the service on the server needs to use pass-through for the MD5 to a 3rd party application I have no control over.
Here is an implementation you can use (updated to use more up to date Java conventions - for:each loop, StringBuilder instead of StringBuffer):
public static String md5(final String s) {
final String MD5 = "MD5";
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest
.getInstance(MD5);
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuilder hexString = new StringBuilder();
for (byte aMessageDigest : messageDigest) {
String h = Integer.toHexString(0xFF & aMessageDigest);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
Although it is not recommended for systems that involve even the basic level of security (MD5 is considered broken and can be easily exploited), it is sometimes enough for basic tasks.
The accepted answer didn't work for me in Android 2.2. I don't know why, but it was "eating" some of my zeros (0) .
Apache commons also didn't work on Android 2.2, because it uses methods that are supported only starting from Android 2.3.x. Also, if you want to just MD5 a string, Apache commons is too complex for that. Why one should keep a whole library to use just a small function from it...
Finally I found the following code snippet here which worked perfectly for me. I hope it will be useful for someone...
public String MD5(String md5) {
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] array = md.digest(md5.getBytes("UTF-8"));
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; ++i) {
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {
} catch(UnsupportedEncodingException ex){
}
return null;
}
The androidsnippets.com code does not work reliably because 0's seem to be cut out of the resulting hash.
A better implementation is here.
public static String MD5_Hash(String s) {
MessageDigest m = null;
try {
m = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
m.update(s.getBytes(),0,s.length());
String hash = new BigInteger(1, m.digest()).toString(16);
return hash;
}
If using Apache Commons Codec is an option, then this would be a shorter implementation:
String md5Hex = new String(Hex.encodeHex(DigestUtils.md5(data)));
Or SHA:
String shaHex= new String(Hex.encodeHex(DigestUtils.sha("textToHash")));
Source for above.
Please follow the link and upvote his solution to award the correct person.
Maven repo link: https://mvnrepository.com/artifact/commons-codec/commons-codec
Current Maven dependency (as of 6 July 2016):
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
A solution above using DigestUtils didn't work for me. In my version of Apache commons (the latest one for 2013) there is no such class.
I found another solution here in one blog. It works perfect and doesn't need Apache commons. It looks a little shorter than the code in accepted answer above.
public static String getMd5Hash(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
String md5 = number.toString(16);
while (md5.length() < 32)
md5 = "0" + md5;
return md5;
} catch (NoSuchAlgorithmException e) {
Log.e("MD5", e.getLocalizedMessage());
return null;
}
}
You will need these imports:
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
This is a slight variation of Andranik and Den Delimarsky answers above, but its a bit more concise and doesn't require any bitwise logic. Instead it uses the built-in String.format method to convert the bytes to two character hexadecimal strings (doesn't strip 0's). Normally I would just comment on their answers, but I don't have the reputation to do so.
public static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
StringBuilder hexString = new StringBuilder();
for (byte digestByte : md.digest(input.getBytes()))
hexString.append(String.format("%02X", digestByte));
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
If you'd like to return a lower case string instead, then just change %02X to %02x.
Edit:
Using BigInteger like with wzbozon's answer, you can make the answer even more concise:
public static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
BigInteger md5Data = new BigInteger(1, md.digest(input.getBytes()));
return String.Format("%032X", md5Data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
Here is Kotlin version from #Andranik answer.
We need to change getBytes to toByteArray (don't need to add charset UTF-8 because the default charset of toByteArray is UTF-8) and cast array[i] to integer
fun String.md5(): String? {
try {
val md = MessageDigest.getInstance("MD5")
val array = md.digest(this.toByteArray())
val sb = StringBuffer()
for (i in array.indices) {
sb.append(Integer.toHexString(array[i].toInt() and 0xFF or 0x100).substring(1, 3))
}
return sb.toString()
} catch (e: java.security.NoSuchAlgorithmException) {
} catch (ex: UnsupportedEncodingException) {
}
return null
}
Hope it help
I have made a simple Library in Kotlin.
Add at Root build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
at App build.gradle
implementation 'com.github.1AboveAll:Hasher:-SNAPSHOT'
Usage
In Kotlin
val ob = Hasher()
Then Use hash() method
ob.hash("String_You_Want_To_Encode",Hasher.MD5)
ob.hash("String_You_Want_To_Encode",Hasher.SHA_1)
It will return MD5 and SHA-1 Respectively.
More about the Library
https://github.com/ihimanshurawat/Hasher
Please use SHA-512, MD5 is insecure
public static String getSHA512SecurePassword(String passwordToHash) {
String generatedPassword = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update("everybreathyoutake".getBytes());
byte[] bytes = md.digest(passwordToHash.getBytes());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return generatedPassword;
}
Useful Kotlin Extension Function Example
fun String.toMD5(): String {
val bytes = MessageDigest.getInstance("MD5").digest(this.toByteArray())
return bytes.toHex()
}
fun ByteArray.toHex(): String {
return joinToString("") { "%02x".format(it) }
}
In our MVC application we generate for long param
using System.Security.Cryptography;
using System.Text;
...
public static string getMD5(long id)
{
// convert
string result = (id ^ long.MaxValue).ToString("X") + "-ANY-TEXT";
using (MD5 md5Hash = MD5.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(result));
// Create a new Stringbuilder to collect the bytes and create a string.
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sBuilder.Append(data[i].ToString("x2"));
// Return the hexadecimal string.
result = sBuilder.ToString().ToUpper();
}
return result;
}
and same in Android application (thenk helps Andranik)
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
...
public String getIdHash(long id){
String hash = null;
long intId = id ^ Long.MAX_VALUE;
String md5 = String.format("%X-ANY-TEXT", intId);
try {
MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] arr = md.digest(md5.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; ++i)
sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1,3));
hash = sb.toString();
} catch (NoSuchAlgorithmException e) {
Log.e("MD5", e.getMessage());
}
return hash.toUpperCase();
}
i have used below method to give me md5 by passing string for which you want to get md5
public static String getMd5Key(String password) {
// String password = "12131123984335";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes());
byte byteData[] = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Digest(in hex format):: " + sb.toString());
//convert the byte to hex format method 2
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
String hex = Integer.toHexString(0xff & byteData[i]);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
System.out.println("Digest(in hex format):: " + hexString.toString());
return hexString.toString();
} catch (Exception e) {
// TODO: handle exception
}
return "";
}
MD5 is a bit old, SHA-1 is a better algorithm, there is a example here.
(Also as they note in that post, Java handles this on it's own, no Android specific code.)
Far too wasteful toHex() conversion prevails in other suggestions, really.
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String md5string(String s) {
return toHex(md5plain(s));
}
public static byte[] md5plain(String s) {
final String MD5 = "MD5";
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance(MD5);
digest.update(s.getBytes());
return digest.digest();
} catch (NoSuchAlgorithmException e) {
// never happens
e.printStackTrace();
return null;
}
}
public static String toHex(byte[] buf) {
char[] hexChars = new char[buf.length * 2];
int v;
for (int i = 0; i < buf.length; i++) {
v = buf[i] & 0xFF;
hexChars[i * 2] = HEX_ARRAY[v >>> 4];
hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
this is working perfectly for me, I used this to get MD5 on LIST Array(then convert it to JSON object), but if you only need to apply it on your data. type format, replace JsonObject with yours.
Especially if you have a mismatch with python MD5 implementation use this!
private static String md5(List<AccelerationSensor> sensor) {
Gson gson= new Gson();
byte[] JsonObject = new byte[0];
try {
JsonObject = gson.toJson(sensor).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
MessageDigest m = null;
try {
m = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] thedigest = m.digest(JsonObject);
String hash = String.format("%032x", new BigInteger(1, thedigest));
return hash;
}
The provided solutions for the Scala language (a little shorter):
def getMd5(content: Array[Byte]) =
try {
val md = MessageDigest.getInstance("MD5")
val bytes = md.digest(content)
bytes.map(b => Integer.toHexString((b + 0x100) % 0x100)).mkString
} catch {
case ex: Throwable => null
}