/* * This file is part of Bitsquare. * * Bitsquare is free software: you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * Bitsquare 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 Affero General Public * License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Bitsquare. If not, see <http://www.gnu.org/licenses/>. */ package io.bitsquare.common.crypto; import com.google.common.base.Charsets; import org.bouncycastle.util.encoders.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.*; /** * StorageSignatureKeyPair/STORAGE_SIGN_KEY_ALGO: That is used for signing the data to be stored to the P2P network (by flooding). * The algo is selected because it originated from the TomP2P version which used DSA. * Changing to EC keys might be considered. * <p> * MsgSignatureKeyPair/MSG_SIGN_KEY_ALGO/MSG_SIGN_ALGO: That is used when sending a message to a peer which is encrypted and signed. * Changing to EC keys might be considered. */ public class Sig { private static final Logger log = LoggerFactory.getLogger(Sig.class); public static final String KEY_ALGO = "DSA"; private static final String ALGO = "SHA256withDSA"; /** * @return keyPair */ public static KeyPair generateKeyPair() { long ts = System.currentTimeMillis(); try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGO, "BC"); keyPairGenerator.initialize(1024); KeyPair keyPair = keyPairGenerator.genKeyPair(); log.trace("Generate msgSignatureKeyPair needed {} ms", System.currentTimeMillis() - ts); return keyPair; } catch (NoSuchAlgorithmException | NoSuchProviderException e) { e.printStackTrace(); throw new RuntimeException("Could not create key."); } } /** * @param privateKey * @param data * @return * @throws SignatureException * @throws NoSuchAlgorithmException * @throws InvalidKeyException */ public static byte[] sign(PrivateKey privateKey, byte[] data) throws CryptoException { try { Signature sig = Signature.getInstance(ALGO, "BC"); sig.initSign(privateKey); sig.update(data); return sig.sign(); } catch (SignatureException | NoSuchProviderException | InvalidKeyException | NoSuchAlgorithmException e) { throw new CryptoException("Signing failed. " + e.getMessage()); } } /** * @param privateKey * @param message UTF-8 encoded message to sign * @return Base64 encoded signature * @throws SignatureException * @throws NoSuchAlgorithmException * @throws InvalidKeyException */ public static String sign(PrivateKey privateKey, String message) throws CryptoException { byte[] sigAsBytes = sign(privateKey, message.getBytes(Charsets.UTF_8)); return Base64.toBase64String(sigAsBytes); } /** * @param publicKey * @param data * @param signature * @return * @throws NoSuchAlgorithmException * @throws InvalidKeyException * @throws SignatureException */ public static boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws CryptoException { try { Signature sig = Signature.getInstance(ALGO, "BC"); sig.initVerify(publicKey); sig.update(data); return sig.verify(signature); } catch (SignatureException | NoSuchProviderException | InvalidKeyException | NoSuchAlgorithmException e) { throw new CryptoException("Signature verification failed. " + e.getMessage()); } } /** * @param publicKey * @param message UTF-8 encoded message * @param signature Base64 encoded signature * @return * @throws NoSuchAlgorithmException * @throws InvalidKeyException * @throws SignatureException */ public static boolean verify(PublicKey publicKey, String message, String signature) throws CryptoException { return verify(publicKey, message.getBytes(Charsets.UTF_8), Base64.decode(signature)); } }