Created
January 9, 2014 08:50
-
-
Save gregopet/8331291 to your computer and use it in GitHub Desktop.
Helper class for the Coursera Cryptography course
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
/** | |
* Represents a byte sequence. | |
*/ | |
class ByteSeq { | |
protected List sequence | |
/** | |
* Default constructor, creates an empty byte sequence. | |
*/ | |
public ByteSeq() { | |
sequence = [] | |
} | |
/** | |
* Constructs a hex string from the internal state. | |
*/ | |
String getHex() { | |
sequence.collect{ Integer.toHexString(it).padLeft(2, "0") }.join() | |
} | |
/** | |
* Constructs a byte sequence from a String representation. | |
*/ | |
void setHex(String hex) { | |
sequence = (hex.chars as List) | |
.collate(2,2,true) | |
.collect { Integer.parseInt(""+it[0]+it[1], 16) } as List | |
} | |
/** | |
* Sets the characters of this ASCII String as the source for the byte sequence. | |
*/ | |
String getAscii() { | |
new String(sequence.toArray() as Byte[]) | |
} | |
/** | |
* Gets the ASCII String encoded by this byte sequence. | |
*/ | |
void setAscii(String ascii) { | |
sequence = ascii.bytes | |
} | |
/** | |
* Support index access to bytes. | |
*/ | |
Byte getAt(int idx) { | |
sequence[idx] | |
} | |
void putAt(int idx, Number val) { | |
sequence[idx] = val | |
} | |
void putAt(int idx, String val) { | |
if (val.size() == 1) sequence[idx] = (int)val[0] | |
else throw new IllegalArgumentException("Cannot place more than 1 character into a single byte location!") | |
} | |
/** | |
* Bytewise XOR of two ByteSeq instances. | |
* @return A new ByteSeq instance. | |
*/ | |
public ByteSeq xor(ByteSeq other) { | |
def xored = new ByteSeq() | |
int minSize = Math.min(sequence.size(), other.sequence.size()) | |
for (int a = 0; a < minSize; a++) { | |
xored.sequence.push( (int)sequence[a] ^ (int)other.sequence[a] ) | |
} | |
return xored | |
} | |
/** | |
* Bytewise AND of two ByteSeq instances. | |
* @return A new ByteSeq instance. | |
*/ | |
public ByteSeq and(ByteSeq other) { | |
def xored = new ByteSeq() | |
int minSize = Math.min(sequence.size(), other.sequence.size()) | |
for (int a = 0; a < minSize; a++) { | |
xored.sequence.push( (int)sequence[a] & (int)other.sequence[a] ) | |
} | |
return xored | |
} | |
} | |
//generate sequence from ascii | |
def message = new ByteSeq(ascii:"We need more cake!") | |
println message.ascii //outputs: We need more cake! | |
println message.hex //outputs: 5765206e656564206d6f72652063616b6521 | |
//generate sequence from a hex string | |
def hexSequence = new ByteSeq(hex:"3f203f") | |
println hexSequence.hex //outputs: 3f203f | |
println hexSequence.ascii //outputs: ? ? | |
//manipulate individual bytes via numbers, as ascii characters or hex strings | |
message[17] = 0x3f | |
println message.ascii //outputs: We need more cake? | |
message[17] = "." | |
println message.ascii //outputs: We need more cake. | |
//XOR | |
def transform = new ByteSeq(hex:"00000000000000000000000000100e0a1500") | |
println( (message ^ transform).ascii ) //outputs: We need more soap. | |
//AND | |
transform.hex = "00000000000000000000000000FFFFFFFF00" | |
println( (message & transform).ascii ) //outputs: cake |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment