import java.util.*;
/**
* @see http://e...content-available-to-author-only...a.org/wiki/Merkle%E2%80%93Hellman_knapsack_cryptosystem
*/
public class Main {
// Extended Euclidean algorithm
private int eea(int e, int ph) {
int xprev = 1, x = 0;
int yprev = 0, y = 1;
int rprev = e, r = ph;
while(r != 0) {
int qnext = rprev / r;
int rnext = rprev % r;
int xnext = xprev - (qnext*x);
int ynext = yprev - (qnext*y);
xprev = x; x = xnext;
yprev = y; y = ynext;
rprev = r; r = rnext;
}
while(xprev < 0) {
xprev += ph;
}
return xprev;
}
private void doIt() {
// First, a superincreasing sequence w is created
int[] w = { 2, 7, 11, 21, 42, 89, 180, 354, };
// This is the basis for a private key. From this, calculate the sum.
int sum = 0;
for(int n : w) { sum += n; }
// Then, choose a number q that is greater than the sum.
int q = 881;
// Also, choose a number r that is in the range and is coprime to q.
int r = 588;
// The private key consists of q, w and r.
// To calculate a public key, generate the sequence β by multiplying each element in w by r mod q
int[] b = new int[w.length];
for(int i=0; i<b.length; i++) {
b[i] = w[i] * r % q;
}
// Say Alice wishes to encrypt "a". First, she must translate "a" to binary (in this case, using ASCII or UTF-8)
char mes = 'a';
int sz = str.length();
for(int i=0; i<8-sz; i++) {
str = "0" + str;
}
// She multiplies each respective bit by the corresponding number in β
int crypt = 0;
for(int i=0; i<b.length; i++) {
crypt += b[i] * (str.charAt(i) - '0');
}
int r1 = eea(r, q);
// She sends this to the recipient.
// To decrypt, Bob multiplies 1129 by r^(-1) mod q
int decrypt = crypt * r1 % q;
// Now Bob decomposes 372 by selecting the largest element in w which is less than or equal to 372.
// Then selecting the next largest element less than or equal to the difference, until the difference is 0:
// The elements we selected from our private key correspond to the 1 bits in the message
StringBuilder s = new StringBuilder("00000000");
for(int i=0; i<8; i++) {
if(decrypt >= w[8-i-1]) {
s = s.replace(8-i-1, 8-i, "1");
decrypt -= w[8-i-1];
}
}
int num
= Integer.
parseInt(s.
toString(),
2);
// When translated back from binary, this "a" is the final decrypted message.
char res = (char)num;
}
public static void main
(String[] args
) { new Main().doIt();
}
}
aW1wb3J0IGphdmEudXRpbC4qOwoKLyoqCiAqIEBzZWUgaHR0cDovL2UuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmEub3JnL3dpa2kvTWVya2xlJUUyJTgwJTkzSGVsbG1hbl9rbmFwc2Fja19jcnlwdG9zeXN0ZW0KICovCnB1YmxpYyBjbGFzcyBNYWluIHsKCiAgICAvLyBFeHRlbmRlZCBFdWNsaWRlYW4gYWxnb3JpdGhtCiAgICBwcml2YXRlIGludCBlZWEoaW50IGUsIGludCBwaCkgewogICAgICAgIGludCB4cHJldiA9IDEsIHggPSAwOwogICAgICAgIGludCB5cHJldiA9IDAsIHkgPSAxOwogICAgICAgIGludCBycHJldiA9IGUsIHIgPSBwaDsKICAgICAgICB3aGlsZShyICE9IDApIHsKICAgICAgICAgICAgaW50IHFuZXh0ID0gcnByZXYgLyByOwogICAgICAgICAgICBpbnQgcm5leHQgPSBycHJldiAlIHI7CiAgICAgICAgICAgIGludCB4bmV4dCA9IHhwcmV2IC0gKHFuZXh0KngpOwogICAgICAgICAgICBpbnQgeW5leHQgPSB5cHJldiAtIChxbmV4dCp5KTsKICAgICAgICAgICAgeHByZXYgPSB4OyB4ID0geG5leHQ7CiAgICAgICAgICAgIHlwcmV2ID0geTsgeSA9IHluZXh0OwogICAgICAgICAgICBycHJldiA9IHI7IHIgPSBybmV4dDsKICAgICAgICB9CiAgICAgICAgd2hpbGUoeHByZXYgPCAwKSB7CiAgICAgICAgICAgIHhwcmV2ICs9IHBoOwogICAgICAgIH0KICAgICAgICByZXR1cm4geHByZXY7CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGRvSXQoKSB7CiAgICAgICAgLy8gRmlyc3QsIGEgc3VwZXJpbmNyZWFzaW5nIHNlcXVlbmNlIHcgaXMgY3JlYXRlZAogICAgICAgIGludFtdIHcgPSB7IDIsIDcsIDExLCAyMSwgNDIsIDg5LCAxODAsIDM1NCwgfTsKCiAgICAgICAgLy8gVGhpcyBpcyB0aGUgYmFzaXMgZm9yIGEgcHJpdmF0ZSBrZXkuIEZyb20gdGhpcywgY2FsY3VsYXRlIHRoZSBzdW0uCiAgICAgICAgaW50IHN1bSA9IDA7CiAgICAgICAgZm9yKGludCBuIDogdykgeyBzdW0gKz0gbjsgfQoKICAgICAgICAvLyBUaGVuLCBjaG9vc2UgYSBudW1iZXIgcSB0aGF0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgc3VtLgogICAgICAgIGludCBxID0gODgxOwoKICAgICAgICAvLyBBbHNvLCBjaG9vc2UgYSBudW1iZXIgciB0aGF0IGlzIGluIHRoZSByYW5nZSBhbmQgaXMgY29wcmltZSB0byBxLgogICAgICAgIGludCByID0gNTg4OwoKICAgICAgICAvLyBUaGUgcHJpdmF0ZSBrZXkgY29uc2lzdHMgb2YgcSwgdyBhbmQgci4KICAgICAgICAKICAgICAgICAvLyBUbyBjYWxjdWxhdGUgYSBwdWJsaWMga2V5LCBnZW5lcmF0ZSB0aGUgc2VxdWVuY2UgzrIgYnkgbXVsdGlwbHlpbmcgZWFjaCBlbGVtZW50IGluIHcgYnkgciBtb2QgcQogICAgICAgIGludFtdIGIgPSBuZXcgaW50W3cubGVuZ3RoXTsKICAgICAgICBmb3IoaW50IGk9MDsgaTxiLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGJbaV0gPSB3W2ldICogciAlIHE7CiAgICAgICAgfQogICAgICAgIAogICAgICAgIC8vIFNheSBBbGljZSB3aXNoZXMgdG8gZW5jcnlwdCAiYSIuIEZpcnN0LCBzaGUgbXVzdCB0cmFuc2xhdGUgImEiIHRvIGJpbmFyeSAoaW4gdGhpcyBjYXNlLCB1c2luZyBBU0NJSSBvciBVVEYtOCkKICAgICAgICBjaGFyIG1lcyA9ICdhJzsKICAgICAgICBTdHJpbmcgc3RyID0gSW50ZWdlci50b0JpbmFyeVN0cmluZyhtZXMpOwogICAgICAgIGludCBzeiA9IHN0ci5sZW5ndGgoKTsKICAgICAgICBmb3IoaW50IGk9MDsgaTw4LXN6OyBpKyspIHsKICAgICAgICAgICAgc3RyID0gIjAiICsgc3RyOwogICAgICAgIH0KCiAgICAgICAgLy8gU2hlIG11bHRpcGxpZXMgZWFjaCByZXNwZWN0aXZlIGJpdCBieSB0aGUgY29ycmVzcG9uZGluZyBudW1iZXIgaW4gzrIKICAgICAgICBpbnQgY3J5cHQgPSAwOwogICAgICAgIGZvcihpbnQgaT0wOyBpPGIubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgY3J5cHQgKz0gYltpXSAqIChzdHIuY2hhckF0KGkpIC0gJzAnKTsKICAgICAgICB9CiAgICAgICAgaW50IHIxID0gZWVhKHIsIHEpOwoKICAgICAgICAvLyBTaGUgc2VuZHMgdGhpcyB0byB0aGUgcmVjaXBpZW50LgogICAgICAgIC8vIFRvIGRlY3J5cHQsIEJvYiBtdWx0aXBsaWVzIDExMjkgYnkgcl4oLTEpIG1vZCBxCiAgICAgICAgaW50IGRlY3J5cHQgPSBjcnlwdCAqIHIxICUgcTsKCiAgICAgICAgLy8gTm93IEJvYiBkZWNvbXBvc2VzIDM3MiBieSBzZWxlY3RpbmcgdGhlIGxhcmdlc3QgZWxlbWVudCBpbiB3IHdoaWNoIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byAzNzIuCiAgICAgICAgLy8gVGhlbiBzZWxlY3RpbmcgdGhlIG5leHQgbGFyZ2VzdCBlbGVtZW50IGxlc3MgdGhhbiBvciBlcXVhbCB0byB0aGUgZGlmZmVyZW5jZSwgdW50aWwgdGhlIGRpZmZlcmVuY2UgaXMgMDoKICAgICAgICAvLyBUaGUgZWxlbWVudHMgd2Ugc2VsZWN0ZWQgZnJvbSBvdXIgcHJpdmF0ZSBrZXkgY29ycmVzcG9uZCB0byB0aGUgMSBiaXRzIGluIHRoZSBtZXNzYWdlCiAgICAgICAgU3RyaW5nQnVpbGRlciBzID0gbmV3IFN0cmluZ0J1aWxkZXIoIjAwMDAwMDAwIik7CiAgICAgICAgZm9yKGludCBpPTA7IGk8ODsgaSsrKSB7CiAgICAgICAgICAgIGlmKGRlY3J5cHQgPj0gd1s4LWktMV0pIHsKICAgICAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoOC1pLTEsIDgtaSwgIjEiKTsKICAgICAgICAgICAgICAgIGRlY3J5cHQgLT0gd1s4LWktMV07CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGludCBudW0gPSBJbnRlZ2VyLnBhcnNlSW50KHMudG9TdHJpbmcoKSwgMik7CgogICAgICAgIC8vIFdoZW4gdHJhbnNsYXRlZCBiYWNrIGZyb20gYmluYXJ5LCB0aGlzICJhIiBpcyB0aGUgZmluYWwgZGVjcnlwdGVkIG1lc3NhZ2UuCiAgICAgICAgY2hhciByZXMgPSAoY2hhciludW07CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKHJlcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewogICAgICAgIG5ldyBNYWluKCkuZG9JdCgpOwogICAgfQp9