I have a Java snippet here, I was wondering if it is possible to translate to VB.Net, as I have no found a snippet for VB.Net - only this:
private static byte[] SHA1(final String in)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(in.getBytes("iso-8859-1"), 0, in.length());
return md.digest();
}
public static String decryptSHA1(String key, final String start) {
final String delim = "a";
if (start == null)
return null;
byte[] hashedkey;
byte[] password;
int i;
try {
hashedkey = SHA1(key);
} catch (final NoSuchAlgorithmException e) {
e.printStackTrace();
return start;
} catch (final UnsupportedEncodingException e) {
e.printStackTrace();
return start;
}
final String[] temp = start.split(delim);
password = new byte[temp.length];
for (i = 0; i < hashedkey.length; i++) {
final int temp2 = Integer.parseInt(temp[i]);
if (hashedkey[i] == temp2) {
break;
} else {
password[i] = (byte) (temp2 - hashedkey[i]);
}
}
return new String(password, 0, i);
}
Thanks for any advice.
The hardest part here seems to be redoing the SHA1 method. You just need to find the equivalent .NET library classes/methods. Judging from the names, you probably want the System.Text.Encoding class and the System.Security.Cryptography.SHA1 class. Off hand, the algorithm probably ends up something like this
Private Shared Function SHA1(input As String) As Byte()
Dim iso8859 = System.Text.Encoding.GetEncoding("iso-8859-1")
Dim inBytes = ios8859.GetBytes(input)
' This is one implementation of the abstract class SHA1.'
Dim sha As New SHA1CryptoServiceProvider()
Return sha.ComputeHash(data)
End Function
From there you should be able to convert the rest of the decryptSHA1 function yourself as it is just basic byte manipulation. I will note that the GetEncoding function says it throws ArgumentException if you pass an invalid code page name and there does not seem to be any equivalent exception for NoSuchAlgorithmException to worry about catching.
Related
I have a method which takes a String as an argument and returns the MD5 value of the String as a String. However, when I use the method I get "Th method md5() is undefined for type String". I'm probably just too tired too see an error I made, could you help me?
public static String md5(String s) {
try {
MessageDigest m = MessageDigest.getInstance("MD5");
m.reset();
m.update(s.getBytes());
byte[] digest = m.digest();
BigInteger bigInt = new BigInteger(1, digest);
return bigInt.toString(16);
} catch (Exception e) {
return null;
}
}
public void hashing() {
int counter = 0;
StringBuilder sb = new StringBuilder();
for (int i=0; i<slovo.length(); i++) {
if (slovo.charAt(i)=='_') {
sb.append(characters.charAt(array[counter]));
counter++;
}else {
sb.append(input.charAt(i));
}
}
if (sb.toString().md5()==hash) { //this is the line which is producing the error
}
System.out.println(sb.toString());
}
A String object does not have the method md5(), and md5 takes in a single argument.
Did you mean md5(sb.toString()) ?
I am new to Android and java in general, i wanted to inspect how a specific app works, so i begun by de-compiling the app using apktool and then used jadx to browse the source files, everything makes sense so far, so i added a mitmproxy to inspect the network traffic from the app.
I know that the request reply is a JSON payload, however "some of them" are encrypted possibly using mcrypt or openssl? so tracing methods leads me to this file.
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class MC {
private IvParameterSpec a;
private SecretKeySpec b;
private Cipher c;
private native int getint();
public native String I6MOYF();
static {
System.loadLibrary("native-lib");
}
public MC(String str) {
this.a = new IvParameterSpec(str.getBytes());
this.b = new SecretKeySpec((I6MOYF() + String.valueOf(getint())).getBytes(), "AES");
try {
this.c = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e2) {
e2.printStackTrace();
}
}
public byte[] encrypt(String str) throws Exception {
if (str == null || str.length() == 0) {
throw new Exception("Empty string");
}
try {
this.c.init(1, this.b, this.a);
return this.c.doFinal(a(str).getBytes());
} catch (Exception e) {
throw new Exception("[encrypt] " + e.getMessage());
}
}
private static String a(String str) {
int length = 16 - (str.length() % 16);
for (int i = 0; i < length; i++) {
str = str + 0;
}
return str;
}
public byte[] des(String str) throws Exception {
if (str == null || str.length() == 0) {
throw new Exception("Empty string");
}
try {
this.c.init(2, this.b, this.a);
Object doFinal = this.c.doFinal(hexToBytes(str));
if (doFinal.length > 0) {
int i = 0;
for (int length = doFinal.length - 1; length >= 0; length--) {
if (doFinal[length] == (byte) 0) {
i++;
}
}
if (i > 0) {
Object obj = new byte[(doFinal.length - i)];
System.arraycopy(doFinal, 0, obj, 0, doFinal.length - i);
return obj;
}
}
return doFinal;
} catch (Exception e) {
throw new Exception("[decrypt] " + e.getMessage());
}
}
public static byte[] hexToBytes(String str) {
byte[] bArr = null;
if (str != null && str.length() >= 2) {
int length = str.length() / 2;
bArr = new byte[length];
for (int i = 0; i < length; i++) {
bArr[i] = (byte) Integer.parseInt(str.substring(i * 2, (i * 2) + 2), 16);
}
}
return bArr;
}
}
i understand that it uses OpenSSL "AES/CBC/NoPadding" mode for for decrypting the payload, however i am at loss how to take the payload and do it manually.
here is an example of the payload the server gives, the app send key header, however changing and dropping it does not change the payload, so i concluded it's not using the key for the actual encryption
AwFpdchYa7twLSEwN884uGQ/CNoLKrGBxtwIXGcL9OQTPPh96I1uhuh85HXLw3XUikVCmKaKgnssGorqYuvHQELce3nAhnaeHDcEsMFIykeitgDWLXeCed6f9UXHn+XF8nC3arHVbhMgIW8bUlWMq6KygRb4jeUufRHJzJ7LK0q6TvY+rF+utv3i//3NCuKfmbiiMlBvyDdMWPIL83YywkdjLujbBn0RNaeqUDjE0I7xqYypWPjwPXH1DZPbnGFYHemJgNS8QKtFnbtiRwEhpzx2sEoe/NBIgvcXsYkRSgrt+Q==
So the main question is, how would you use the provided code to manually decrypt the payload?
EDIT:
as suggested by Mr. #Robert, i tried to see how the native functions being called, so i installed frida-server on android emulator, and here is the interesting call, not sure what to make of it
/* TID 0x10b1 */
15066 ms open(pathname="/data/app/com.friga.gameapp-lPtwMqeZ36x47-Yo8YDzOg==/lib/x86/libnative-lib.so", flags=0x0)
i guess this supposed to be the key? -lPtwMqeZ36x47-Yo8YDzOg==
I managed to solve the problem using frida by following "Frida hooking android part 5: Bypassing AES encryption" post by 11x256 blog
I have an API documentation that requires encrypting a key to authenticate,
I managed to build and compile their sample code, but the results on windows are different than linux.
When I run and test from Windows, all seems to be correct and works with the API.
That same test on Linux outputs a different result. I need it working on Linux since that's the main server.
I am using & running the same jar file on both environments.
This is the key I am trying to encrypt (it's a dynamic key):
2136230$486B91E1BEA5D082BA3601CD803585CE$20140409$20140409$$ABCDEFGH$Reserved$CTC
This is the correct output on Windows (it's obviously quite longer):
F7BE2B7E0CEAD9D09135FCF2A8AEB11E2937D26B33CCBC9B8132A29A3534040C9737B2A8E3F271A9DF6454696CF890F7886223AE9C86F81EF58E41AEAA3D34A80F7089154E64F4FD36E75C25A7C2DA7FF03D21F57DA950F5
This is the wrong output from Linux:
F66D4CE1238B30EE54ABC74966D7AC3064FEA3ADFB9D37548E41509CE4FED9CB1D146651B491F2433169999A85F73DAF9ACD07A090DF3D85477BE4201ADC9E1A0181EA7CB763050A
What is causing this and how to correct it ?
This is the source code of the program to use as we received from the API company:
public class DESUtil
{
private static final String Algorithm = "DESede/ECB/PKCS5Padding";// DESede/ECB/PKCS5Padding;DESede
private static final String DESede = "DESede";
public static byte[] encrypt(byte[] keybyte, byte[] src)
throws NoSuchAlgorithmException, NoSuchPaddingException, Exception
{
SecretKey deskey = new SecretKeySpec(keybyte, DESede);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE, deskey);
return c1.doFinal(src);
}
public static byte[] decrypt(byte[] keybyte, byte[] src)
throws NoSuchAlgorithmException, NoSuchPaddingException, Exception
{
SecretKey deskey = new SecretKeySpec(keybyte, DESede);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE, deskey);
return c1.doFinal(src);
}
public static String byte2hex(byte[] b)
{
StringBuffer hs = new StringBuffer();
String stmp = "";
for (int n = 0; n <b.length; n++)
{
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1)
hs.append("0").append(stmp);
else
hs.append(stmp);
}
return hs.toString().toUpperCase(Locale.getDefault());
}
public static byte[] hex2byte(String hexStr)
{
if (hexStr.length() % 2 != 0)
{
AppLogger.error("hex2bytes's hexStr length is not even.");
return null;
}
byte[] toBytes = new byte[hexStr.length() / 2];
for (int i = 0, j = 0; i <hexStr.length(); j++, i = i + 2)
{
int tmpa = Integer.decode(
"0X" + hexStr.charAt(i) + hexStr.charAt(i + 1)).intValue();
toBytes[j] = (byte) (tmpa & 0XFF);
}
return toBytes;
}
public static void main(String[] args)
{
Security.addProvider(new com.sun.crypto.provider.SunJCE());
final byte[] rawKey = "db90e7eb".getBytes();
final byte[] keyBytes = new byte[24];
for (int i = 0; i <rawKey.length; i++)
{
keyBytes[i] = rawKey[i];
}
for (int i = rawKey.length; i <keyBytes.length; i++)
{
keyBytes[i] = (byte)0;
}
String szSrc = "20926330$AD75B1697FB5EB6345B2D412124030D2$10086$10086$10.164.111$ABCDEFGH$Reserved$CTC";
System.out.println("string before encrypt:" + szSrc);
byte[] encoded = null;
try
{
encoded = encrypt(keyBytes, szSrc.getBytes());
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("string after encrypt::" + byte2hex(encoded));
byte[] srcBytes = null;
try
{
srcBytes = decrypt(keyBytes, encoded);
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("string before decode: :" + (new String(srcBytes)));
}
}
Almost certainly your use of szSrc.getBytes() which uses the platform's default character encoding.
Try szSrc.getBytes("ISO-8859-1") as a starter if it's working on Windows, but if this string comes from an external service you should determine the encoding scheme dynamically (eg. if it comes through a Servlet use httpRequest.getCharacterEncoding()).
Can someone figure out why the output of these (php and java) snippets of code don't return the same SHA512 for the same input?
$password = 'whateverpassword';
$salt = 'ieerskzcjy20ec8wkgsk4cc8kuwgs8g';
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, true);
echo "digest: ".base64_encode($digest);
for ($i = 1; $i < 5000; $i++) {
$digest = hash('sha512', $digest.$salted, true);
}
$encoded_pass = base64_encode($digest);
echo $encoded_pass;
This is the code on the android application:
public String processSHA512(String pw, String salt, int rounds)
{
try {
md = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("No Such Algorithm");
}
String result = hashPw(pw, salt, rounds);
System.out.println(result);
return result;
}
private static String hashPw(String pw, String salt, int rounds) {
byte[] bSalt;
byte[] bPw;
String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString();
try {
bSalt = appendedSalt.getBytes("ISO-8859-1");
bPw = pw.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Unsupported Encoding", e);
}
byte[] digest = run(bPw, bSalt);
Log.d(LCAT, "first hash: " + Base64.encodeBytes(digest));
for (int i = 1; i < rounds; i++) {
digest = run(digest, bSalt);
}
return Base64.encodeBytes(digest);
}
private static byte[] run(byte[] input, byte[] salt) {
md.update(input);
return md.digest(salt);
}
The library for base64 encoding is this: base64lib
This java code is actually some modified code I found around another question in StackOverflow.
Although the Android code is running fine it doesn't match with the output from the php script. It doesn't even match the first hash!
Note 1: On php hash('sha512',$input, $raw_output) returns raw binary output
Note 2: On java I tried to change the charset (UTF-8, ASCII) but it also didn't work.
Note 3: The code from the server can not be changed, so I would appreciate any answer regarding how to change my android code.
The first hash should be the same on the server and in Java. But then in the loop what gets appended to the digest is password{salt} in the PHP code, but only {salt} in the Java code.
For the lazy ones, one example better than a thousand words ;). I finally understood what was happening. The method update appends bytes to the digest, so when you append $password.{$salt} is the same as doing mda.update(password bytes) and the mda.digest("{$salt}" bytes. I do that answer because I was going crazy finding why it was not working and it was all in this answer.
Thanks guys.
This is the example that works in a Java Server:
public static String hashPassword(String password, String salt) throws Exception {
String result = password;
String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString();
String appendedSalt2 = new StringBuilder().append(password).append('{').append(salt).append('}').toString();
if(password != null) {
//Security.addProvider(new BouncyCastleProvider());
MessageDigest mda = MessageDigest.getInstance("SHA-512");
byte[] pwdBytes = password.getBytes("UTF-8");
byte[] saltBytes = appendedSalt.getBytes("UTF-8");
byte[] saltBytes2 = appendedSalt2.getBytes("UTF-8");
byte[] digesta = encode(mda, pwdBytes, saltBytes);
//result = new String(digesta);
System.out.println("first hash: " + new String(Base64.encode(digesta),"UTF-8"));
for (int i = 1; i < ROUNDS; i++) {
digesta = encode(mda, digesta, saltBytes2);
}
System.out.println("last hash: " + new String(Base64.encode(digesta),"UTF-8"));
result = new String(Base64.encode(digesta));
}
return result;
}
private static byte[] encode(MessageDigest mda, byte[] pwdBytes,
byte[] saltBytes) {
mda.update(pwdBytes);
byte [] digesta = mda.digest(saltBytes);
return digesta;
}
What I'm trying to do is to convert a password typed into a jPasswordField into SHA-256 hash. I was wandering around and found how to do this if I've got password saved as a string but the field I'm using is returning char[] so I ended up just guessing what to do... at first I've got different results even if the password was the same but now I believe I'm closer as it's a constant; but it's still not it as the output of
echo -n 'abc' | sha256sum
is
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
while the output of my action (for the same input) is
86900f25bd2ee285bc6c22800cfb8f2c3411e45c9f53b3ba5a8017af9d6b6b05
My action looks like this:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
NoSuchAlgorithmException noSuchAlgorithmException = null;
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException ex) {
noSuchAlgorithmException = ex;
}
if (noSuchAlgorithmException != null) {
System.out.println(noSuchAlgorithmException.toString());
}
else {
UnsupportedEncodingException unsupportedEncodingException = null;
byte[] hash = null;
char[] password = jPasswordField1.getPassword();
StringBuffer stringBuffer = new StringBuffer();
for (char c : password) {
if (c > 0 && c < 16) {
stringBuffer.append("0");
}
stringBuffer.append(Integer.toHexString(c & 0xff));
}
String passwordString = stringBuffer.toString();
try {
hash = messageDigest.digest(passwordString.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
unsupportedEncodingException = ex;
}
if (unsupportedEncodingException != null) {
System.out.println(unsupportedEncodingException.toString());
}
else {
stringBuffer = new StringBuffer();
for (byte b : hash) {
stringBuffer.append(String.format("%02x", b));
}
String passwordHashed = stringBuffer.toString();
System.out.println(passwordHashed);
}
}
Any ideas?
You've pretty much nailed it. just took the hard/wrong way converting from char[] to String -> new String(password) is all you need. (hint, if you find yourself manually converting between bytes and chars, you're probably doing it wrong).
as a side note, exceptions are "thrown" for a reason. that makes it easy to skip the following code which shouldn't be executed when the exception is thrown. by catching and turning the exceptions into "if" blocks, you make the code more complex than it needs to be.
This prints out the same hash as sha256sum
public static void main(String[] args)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
char[] password = new char[]{'a', 'b', 'c'};
MessageDigest messageDigest = null;
messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hash = null;
// This is how you convert a char array into a String without reencoding it into a different set of characters.
String passwordString = new String(password);
hash = messageDigest.digest(passwordString.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte b : hash) {
sb.append(String.format("%02x", b));
}
String passwordHashed = sb.toString();
System.out.println(passwordHashed);
}