Java DES Encrypt/Decrypt methods - java

I need to create two simple methods for string DES encryption/decruption. The goal is to have these two methods in the following form
public static String desEcnrypt(String key, String clearMessage)
{
.....
}
public static String desDecrypt(String key, String encryptedMessage)
{
.....
}
I haven't found yet any example in this form.

Use the "not-yet-commons-ssl.jar" from http://juliusdavies.ca/commons-ssl/.
http://juliusdavies.ca/commons-ssl/pbe.html
PBE code example (DES-3):*
char[] password = {'c','h','a','n','g','e','i','t'};
byte[] data = "Hello World!".getBytes();
// Encrypt!
byte[] encrypted = OpenSSL.encrypt("des3", password, data);
System.out.println("ENCRYPTED: [" + new String(encrypted) + "]");
// Decrypt results of previous!
data = OpenSSL.decrypt("des3", password, encrypted);
System.out.println("DECRYPTED: [" + new String(data) + "]");
OUTPUT:
=======================
ENCRYPTED: [U2FsdGVkX19qplb9qVDVVEYxH8wjJDGpMS+F4/2pS2c=]
DECRYPTED: [Hello World!]

Related

I have created a JWT object with some data. Then I decode that same JWT object just to compare and see if the validation passes. But it does not

I have created a JWT object with some data. Then I decode that same JWT object just to compare and see if the validation passes. But it does not. Following is the code I have created. What could be the issue?
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//Make a JWT Token String
String jws = Jwts.builder().setSubject("adam")
.setExpiration(new java.util.GregorianCalendar(2021,
Calendar.NOVEMBER, 8).getTime())
.setIssuer("someUser#mycompany.com")
.claim("groups", new String[] { "user", "admin" })
// HMAC using SHA-512 and 12345678 base64 encoded
.signWith(signatureAlgorithm, "MTIzNDU2Nzg=").compact();
System.out.println("JWTS String: "+ jws.toString());
//=================================================
//Decode the string back
Base64.Decoder decoder = Base64.getDecoder();
String[] chunks = jws.split("\\.");
String header = new String(decoder.decode(chunks[0]));
String payload = new String(decoder.decode(chunks[1]));
String signature = chunks[2];
System.out.println("Header: " + header);
System.out.println("PayLoad: " + payload);
System.out.println("Signature: " + signature);
String tokenWithoutSignature = chunks[0] + "." + chunks[1];
SecretKeySpec secretKeySpec = new
SecretKeySpec("MTIzNDU2Nzg=".getBytes(),signatureAlgorithm.getJcaName());
DefaultJwtSignatureValidator validator = new
DefaultJwtSignatureValidator(signatureAlgorithm,secretKeySpec);
if (validator.isValid(tokenWithoutSignature, signature)){
System.out.println("TOKEN IS VALID");
}else{
System.out.println("TOKEN IS INVALID");
}
You need to base64 decode the secret first.
replace...
SecretKeySpec secretKeySpec = new SecretKeySpec("MTIzNDU2Nzg=".getBytes(),signatureAlgorithm.getJcaName());
with
SecretKeySpec secretKeySpec = new SecretKeySpec(TextCodec.BASE64.decode("MTIzNDU2Nzg="), signatureAlgorithm.getJcaName());
and it should work!

Java SHA not woking. Hash value dosen't equal String. Is there an issue with my encoding?

Basically I have this
if (args.length != 1) {
System.err.println("Usage: java MyMd5 <message>");
System.exit(1);
}
try {
// get message
byte[] message = args[0].getBytes("UTF8");
// create message digest object for MD5
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
// System.out.println("Provider: " +
messageDigest.getProvider().getInfo();
// create message digest
messageDigest.update(message);
byte[] md = messageDigest.digest();
// print result
System.out.println("Message Digest Algorithm: MD5");
System.out.println("Message: " + new String(message));
System.out.println("Message Digest: \"" + new String(md, "UTF8") + "\"");
String HashPassword=new String(md, "UTF8");
System.out.println(HashPassword);
System.out.println(HashPassword.equals("???8p???W?B:??N?~"));
but somehow when I try to compare it is returning false. Is it some problem with my encoding? Thanks!
Message Digest Algorithm: MD5
Message: pass123
Message Digest: "???8p???W?B:??N?~"
???8p???W?B:??N?~
false
The problem is with unnecessary encoding, with md5 we have to encode the String in the correct way instead of using UTF8 encoding
public static void main(String[] args) throws Exception {
String pass = "pass123";
byte[] message = pass.getBytes();
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
messageDigest.update(message);
byte[] md = messageDigest.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < md.length; i++) {
sb.append(Integer.toString((md[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("encoded pass:" + sb.toString());
System.out.println(sb.toString().equals("aafdc23870ecbcd3d557b6423a8982134e17927e"));
}
If I understood your question correctly you want to compare newly generated hash string with existing one (stored in a data base or somewhere else). It's possible with provided above code and you will get true if you store generated value (not copy it from console) to the data base for example, and then compare it with newly generated.
But when you generate hash it contains symbols (characters), that doesn't have correct representation in any String encoding. So, nobody don't store hashes as a plain strings. Usually they are stored in hex string representation or Base64 representation.
Implementation with the use of hex strings provided below:
public static void main(String[] args) throws Exception { // args = ["Hello world"]
if (args.length != 1) {
System.err.println("Usage: java MyMd5 <message>");
System.exit(1);
}
// get message
byte[] message = args[0].getBytes("UTF8"); //You may have problems with encoding here. In Windows, for example, with symbols that are out of English alphabet range
// create message digest object for MD5
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
// System.out.println("Provider: " +
messageDigest.getProvider().getInfo();
// create message digest
messageDigest.update(message);
byte[] md = messageDigest.digest();
System.out.println("Digest: " + byteArrayToHexString(md));
System.out.println("Is equals? " + byteArrayToHexString(md).equals("7b502c3a1f48c8609ae212cdfb639dee39673f5e"));
}
private static String byteArrayToHexString(byte[] array) {
StringBuilder result = new StringBuilder(array.length);
IntStream.range(0, array.length)
.forEach(i -> result.append(Integer.toString( (array[i] & 0xff) + 0x100, 16).substring(1)));
return result.toString();
}
Also, in provided example mentioned that you are using MD5, but actually it's SHA. MessageDigest messageDigest = MessageDigest.getInstance("SHA");

C# to Java Base64 and HmacSHA256 encryption

I have the following code in C# which generates a hash value from a Base64 encoded string.
var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
string verb = "post";
string resourceType = "docs";
string resourceId = "dbs/ToDoList/colls/Items";
string date = DateTime.UtcNow.ToString("R");
string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
verb.ToLowerInvariant(),
resourceType.ToLowerInvariant(),
resourceId,
date.ToLowerInvariant(),
""
);
byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
string signature = Convert.ToBase64String(hashPayLoad);
string authToken = System.Web.HttpUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
keyType,
tokenVersion,
signature));
This works perfectly fine and I wanted to convert it to Java code for my Android app. I checked references from these sources-
C# vs Java HmacSHA1 and then base64
c# and java - difference between hmacsha256 hash
and wrote below code in Java-
String restServiceVersion = "2017-02-22";
String verb = "post";
String resourceType = "docs";
String resourceId = "dbs/ToDoList/colls/Items";
String dateString = org.apache.http.impl.cookie.DateUtils.formatDate(new Date(System.currentTimeMillis()));
String gmtIndex = "GMT";
int index = dateString.indexOf(gmtIndex);
String dateStringFinal = dateString.substring(0, index + 3).toLowerCase();
String payLoad = verb +"\n" + resourceType + "\n" + resourceId + "\n" + dateStringFinal + "\n\n";
System.out.println(payLoad);
String secretAccessKey = MASTER_KEY;
String data = payLoad;
byte[] secretKey = Base64.decode(secretAccessKey, Base64.DEFAULT);
SecretKeySpec signingKey = new SecretKeySpec(secretKey, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] bytes = data.getBytes("UTF-8");
byte[] rawHmac = mac.doFinal(bytes);
String authToken = "type=master&ver=1.0&sig=" + Base64.encodeToString(rawHmac, Base64.DEFAULT);
The authToken value generated in Java does not match with C#. Also the byte array generated from Base64 decoding differs.
I am not sure if this is the correct approach. Can someone please take a look? All I need is to convert the above working C# code to Java for my Android app.
Most likely explanation: you have invisible unicode characters (e.g. "zero-width non-joiner") embedded in your BASE64 strings. One platform is stripping these out when base-64 decoding, the other is not, resulting in different keys.

Amazon AWS Signature V4 Java gives Wrong Encoding

I am trying to create a simple form to POST an object to a bucket in S3 directly from my browser using AWS Signature V4.
I use Java to generate the policy and signature values for the pre-signed form. For now, I just want to test that it works so I don't mind that this is a manual signature generation process.
My Java code is the following
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class Lala {
static String policy_document = "{ \"expiration\": \"2015-12-30T12:00:00.000Z\"," +
" \"conditions\": [" +
" {\"bucket\": \"sigv4examplebucket\"}," +
" [\"starts-with\", \"$key\", \"user/user1/\"]," +
" {\"acl\": \"public-read\"}," +
" {\"success_action_redirect\": \"http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html\"}," +
" [\"starts-with\", \"$Content-Type\", \"image/\"]," +
" {\"x-amz-meta-uuid\": \"14365123651274\"}," +
" {\"x-amz-server-side-encryption\": \"AES256\"}," +
" [\"starts-with\", \"$x-amz-meta-tag\", \"\"]," +
" {\"x-amz-credential\": \"AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request\"}," +
" {\"x-amz-algorithm\": \"AWS4-HMAC-SHA256\"}," +
" {\"x-amz-date\": \"20151229T000000Z\" }" +
" ]" +
"}";
static String secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
public static void main(String[] args) throws Exception {
// Create a policy using UTF-8 encoding.
byte[] utf8_policy = policy_document.getBytes("UTF-8");
// Convert the UTF-8-encoded policy bytes to Base64. The result is the StringToSign.
String base64_policy = new String(Base64.encodeBase64(utf8_policy));
// Create a signing key.
byte[] signing_key = getSignatureKey(secret_key , "20151229", "us-east-1", "s3");
// Use the signing key to sign the StringToSign using HMAC-SHA256 signing algorithm.
byte[] signature_bytes = HmacSHA256(base64_policy, signing_key);
String signature = Hex.encodeHexString(signature_bytes);
System.out.println(base64_policy);
System.out.println();
System.out.println(signature);
}
static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
byte[] kDate = HmacSHA256(dateStamp, kSecret);
byte[] kRegion = HmacSHA256(regionName, kDate);
byte[] kService = HmacSHA256(serviceName, kRegion);
byte[] kSigning = HmacSHA256("aws4_request", kService);
return kSigning;
}
static byte[] HmacSHA256(String data, byte[] key) throws Exception {
String algorithm="HmacSHA256";
Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(data.getBytes("UTF-8"));
}
}
The policy document and access/secret keys pair are all taken from the Amazon's example here.
My code gives back the following Base64 encoded policy:
eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLCAgImNvbmRpdGlvbnMiOiBbICAgIHsiYnVja2V0IjogInNpZ3Y0ZXhhbXBsZWJ1Y2tldCJ9LCAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwgICAgeyJhY2wiOiAicHVibGljLXJlYWQifSwgICAgeyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6ICJodHRwOi8vc2lndjRleGFtcGxlYnVja2V0LnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRtbCJ9LCAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sICAgIHsieC1hbXotbWV0YS11dWlkIjogIjE0MzY1MTIzNjUxMjc0In0sICAgIHsieC1hbXotc2VydmVyLXNpZGUtZW5jcnlwdGlvbiI6ICJBRVMyNTYifSwgICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sICAgIHsieC1hbXotY3JlZGVudGlhbCI6ICJBS0lBSU9TRk9ETk43RVhBTVBMRS8yMDE1MTIyOS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0sICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwgICAgeyJ4LWFtei1kYXRlIjogIjIwMTUxMjI5VDAwMDAwMFoiIH0gIF19
and the following signature for it
1df5972015a56d4fdef92944436b91ce1f39b5cc684dcce9f4dab74b82734e84
which are different from the ones provided by Amazon in the above link.
Am I missing something? I have a feeling that the String format in the policy_document variable might be messing things up, but no matter how I format it (i.e. new lines, escaping etc.) I can't seem to get it working.
Decode Amazon's and yours, they are not the same, mainly in formatting. Simple formatting differences will result in a different signing hash.
In your case you need to add newline characters at the end of each line.
Amazon
{ "expiration": "2015-12-30T12:00:00.000Z",
"conditions": [
{"bucket": "sigv4examplebucket"},
["starts-with", "$key", "user/user1/"],
{"acl": "public-read"},
{"success_action_redirect": "http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html"},
["starts-with", "$Content-Type", "image/"],
{"x-amz-meta-uuid": "14365123651274"},
{"x-amz-server-side-encryption": "AES256"},
["starts-with", "$x-amz-meta-tag", ""],
{"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-date": "20151229T000000Z" }
]
}
Yours:
{ "expiration": "2015-12-30T12:00:00.000Z", "conditions": [ {"bucket": "sigv4examplebucket"}, ["starts-with", "$key", "user/user1/"], {"acl": "public-read"}, {"success_action_redirect": "http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html"}, ["starts-with", "$Content-Type", "image/"], {"x-amz-meta-uuid": "14365123651274"}, {"x-amz-server-side-encryption": "AES256"}, ["starts-with", "$x-amz-meta-tag", ""], {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request"}, {"x-amz-algorithm": "AWS4-HMAC-SHA256"}, {"x-amz-date": "20151229T000000Z" } ]}
'

Java Blowfish decrypt not giving original string back

I'm implementing a simple password store using Blowfish. All was fine until I tried out a few different password/key combinations and came across numerous instances where the decrypted values were still garbage.
Below is a standalone class that demonstrates the issue. I get the following output:
'Aaaaaaa7' encrypted: 'r?—èLèdÓ,·Ã¸ÍÒ'*
'Aaaaaaa7' decrypted: 'ñü=€¼(T'*
Any idea what I need to do to guarantee it always decrypts correctly.
(Using jce.jar in JDK 1.6.0_26)
Thanks,
David
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class BlowfishTwoWayHashImpl {
static {
test();
}
public static void test() {
String key = "wibble";
String passwordToEnrypt = "Aaaaaaa7";
String enc = BlowfishTwoWayHashImpl.encryptBlowfish(passwordToEnrypt, key);
System.out.println("'" + passwordToEnrypt + "' encrypted: '" + enc + "'");
String dec = BlowfishTwoWayHashImpl.decryptBlowfish(enc, key);
System.out.println("'" + passwordToEnrypt + "' decrypted: '" + dec + "'");
}
private static final String CIPHER_NAME = "Blowfish";
public static String encryptBlowfish(String toEncrypt, String key) {
return processString(toEncrypt, key, Cipher.ENCRYPT_MODE);
}
public static String decryptBlowfish(String toDecrypt, String key) {
return processString(toDecrypt, key, Cipher.DECRYPT_MODE);
}
private static String processString(String toEncrypt, String key, int encryptDecryptMode) {
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), CIPHER_NAME);
Cipher cipher;
try {
cipher = Cipher.getInstance(CIPHER_NAME);
cipher.init(encryptDecryptMode, secretKeySpec);
return new String(cipher.doFinal(toEncrypt.getBytes()));
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
}
Don't do this:
return new String(cipher.doFinal(toEncrypt.getBytes()));
You're using the platform default encoding all over the place in your code. Don't do this. It will lose data.
When you're converting genuine text to bytes (e.g. on encryption) use a specific charset - UTF-8 is a good choice. Use the same charset to decode from "encoded text" to String.
When you're converting arbitrary binary data to text, use base64 encoding, e.g. via this public domain Base64 encoding library.
Basically, when you create a new string with the String(byte[]) or String(byte[], String) constructors, you're saying, "This is genuine text data - please just decode it as a string." When the data is actually the result of encryption, it's not text data... it's an arbitrary bunch of bytes.

Categories

Resources