/******************************************************************************* * Copyright (c) 2013 Lectorius, Inc. * Authors: * Vijay Pandurangan (vijayp@mitro.co) * Evan Jones (ej@mitro.co) * Adam Hilss (ahilss@mitro.co) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * You can contact the authors at inbound@mitro.co. *******************************************************************************/ package co.mitro.core.crypto; import java.util.Random; import co.mitro.core.crypto.KeyInterfaces.CryptoError; import co.mitro.core.crypto.KeyInterfaces.PrivateKeyInterface; import co.mitro.core.crypto.KeyInterfaces.PublicKeyInterface; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonParser; public class CrappyKeyFactory implements KeyInterfaces.KeyFactory { private static final int MAX_VALUE = 100; private static final Gson gson = new Gson(); private static int hash(String s) { int output = 0; for (int i = 0; i < s.length(); i++) { output = ((output << 5) - output) + s.charAt(i); } return output; } private static final class CrappyMessage { String message; int crypto; } private static final class CrappySerialized { String type; int key; String password; } private static enum KeyType { PUBLIC("PUB"), PRIVATE("PRV"), ENCRYPTED("PAS"); public final String value; private KeyType(String value) { this.value = value; } } public static class CrappyPublicKey implements KeyInterfaces.PublicKeyInterface { protected final int publicKeyValue; public CrappyPublicKey(int publicKeyValue) { this.publicKeyValue = publicKeyValue; assert this.publicKeyValue < MAX_VALUE; } protected String toJson(KeyType type, String password) { CrappySerialized key = new CrappySerialized(); key.type = type.value; key.key = publicKeyValue; key.password = password; return gson.toJson(key); } @Override public String toString() { return toJson(KeyType.PUBLIC, null); } @Override public boolean verify(String message, String signature) throws CryptoError { int h = hash(message); h += publicKeyValue; JsonParser parser = new JsonParser(); try { JsonElement e = parser.parse(signature); return e.getAsInt() == h; } catch (NumberFormatException e) { return false; } } @Override public String encrypt(String plaintext) throws CryptoError { CrappyMessage message = new CrappyMessage(); message.message = plaintext; message.crypto = MAX_VALUE - publicKeyValue; return gson.toJson(message); } } public static class CrappyPrivateKey extends CrappyPublicKey implements PrivateKeyInterface { public CrappyPrivateKey(int publicKeyValue) { super(publicKeyValue); } @Override public String toString() { return toJson(KeyType.PRIVATE, null); } @Override public String sign(String message) { int h = hash(message); h += publicKeyValue; return gson.toJson(h); } @Override public KeyInterfaces.PublicKeyInterface exportPublicKey() { return new CrappyPublicKey(publicKeyValue); } @Override public String decrypt(String message) throws CryptoError { CrappyMessage struct = gson.fromJson(message, CrappyMessage.class); if (struct.crypto != MAX_VALUE - publicKeyValue) { throw new CryptoError("Wrong key? Message: " + struct.crypto + " key: " + publicKeyValue); } return struct.message; } @Override public String exportEncrypted(String password) throws CryptoError { return toJson(KeyType.ENCRYPTED, password); } } @Override public PublicKeyInterface loadPublicKey(String serializedKey) throws CryptoError { CrappySerialized key = gson.fromJson(serializedKey, CrappySerialized.class); if (!key.type.equals(KeyType.PUBLIC.value)) { throw new CryptoError("Bad key type: " + key.type); } return new CrappyPublicKey(key.key); } @Override public PrivateKeyInterface loadPrivateKey(String serializedKey) throws CryptoError { CrappySerialized key = gson.fromJson(serializedKey, CrappySerialized.class); if (!key.type.equals(KeyType.PRIVATE.value)) { throw new CryptoError("Bad key type: " + key.type); } return new CrappyPrivateKey(key.key); } @Override public PrivateKeyInterface loadEncryptedPrivateKey(String serializedKey, String password) throws CryptoError { CrappySerialized key = gson.fromJson(serializedKey, CrappySerialized.class); if (!key.type.equals(KeyType.ENCRYPTED.value)) { throw new CryptoError("Bad key type: " + key.type); } if (!key.password.equals(password)) { throw new CryptoError("Invalid password"); } return new CrappyPrivateKey(key.key); } @Override public PrivateKeyInterface generate() throws CryptoError { int publicKeyValue = new Random().nextInt(MAX_VALUE - 1) + 1; return new CrappyPrivateKey(publicKeyValue); } }