How to encrypt or tokenize a username and date token? - java

Need to pass a tokenized (encrypted) username and date from webapp A to webapp B via a url parameter. Something like http://webappB?username=userA&timestamp=13445341313 should be sent as http://webappB?token=geufjsggtj26hjdhcjre87klj3. The receiving webapp B should be able to decode the token into the original parameters.
Which technology offers a simple solution that is available for .NET and java? Thanks

I would like to share the solution that I found after some more research.
I chose a very simple symmetric XOR based scramble method in favour of using encryption across platforms.
A piece of code says more than thousand words :
// webappA, encode URL parameter
byte[] userBytes = username.getBytes("UTF-8");
byte[] keyBytes = key.getBytes("UTF-8");
//XOR scramble
byte[] encrypted = new byte[userBytes.length];
for(int i = 0; i < userBytes.length; i++){
encrypted[i] = (byte)(userBytes[i] ^ keyBytes[i % keyBytes.length]);
}
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(encrypted);
// webappB, decode the parameter
BASE64Decoder decoder = new BASE64Decoder();
byte[] decoded = decoder.decodeBuffer( encoded );
//XOR descramble
byte[] decrypted = new byte[decoded.length];
for(int i = 0; i < decoded.length; i++){
decrypted[i] = (byte)(decoded[i] ^ keyBytes[i % keyBytes.length] );
}

What you've suggested is very simple and doesn't require including technologies outside of what Java and .NET already offer. Simply build up an HTTP request, fire it to the right URL, and listen for the response.
Class References
Java: HttpURLConnectionOracle
.NET: WebRequestMSDN
If you think you'll be doing more of this, or the data gets more frequent, complex, or structured, I highly recommend the ubiquitous SOAPWikipedia protocol for extensibility and modularity.

Related

JSP(Java): Encoding byte array and use in JavaScript same in C#

I use this code in C#.net to send challenge to web page.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
Byte[] rnd = new Byte[64];
rng.GetBytes(rnd);
hidChallenge.Value = Encoding.Unicode.GetString(rnd);
And I in java script use of it.
var base64str = document.getElementById("<%=hidChallenge.ClientID %>");
When run and debug:
base64str = 感≗좦短䗅燛梻脕冔춇噙풣訋詇蹘᧩쾏휇᯸늸䫐顨◣希ࠟ䠎ᐷ
But in java (JSP)
I use this code:
Random r = new Random();
byte[] rndbyte = new byte[64];
r.nextBytes(rndbyte);
String challenge = new String(rndbyte,StandardCharsets.UTF_16LE);
session.setAttribute("challenge", challenge);
And in javascript:
var base64str = 퓻�ꦖ쁳春꼪ꝝ䣇͋ꟼ鱐䆺㺪᠁郷̣攺줶ꋏ歮㏹㬎ꢔ崬魔弝孓翊
I try follow charset also:
US_ASCII
UTF_8
UTF_16
So I get base 64 string error.
it sounds like there is a confusion between what UTF-8/16 or Ascii are for, and Base64.
UTF-8 is meant to encode string to byte sequence. And Base64 is meant to encode byte sequence to string.
If you want to generate base64 in Java, here is how it should look like:
Random r = new Random();
byte[] rndbyte = new byte[64];
r.nextBytes(rndbyte);
String challenge = Base64.encodeBase64String(rndbyte);
session.setAttribute("challenge", challenge);
Here is another post that explain pretty good the difference, if you want to know more about this:
What's the difference between UTF8/UTF16 and Base64 in terms of encoding

Generating a dynamic password reset link

