Skip to content

Instantly share code, notes, and snippets.

@kencoba
Created June 14, 2011 10:13
Show Gist options
  • Save kencoba/1024627 to your computer and use it in GitHub Desktop.
Save kencoba/1024627 to your computer and use it in GitHub Desktop.
IPSJ problem: public key encoding
/*
* 共通鍵暗号化
* 仕様:
* キー = {キーの長さ,左循環シフト回数,キー本体}
* 平文 = byte列
* 暗号化操作
*  1.平文を、キー本体のサイズごとに分割し、部分平文を作る
* 2.部分平文に対し、左循環シフト回数分、左循環シフトし、シフト文を作る
* 3.シフト文とキー本体のxorをとり、暗号化部分バイト列を作る
* 4.暗号化部分バイト列を結合し、暗号化文を作る
*/
public class PublicKeyEncoder {
public static void main(String[] args) {
byte[] key = {0x05,0x02,(byte)0xF0,(byte)0xed,0x1c};
byte[] src = {(byte)0xf2,0x34,0x0c,0x5c,0x1d};
System.out.print("\nkey: ");
print(key);
System.out.print("\nsrc: ");
print(src);
byte[] encoded = encode(key,src);
System.out.print("\nencoded:");
print(encoded);
byte[] decoded = decode(key,encoded);
System.out.print("\ndecoded:");
print(decoded);
}
static byte[] encode(byte[] key, byte[] src) {
int keyLength = key[0];
int rotateSize = key[1];
int[] keyBody = getKeyBody(key);
byte[][] splitedSrc = split(src, key.length - 2);
byte[] dest = new byte[src.length];
int i = 0;
for (byte[] s : splitedSrc) {
byte[] encoded =
toByteArray(xor(keyBody, leftRotate(rotateSize, toIntArray(s))));
System.arraycopy(encoded,0,dest,i,encoded.length);
i += encoded.length;
}
return dest;
}
static byte[] decode(byte[] key, byte[] src) {
int keyLength = key[0];
int rotateSize = key[1];
int[] keyBody = getKeyBody(key);
byte[][] splitedSrc = split(src, key.length - 2);
byte[] dest = new byte[src.length];
int i = 0;
for (byte[] s : splitedSrc) {
byte[] decoded =
toByteArray(rightRotate(rotateSize, xor(keyBody, toIntArray(s))));
System.arraycopy(decoded,0,dest,i,decoded.length);
i += decoded.length;
}
return dest;
}
static byte[] toByteArray(int[] src) {
int size = src.length / 8;
byte[] dest = new byte[size];
for (int i = 0; i < dest.length; i++) {
int[] subsrc = sub(src, i * 8, 8);
dest[i] = toByte(subsrc);
}
return dest;
}
static int[] sub(int[] src,int start,int length) {
int[] dest = new int[length];
System.arraycopy(src,start,dest,0,dest.length);
return dest;
}
static void print(int[] data) {
for (int d : data) {
System.out.print(d);
}
}
static void print(byte[] data) {
int j = 0;
for (int i: toIntArray(data)){
System.out.print(i);
j++;
if (j > 7) { System.out.print(" "); j = 0; }
}
}
static void print(byte[][] data) {
for (byte[] d : data) {
print(d);
System.out.println();
}
}
static byte[][] split(byte[] src, int eachLength) {
int size = src.length / eachLength;
size = (src.length % eachLength) != 0 ? size + 1 : size;
byte[][] splited = new byte[size][eachLength];
// キー本体の長さで割り切れない部分の配列を生成する。
if (src.length % eachLength != 0) {
splited[splited.length - 1] = new byte[src.length % eachLength];
}
for (int i = 0; i < splited.length; i++) {
System.arraycopy(src, i * eachLength, splited[i], 0, splited[i].length);
}
return splited;
}
/**
* 暗号キーの本体を得る
**/
static int[] getKeyBody(byte[] key) {
int bodyLength = key[0] - 2;
byte[] keyBody = new byte[bodyLength];
System.arraycopy(key, 2, keyBody, 0, keyBody.length);
return toIntArray(keyBody);
}
/**
* xorをとる
**/
static int[] xor(int[] bits1, int[] bits2) {
int length = bits1.length < bits2.length ? bits1.length : bits2.length;
int[] dest = new int[length];
for (int i = 0; i < dest.length; i++) {
dest[i] = bits1[i] ^ bits2[i];
}
return dest;
}
/**
* 右ローテートする
**/
static int[] rightRotate(int rotateSize, int[] src) {
int[] dest = new int[src.length];
System.arraycopy(src, src.length - rotateSize, dest, 0, rotateSize);
System.arraycopy(src, 0, dest, rotateSize, dest.length - rotateSize);
return dest;
}
/**
* 左ローテートする
**/
static int[] leftRotate(int rotateSize, int[] src) {
int[] dest = new int[src.length];
System.arraycopy(src, rotateSize, dest, 0, dest.length - rotateSize);
System.arraycopy(src, 0, dest, dest.length - rotateSize, rotateSize);
return dest;
}
/**
* 配列要素を逆転した配列を返す
**/
static int[] reverse(int[] src) {
int[] dest = new int[src.length];
for (int i = dest.length - 1; i >= 0; i--) {
dest[i] = src[src.length - 1 - i];
}
return dest;
}
/**
* byte配列をint配列に変換する
* 最上位ビット=int[0]
**/
static int[] toIntArray(byte[] src) {
int[] dest = new int[src.length * 8];
for (int i = 0; i < src.length; i++) {
int[] d = toIntArray(src[i]);
System.arraycopy(d, 0, dest, i * 8, 8);
}
return dest;
}
/**
* byteをint配列に変換する。
* 最上位ビット=int[0]
**/
static int[] toIntArray(byte src) {
int[] dest = new int[8];
for (int i = 0; i < dest.length; i++) {
dest[i] = (src & 1 << i) > 0 ? 1 : 0;
}
return reverse(dest);
}
/**
* int[]をbyteに変換する
* int[0]=最上位ビット
**/
static byte toByte(int[] src) {
int[] src2 = reverse(src);
byte dest = 0;
for (int i = 0; i < 8; i++) {
dest |= src2[i] << i;
}
return dest;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment