Solved

SecretKeySpec mac and base64

Posted on 2012-03-15
11
1,024 Views
Last Modified: 2012-03-15
I have a secret key which is already in base64 format.

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKey;
import java.security.Key;

              String key = "<base 64 encoded string>";
              String key_1 =  Base64.decode(key);
              try {
                  Mac mac = Mac.getInstance("HmacSHA1");
                  SecretKey secretKey  = new SecretKeySpec(key_1.getBytes("UTF-8"),"HmacSHA1");
                   
                  mac.init(secretKey);
                  String enc = new String(mac.doFinal());

                  // Base 64 Encode the results
                  String retVal = Base64Codec.encode(enc);
                  System.out.println ("result: " + retVal);
              } catch (Exception e) {
                  System.out.println(e.getMessage());
              }

The output I am getting  "result: "  is not matching with the output when I execute an equivalent code in python

I am sure something to do with byte array conversion in java and string but cant figure it


NOTE: If I don't do base64 decode and use "new SecretKeySpec(key.getBytes)"
then the output of "result: " is same in java and output from python code.
0
Comment
Question by:learningunix
  • 6
  • 5
11 Comments
 
LVL 35

Expert Comment

by:mccarl
ID: 37727439
I am not sure what the question is then since you have solved it with your statement...

If I don't do base64 decode and use "new SecretKeySpec(key.getBytes)"
then the output of "result: " is same in java and output from python code.

Your python code is maybe automatically doing the Base64 encode when it create the SecretKeySpec equivalent? I don't know because a) you have posted the python code, and b) I don't know a lot of python anyway ;)
0
 

Author Comment

by:learningunix
ID: 37727488
The python code does base64decode first. I am trying to mimic the code in java.
python uses "base64" and "hmac" library
0
 

Author Comment

by:learningunix
ID: 37727499
I am sure something to do with base64decode as it coverts to binary on windows and something is getting messed up.  The python I am runing is on linux machine
0
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
LVL 35

Expert Comment

by:mccarl
ID: 37727503
Ok, maybe your statement is a bit unclear... when you said
If I don't do base64 decode and use "new SecretKeySpec(key.getBytes)"
did you mean that when you don't do base64 decode in both java and python the results come out the same?

(I thought that you were saying that when the python code DOES do the bas64 decode and the Java DOESN'T do the decode, that the results line up)
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37727516
What are you using to do your Base64 conversion?

I would say that you are on the mark with byte array conversions being the issue. It is strange that your Base64.decode(key) returns a String, it should really return a byte[] so that no further conversion needs to happen. Yeah, the problem that you are having is because the bytes will be converted to String and then back again at .getBytes("UTF-8") but various encoding schemes will conspire to change the actual bytes on the way through.
0
 

Author Comment

by:learningunix
ID: 37727519
may be i confused u. let me explain it again.

the exact above Java code is running on windows. An exact identical code in python runs from unix.

the value of result does not match.

not sure if something to do with charset on windows
0
 

Author Comment

by:learningunix
ID: 37727544
The issue is definitely with java. I just installed python on y windows machine and I get same value for "result" when I run python on unix

Not sure why Java won't give me same reuslt. something to with getBytes or new String() which is messing up
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37727563
Yeah, I understood that part ok. The part that wasn't clear was the NOTE: right at the end of the original question. (That's what I was referring to in the above comment)

Anyway, regardless, I think the issue is still what I wrote about above... So again, what are you using to do the Base64 conversion? A library? Your own code?


Hang on a sec, you just mentioned "new String()" and this made me check your code again, and yes there is an issue there to. The byte[] returned from mac.doFinal() is being converted to a String aswell. This byte[] should also just be passed directly from mac.doFinal() to base64 encode(), not via a String!
0
 

Author Comment

by:learningunix
ID: 37727583
I found the solution, I knew it was charset issue.
the correct solution is

SecretKey secretKey  = new SecretKeySpec(key_1.getBytes("ISO-8859-1"),"HmacSHA1");
String enc = new String(mac.doFinal(), "ISO-8859-1");


PS: I have my own base 64 which accepts string only
0
 
LVL 35

Accepted Solution

by:
mccarl earned 500 total points
ID: 37727639
NO, the solution is to NOT convert to string at all. You will only be setting yourself for more issues down the track, ie. remembering to use the correct encoding everywhere, or someone changing the encoding unknowingly because it isn't clear what is going. On top of that is the lack of efficiency as you needlessly convert to string and back again.

Change you Base64 routines to encode from a byte[] and to decode back to a byte[] and save yourself all this unnecessary heart ache!!
0
 

Author Closing Comment

by:learningunix
ID: 37727666
Thanks
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question