I was writing this code to restore the user's saved chrome passwords and display them on the console.
I was able to decode Base64 encoded. But I am failing in decrying from this Crypt32Util.cryptUnprotectData any help ...
I am a beginner. :)
Main.java
import java.io.FileReader;
import java.util.Base64;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.sun.jna.platform.win32.Crypt32Util;
public class Main {
public static void main(String[] args) {
String name = System.getProperty("user.home");
name += "\\AppData\\Local\\Google\\Chrome\\User Data\\";
String masterKey = "";
String localState = name + "Local State";
try {
Object object = new JSONParser().parse(new FileReader(localState));
System.out.println("Success");
JSONObject jsonObject = (JSONObject) object;
JSONObject tempJsonObject = (JSONObject) jsonObject.get("os_crypt");
Base64.Decoder decoder = Base64.getDecoder();
String encryptedKey = (String) tempJsonObject.get("encrypted_key");
String decryptedKey = new String(decoder.decode(encryptedKey));
String encryptedMasterKey = decryptedKey.substring(5);
System.out.println(encryptedMasterKey);
masterKey = new String(Crypt32Util.cryptUnprotectData(encryptedMasterKey.getBytes()));
System.out.println(masterKey);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output
Success
[value of **encryptedMasterKey**]
com.sun.jna.platform.win32.Win32Exception: The data is invalid.
at com.sun.jna.platform.win32.Crypt32Util.cryptUnprotectData(Crypt32Util.java:144)
at com.sun.jna.platform.win32.Crypt32Util.cryptUnprotectData(Crypt32Util.java:117)
at com.sun.jna.platform.win32.Crypt32Util.cryptUnprotectData(Crypt32Util.java:104)
at com.main.Main.main(Main.java:26)
decoder.decode() returns binary data. You cannot create a String from binary data.
If you want a byte[] with the first 5 bytes from the byte[] returned by decoder.decode(), use Arrays.copyOfRange():
String encryptedKey = (String) tempJsonObject.get("encrypted_key");
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodedKey = decoder.decode(encryptedKey);
byte[] encryptedMasterKey = Arrays.copyOfRange(decodedKey, 0, 5);
byte[] masterKey = Crypt32Util.cryptUnprotectData(encryptedMasterKey);
However, I doubt that is correct. Why do you believe the master password could be encrypted to only 5 bytes, and what is all the rest then?
It's far more likely that all the bytes are encrypted version of the master key:
String encryptedKey = (String) tempJsonObject.get("encrypted_key");
byte[] masterKey = Crypt32Util.cryptUnprotectData(Base64.getDecoder().decode(encryptedKey));
The answer of #Andreas is almost correct
I used this code which gave me an exception
String encryptedKey = (String) tempJsonObject.get("encrypted_key");
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodedKey = decoder.decode(encryptedKey);
byte[] encryptedMasterKey = Arrays.copyOfRange(decodedKey, 0, 5);
byte[] masterKey = Crypt32Util.cryptUnprotectData(encryptedMasterKey);
So it just changed some values in
String encryptedKey = (String) tempJsonObject.get("encrypted_key");
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodedKey = decoder.decode(encryptedKey);
byte[] encryptedMasterKey = Arrays.copyOfRange(decodedKey, 5, decodedKey.length);
byte[] masterKey = Crypt32Util.cryptUnprotectData(encryptedMasterKey);
It worked But now I have to understand its key format :)
Thanks, Andreas
Related
I have the following JAVA and I am trying to convert into C# using ChilKat (or BouncyCastle) I have a working version in ChilKat, but not sure how to validate Here is the JAVA code:
private SecretKey symmKey = null;
public String encrypt(String strToEncrypt) throws Exception
{
String symmEncryptMode = "DESede";
String encString= null;
KeyGenerator keyGen = KeyGenerator.getInstance(symmEncryptMode);
symmKey = keyGen.generateKey();
byte dataToEncrypt[] = strToEncrypt.getBytes();
Cipher symmCipher = Cipher.getInstance(symmEncryptMode);
symmCipher.init(Cipher.ENCRYPT_MODE, symmKey);
byte[] encrypted = symmCipher.doFinal(dataToEncrypt);
encString= new String(Base64.encode(encrypted));
encString = URLEncoder.encode(encString, "UTF-8");
return(encString);
} //end method create Signature
Here is what I have so far (It returns a value, but I don't know how to validate as this is one of three steps of my encyption process - step 3 works, 1 and 2 are suspect, so I figured I'd ask one at a time...) This uses ChilKat and it returns a value, but I am not sure if it is correct:
private static string EncryptStringSymmetric(string data2Encrypt, ref string passKey)
{
//Init Encryptor
Crypt2 encryptor = new Crypt2();
bool success = encryptor.UnlockComponent("Anything for 30 - day trial");
if (success != true)
{ throw (new Exception("Crypt component unlock failed")); }
//Encryptor Settings
encryptor.CryptAlgorithm = "3des";
encryptor.KeyLength = 192;
encryptor.EncodingMode = "base64";
encryptor.PaddingScheme = 0;
encryptor.Charset = "utf-8";
encryptor.CipherMode = "ecb";
encryptor.RandomizeKey();
passKey = encryptor.GetEncodedKey("base64");
string eStr;
//byte[] bytesToEncrypt = Encoding.ASCII.GetBytes(data2Encrypt);
//eStr = encryptor.EncryptBytesENC(bytesToEncrypt);//??
eStr = encryptor.EncryptStringENC(data2Encrypt);
return eStr;
}
I need your help. My java and python scripts not getting the ame sha-1 value of a string:
hash.py
# -*- coding: utf-8 -*-
import hashlib
username = raw_input('username:')
timestamp = raw_input('timestamp:')
app_id = 'dad'
secret_key = 'dadda'
print 'The hashed string is: ' , hashlib.sha1( username + timestamp + app_id + secret_key ).hexdigest()
hash.java
public static String generateSHA1(String password)
{
String sha1 = "";
try
{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(password.getBytes("UTF-8"));
sha1 = byteToHex(crypt.digest());
}
catch(Exception e)
{
e.printStackTrace();
}
return sha1;
}
private static String byteToHex(final byte[] hash)
{
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
UPDATE:
Assuming password is already the concatenated: username, timestamp, app_id and secret_key
Is there something I missed? I think there is something wrong with my java code re. UTF-8 outputting this: \xe2\x80\x8b but I couldn't figure it out. Any help will be appreciated. Thanks.
Ensure that both inputs use exactly the same format and encoding and try to use HMAC library.
Java:
String key = "2b5ba589b618ff2485f3391e425f86f0f405fd8e";
String data = "Something you want to keep secret!";
byte[] decodedKey = Hex.decodeHex(key.toCharArray());
SecretKeySpec keySpec = new SecretKeySpec(decodedKey, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(keySpec);
byte[] dataBytes = data.getBytes("UTF-8");
byte[] signatureBytes = mac.doFinal(dataBytes);
String signature = new String(Base64.encodeBase64(signatureBytes), "UTF-8");
System.out.println("key = " + key);
System.out.println("data = " + data);
System.out.println("signature = " + signature);
Python:
import hmac
import hashlib
key = "2b5ba589b618ff2485f3391e425f86f0f405fd8e"
data = "Something you want to keep secret!"
decodedKey = key.decode("hex")
hmac = hmac.new(decodedKey, data.encode('UTF-8'), hashlib.sha1)
signature = hmac.digest().encode('base64')
print "key =", key
print "data =", data
print "signature =", signature
Both signature outputs should be the same.
As part of my J2EE application's email service, I encode into BASE64
body = MimeUtility.encodeText(orig_mail_body,"UTF-8","BASE64");
but in some circumstances it's throwing an exception:
java.io.UnsupportedEncodingException: Unknown transfer encoding: BASE64
at javax.mail.internet.MimeUtility.encodeWord(MimeUtility.java:565)
at javax.mail.internet.MimeUtility.encodeText(MimeUtility.java:373)
I've been trying to uncover why I get this particular message, but to no avail.
Can someone illuminate me?
It seems like the only valid values for the 'encoding' argument are "B" or "Q"; so my code should be:
body = MimeUtility.encodeText(orig_mail_body,"UTF-8","B");
if you're using java 8 now there is a class that can solve that.
byte[] bytes = orig_mail_body.getBytes();
Base64.Encoder encoder = Base64.getEncoder();
String encode = encoder.encodeToString(bytes);
System.out.print(encode);
with spring: org.springframework.security.crypto.codec
public static String base64Encode(String token) {
byte[] encodedBytes = Base64.encode(token.getBytes());
return new String(encodedBytes, Charset.forName("UTF-8"));
}
public static String base64Decode(String token) {
byte[] decodedBytes = Base64.decode(token.getBytes());
return new String(decodedBytes, Charset.forName("UTF-8"));
}
with apache commons
org.apache.commons.codec.binary.Base64;
byte[] encodedBytes = Base64.encodeBase64("Test".getBytes());
System.out.println("encodedBytes " + new String(encodedBytes));
byte[] decodedBytes = Base64.decodeBase64(encodedBytes);
System.out.println("decodedBytes " + new String(decodedBytes));
Salud
I am trying to encrypt a string using the RSA public key encryption. I have a public key which is:
-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7yyFgPV6Fk8JWngl3MIz\n1U2DMwKPNCRkeQ79g/qwKL0LP5aVkQUUxqYhX0mmQMWnT5t+7Hoc6UUxyjGSkI9o\nv0Q3oTSVtByIQDdySXZWihzjVjn3h98chevZuNNkJ4GNADHj5K/7LOWLpKSQJ2Hj\nIFdVrcKSjy4kiP/UMHgsfq0GWQAtGv8ebcybWuEf8rzTMndxmI96Nmz5PgPK7K75\nXbMgJlOMoMlXDsgmghpGzH8p10r/qHGlYi/COa4PZ7Pvbveg1BoH5LPy/8mLZ+Oa\n9owl10yBIoh9/H5KnijZ0Uq8MH0QdgQXekLC9sRh3uGTe69IQrGXzSv7tHe5fgv6\nnwIDAQAB\n-----END
PUBLIC KEY-----
I am using following code to encrypt it :
private String generateRSAEncryptedText(String publicKey) {
String baseCredentials = email + "---" + password;
try {
return encryptRSA(context, baseCredentials, publicKey);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private String getPublicKeyStringFromPemFormat(String PEMString, boolean isFilePath) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
BufferedReader pemReader = null;
if (isFilePath) {
pemReader = new BufferedReader(new InputStreamReader(new FileInputStream(PEMString)));
} else {
pemReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(PEMString.getBytes("UTF-8"))));
}
StringBuffer content = new StringBuffer();
String line = null;
while ((line = pemReader.readLine()) != null) {
if (line.indexOf("-----BEGIN PUBLIC KEY-----") != -1) {
while ((line = pemReader.readLine()) != null) {
if (line.indexOf("-----END PUBLIC KEY") != -1) {
break;
}
content.append(line.trim());
}
break;
}
}
if (line == null) {
throw new IOException("PUBLIC KEY" + " not found");
}
Log.i("PUBLIC KEY: ", "PEM content = : " + content.toString());
return content.toString();
}
public String encryptRSA(Context mContext, String message, String publicKeyString) throws Exception {
String keyString = getPublicKeyStringFromPemFormat(publicKeyString, false);
// converts the String to a PublicKey instance
byte[] keyBytes = Base64.decode(keyString.getBytes("utf-8"), Base64.NO_WRAP);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(spec);
// decrypts the message
byte[] dectyptedText = null;
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
dectyptedText = cipher.doFinal(Base64.decode(message.getBytes("utf-8"), Base64.NO_WRAP));
return Base64.encodeToString(dectyptedText, Base64.NO_WRAP);
}
Using this, i am able to generate an encrypted text but the PHP server is not able to decrypt my encrypted text.
Server is working correctly as i am able to the whole exercise using a python script but it is not working for android.
Any idea what i might be doing wrong.. all help is appreciated.
Some other pointer:
I get the public key as a string from the server and it can be changed at any time so cant save it in a cert file.
I am using android.util.Base64 class for encoding.
Let me know if you need any other information.
Working Python Code:
import requests
import base64
def try_api():
API_ENDPOINT = 'https://example.com/login.php'
PUBLIC_KEY = None
###get_pulic_key###
payload = {'requestType':'getPubkey'}
r = requests.post(API_ENDPOINT, data=payload, verify=False)
mycookies = dict (r.cookies)
#print mycookies
res = r.json()
PUBLIC_KEY = res[1]
print "PublicKey\n", PUBLIC_KEY
###get_token###
credential = prepare_credentials('abc#gmail.com', 'abctest', PUBLIC_KEY)
print "Credential\n", credential
cred_payload = {'requestType':'credentialLogin', 'credential':credential}
r = requests.post(API_ENDPOINT, data=cred_payload, cookies=mycookies, verify=False)
#print r.text
status, token =r.json()
def prepare_credentials(username, password, public_key):
"""
Given username and password prepare the credentials
"""
basecred = "%s---%s" % (username, password)
#print "basecred\n", basecred
basecred64 = base64.b64encode(basecred)
#print "basecred64\n", basecred64
basecred64encrypted64 = encrypt_RSA(public_key, basecred64)
#print "basecred64encrypted64\n", basecred64encrypted64
return basecred64encrypted64
def encrypt_RSA(public_key, message):
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
rsakey = RSA.importKey(public_key)
rsakey = PKCS1_v1_5.new(rsakey)
encrypted = rsakey.encrypt(message)
return base64.b64encode(encrypted)
if __name__=='__main__':
try_api()
I am trying to run a simple encryption/decryption program. I am getting a padding exception. There must be something hidden that I am not aware. I basically encrypted a string write it to a file, read it back, and decrypted it. The original encrypted array was decrypted without a problem. I compared the original encrypted array with the array read back from the file, they were identical from what I can see. The buffer from the file does not work, so there must be something difference. I don't know what to do.
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
public class sample
{
private static String _algo = "AES";
private static byte[] _key = new byte[16];
public static byte[] encrypt (String val) throws Exception
{
Key key = new SecretKeySpec (_key, _algo);
Cipher c = Cipher.getInstance (_algo);
c.init (Cipher.ENCRYPT_MODE, key);
byte[] encode = c.doFinal (val.getBytes());
return encode;
}
public static String decrypt (byte[] val) throws Exception
{
Key key = new SecretKeySpec (_key, _algo);
Cipher c = Cipher.getInstance (_algo);
c.init (Cipher.DECRYPT_MODE, key);
byte[] decode = c.doFinal (val);
String decodeStr = new String (decode);
return decodeStr;
}
public static void main (String[] args) throws Exception
{
String str = "Good bye cruel world";
//
// get password from command line
//
_key = args[0].getBytes();
byte[] encodeArray = sample.encrypt (str);
//
// write encrypted array to file
//
FileOutputStream os = new FileOutputStream ("data");
os.write (encodeArray);
os.close();
//
// decode and print out string
//
String decodeStr = sample.decrypt (encodeArray);
System.out.println ("decodeStr = " + decodeStr);
//
// read back encrypted string
byte[] buffer = new byte[64];
FileInputStream is = new FileInputStream ("data");
is.read (buffer);
is.close();
decodeStr = sample.decrypt (buffer);
System.out.println ("decodeStr = " + decodeStr);
}
}
Output:
java sample 1234567890123456
decodeStr = Good bye cruel world
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at sample.decrypt(sample.java:32)
at sample.main(sample.java:70)
The problem is that the byte buffer with a size of 64, which you are reading the file into, is too big. Change it to 32.
Or use the length of the file like this:
byte[] buffer = new byte[(int)new File("data").length()];