package edu.washington.cs.publickey;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.LinkedList;
import java.util.List;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.Base64;
public class Tools {
public final static byte[] SHA1_SEED = Base64.decode("jRofQW+cWzw0ESusBZ4eO0Zm4ZuTWt1j" + "nqpIS5UDMAt3QPluOWenQUy2RZzvJJv1" + "ab5QyEqfFrEQVRcWEDun+mb9051wtHZD" + "gt0vMbVOWLdX/Ptd7C/aZUiIcgpWqaR6" + "ruv6s6ZO7xWXHP/ZU+HbWIUXg7eFCj4B" + "+WBtbm319fcH0A/kAeUsRFBUSOh3K/Qf" + "DvQpAPVG730acxWQTKbkNg4CmPi5iVmd" + "9ow0QwPntAMw0wMocP3DBWbuqM1hrQ4d" + "wWSef52A52PV4qTQjus9vc1T7Br8fDOG" + "3NK8CwzB1bgH72tuj13Go8CCNwHksLWm" + "6wJwEPbRLt4/NUXBIYdv9CbEmBMDc601" + "i7Y/9IKhIW01fAatjZwTM5aTsQ1qj+BZ" + "S9z384SQ1d6QAQN5Gz0GxXcaQJdGN7M3" + "rTmP4SMebOwGPR99MBG8zStNzcoVC/mk" + "JTjJFXYtqNWTtWMefMZCY8vBjk43Oslt");
public static class AcceptAllFilter implements PacketFilter {
public boolean accept(Packet packet) {
return true;
}
}
public final static String DEFAULT_PUBLIC_KEY_SERVER = "publickey.cs.washington.edu@gmail.com";
// sent in the client hello
public final static String PUBLICKEY_PAYLOAD_KEY__PublicKeyFriend = "PUBLICKEY_PAYLOAD_PUBLIC_KEY";
// sent the in server challenge
public final static String PUBLICKEY_PAYLOAD_NOUNCE__base64_byte_array = "PUBLICKEY_PAYLOAD_NOUNCE";
// sent in the client request
public final static String PUBLICKEY_PAYLOAD_SIGNATURE__String_Base64 = "PUBLICKEY_PAYLOAD_SIGNATURE";
public final static String PUBLICKEY_PAYLOAD_FRIENDS__MergeSha1_Base64 = "PUBLICKEY_PAYLOAD_FRIENDS";
public final static String PUBLICKEY_PAYLOAD_KNOWN_KEYS__MergeSha1_Base64 = "PUBLICKEY_PAYLOAD_KNOWN_KEYS";
// send in the server response
public final static String PUBLICKEY_PAYLOAD_FRIENDS_KEYS__PublicKeyFriend_array = "PUBLICKEY_PAYLOAD_FRIENDS_KEYS";
private static MessageDigest md;
static {
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static byte[] getSha1(String networkUid) throws NoSuchAlgorithmException, UnsupportedEncodingException {
if (networkUid.contains("/")) {
String newId = networkUid.split("/")[0];
// System.out.println("converting: " + networkUid + "->" + newId);
networkUid = newId;
}
return getSha1(networkUid.getBytes());
}
public static byte[] getSha1(byte[] bytes) throws NoSuchAlgorithmException, UnsupportedEncodingException {
md.update(SHA1_SEED);
md.update(bytes, 0, bytes.length);
byte[] sha1hash = md.digest();
md.reset();
return sha1hash;
}
public static List<byte[]> getListSha1(String mergedSha1s) {
byte[] merged = Base64.decode(mergedSha1s);
if (merged.length % 20 != 0) {
throw new RuntimeException("error, only 20 byte sha1 allowed: " + merged.length + " mod 20!=0");
}
List<byte[]> listOfSha1s = new LinkedList<byte[]>();
for (int i = 0; i < merged.length / 20; i++) {
byte[] sha1 = new byte[20];
System.arraycopy(merged, i * 20, sha1, 0, 20);
listOfSha1s.add(sha1);
}
return listOfSha1s;
}
public static String mergeSha1sAndBase64(List<byte[]> listOfSha1s) {
byte[] merged = new byte[listOfSha1s.size() * 20];
for (int i = 0; i < listOfSha1s.size(); i++) {
if (listOfSha1s.get(i).length != 20) {
throw new RuntimeException("only 20 byte sha1 hashes is allowed");
}
System.arraycopy(listOfSha1s.get(i), 0, merged, i * 20, 20);
}
return Base64.encodeBytes(merged, Base64.DONT_BREAK_LINES);
}
public static PublicKey keyForEncodedBytes(byte[] inBytes) throws InvalidKeySpecException {
X509EncodedKeySpec key_spec = new X509EncodedKeySpec(inBytes);
KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
System.err.println(e);
e.printStackTrace();
return null;
}
return keyFactory.generatePublic(key_spec);
}
public static boolean verifySignature(PublicKey key, byte[] nounce, byte[] signature) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException {
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initVerify(key);
sig.update(nounce);
return sig.verify(signature);
}
}