To reset my password I want to send the user a link to site/account/{hash} where {hash} is a hash of the user's password and a timestamp.
I have the following code to hash only the email and have a readable link:
String check = info.mail;
MessageDigest md = MessageDigest.getInstance("SHA-1");
String checkHash = Base64.encodeBase64String(md.digest(check.getBytes()));
if(checkHash.equals(hash)){
return ResponseEntity.ok("Password reset to: " + info.password);
}else{
return ResponseEntity.ok("Hash didn't equal to: " + checkHash);
}
The problem is that when I convert this to Base64 it may include / signs what will mess up my links and checking of the hash.
I can simply replace any unwanted signs by something else after the hashing but is there some other way to have your hash only include a certain part of codes?
Also I know the returns are still sent unsafe but this is just for testing and debugging.
The RFC 3548 specifies a variant often called "base64url" specifically designed for that purpose. In this variant, + and / are replaced by - and _.
Java 8 has built-in support with the new Base64 class. If you're stuck with an older version, the Base64 class of Apache Commons can be configured to be url safe by using the new Base64(true) constructor.
Other options might be:
Don't use Base64, but transfer the bytes as hexadecimal
representation (which will not contain any special characters):
String checkHash = toHex(md.digest(check.getBytes()));
with
private static String toHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
Use URL encoding/decoding on the generated hash (that's what you already know)

Java and Php returns different hashes

So, PHP code:
$result = hash("whirlpool","xxx".$password."zzz");
JAVA:
import gnu.crypto.Registry;
import gnu.crypto.hash.HashFactory;
import gnu.crypto.hash.IMessageDigest;
public class WhirlpoolHash {
String result;
WhirlpoolHash(String pass) {
String to_encode = "xxx"+pass+"zzz";
IMessageDigest old_encoder = HashFactory.getInstance(Registry.WHIRLPOOL_HASH);
byte[] input = to_encode.getBytes();
old_encoder.update(input, 0, input.length);
byte[] digest = old_encoder.digest();
this.result = gnu.crypto.util.Util.toString(digest).toLowerCase();
}
public String Get() {
return this.result;
}
}
And the result vars are different. I need java class to return the same value as php does.
I have passwords stored in MySQL DB UTF-8 encoded generated by PHP and need to compare it with data sent by JavaFX app.
Of course i can send unencrypted password, and do it with php but I dont whant to.
So Java example for encrypting pwd with whirlpool algorithm using gnu-crypto jar was an answer.
I dont know why but jonelo.jacksum.JacksumAPI gives the result same as PHP.
Late response, but in case it helps someone else.
I had almost the exact same issue and used Bouncy Castle in Java. After some trial and error, I got the hashes with Whirlpool to match my PHP hash, which looked similar to yours. Assuming you pass in the password:
WhirlpoolDigest messageDigest = new WhirlpoolDigest();
final String convertedHash = "xxx" + password + "yyy";
messageDigest.reset();
final byte[] bytes = convertedHash.getBytes();
messageDigest.update(bytes, 0, bytes.length);
byte[] hash = new byte[messageDigest.getDigestSize()];
messageDigest.doFinal(hash, 0);
System.out.println(Hex.toHexString(hash));
The biggest issue for me was the final steps - the doFinal() and the Hex.toHexString() ...
My maven dependency looked like this:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk15on</artifactId>
<version>1.64</version>
</dependency>

JAVA: failing to get encrypted data in string using xor

I was trying to print encrypted text using string perhaps i was wrong somewhere. I am doing simple xor on a plain text. Coming encrypted text/string i am putting in a C program and doing same xor again to get plain text again.
But in between, I am not able to get proper string of encrypted text to pass in C
String xorencrypt(byte[] passwd,int pass_len){
char[] st = new char[pass_len];
byte[] crypted = new byte[pass_len];
for(int i = 0; i<pass_len;i++){
crypted[i] = (byte) (passwd[i]^(i+1));
st[i] = (char)crypted[i];
System.out.println((char)passwd[i]+" "+passwd[i] +"= " + (char)crypted[i]+" "+crypted[i]);/* characters are printed fine but problem is when i am convering it in to string */
}
return st.toString();
}
I don't know if any kind of encoding also needed because if i did so how I will decode and decrypt from C program.
example if suppose passwd = bond007
then java program should return akkb78>
further C program will decrypt akkb78> to bond007 again.
Use
return new String(crypted);
in that case you don't need st[] array at all.
By the way, the encoded value for bond007 is cmm`560 and not what you posted.
EDIT
While solution above would most likely work in most java environments, to be safe about encoding,
as suggested by Alex, provide encoding parameter to String constructor.
For example if you want your string to carry 8-bit bytes :
return new String(crypted, "ISO-8859-1");
You would need the same parameter when getting bytes from your string :
byte[] bytes = myString.getBytes("ISO-8859-1")
Alternatively, use solution provided by Alex :
return new String(st);
But, convert bytes to chars properly :
st[i] = (char) (crypted[i] & 0xff);
Otherwise, all negative bytes, crypted[i] < 0 will not be converted to char properly and you get surprising results.
Change this line:
return st.toString();
with this
return new String(st);

HTML5 Websocket Server handshake (v.76) (Java)

I'm trying to build a Java-based HTML5 websocket server (v76) and have problems with the handshake. There are a few opensource Java solutions that supposedly support v76 but none of them seem to work.
I am certain my handshake response is correct (at least calculating the two key's responses). My question: Is Java by default Big Endian? Since the concatenation of the two key answers + the response bytes is the handshake answer, I'm having to do multiple type conversions (string to int, concat two ints into a string, then convert to byte and concat with the response bytes, then MD5 encoding), is there something in particular I need to be looking for? My response always seems accurate using Wireshark (# of bytes), but since the clients have no debug information it's hard to tell why my handshakes are failing.
Any supporting answers or working code would be EXTREMELY valuable to me.
Hey, this is a working example of the handshake producer for websockets version 76. If you use the example from the spec (http://tools.ietf.org/pdf/draft-hixie-thewebsocketprotocol-76.pdf) and print the output as a String, it produces the correct answer.
public byte[] getHandshake (String firstKey, String secondKey, byte[] last8)
{
byte[] toReturn = null;
//Strip out numbers
int firstNum = Integer.parseInt(firstKey.replaceAll("\\D", ""));
int secondNum = Integer.parseInt(secondKey.replaceAll("\\D", ""));
//Count spaces
int firstDiv = firstKey.replaceAll("\\S", "").length();
int secondDiv = secondKey.replaceAll("\\S", "").length();
//Do the division
int firstShake = firstNum / firstDiv;
int secondShake = secondNum / secondDiv;
//Prepare 128 bit byte array
byte[] toMD5 = new byte[16];
byte[] firstByte = ByteBuffer.allocate(4).putInt(firstShake).array();
byte[] secondByte = ByteBuffer.allocate(4).putInt(secondShake).array();
//Copy the bytes of the numbers you made into your md5 byte array
System.arraycopy(firstByte, 0, toMD5, 0, 4);
System.arraycopy(secondByte, 0, toMD5, 4, 4);
System.arraycopy(last8, 0, toMD5, 8, 8);
try
{
//MD5 everything together
MessageDigest md5 = MessageDigest.getInstance("MD5");
toReturn = md5.digest(toMD5);
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return toReturn;
}
I wrote this so feel free to use it where ever.
EDIT: Some other problems I ran into - You MUST write the 'answer' to the handshake as bytes. If you try to write it back to the stream as a String it will fail (must be something to do with char conversion?). Also, make sure you're writing the rest of the response to the handshake exactly as it shows in the spec.
Jetty 7 supports web sockets, and is open source. You might find inspiration (but I would suggest you just embed Jetty in your application and be done with it).
http://blogs.webtide.com/gregw/entry/jetty_websocket_server
You can try my implementation:
https://github.com/TooTallNate/Java-WebSocket
It supports draft 75 and 76 currently. Verified with current versions of Chrome and Safari. Good luck!

Categories

Resources