mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-05-19 23:10:48 -04:00
move network code to module
This commit is contained in:
parent
105a63847a
commit
c6ece486ed
384 changed files with 11571 additions and 21763 deletions
60
common/src/main/java/io/bitsquare/app/Logging.java
Normal file
60
common/src/main/java/io/bitsquare/app/Logging.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.app;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
|
||||
import ch.qos.logback.core.rolling.RollingFileAppender;
|
||||
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Logging {
|
||||
public static void setup(String fileName) {
|
||||
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
RollingFileAppender appender = new RollingFileAppender();
|
||||
appender.setContext(loggerContext);
|
||||
appender.setFile(fileName + ".log");
|
||||
|
||||
FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy();
|
||||
rollingPolicy.setContext(loggerContext);
|
||||
rollingPolicy.setParent(appender);
|
||||
rollingPolicy.setFileNamePattern(fileName + "_%i.log");
|
||||
rollingPolicy.setMinIndex(1);
|
||||
rollingPolicy.setMaxIndex(10);
|
||||
rollingPolicy.start();
|
||||
|
||||
SizeBasedTriggeringPolicy triggeringPolicy = new ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy();
|
||||
triggeringPolicy.setMaxFileSize("1MB");
|
||||
triggeringPolicy.start();
|
||||
|
||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||
encoder.setContext(loggerContext);
|
||||
encoder.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %xEx%n");
|
||||
encoder.start();
|
||||
|
||||
appender.setEncoder(encoder);
|
||||
appender.setRollingPolicy(rollingPolicy);
|
||||
appender.setTriggeringPolicy(triggeringPolicy);
|
||||
appender.start();
|
||||
|
||||
ch.qos.logback.classic.Logger logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
||||
logbackLogger.addAppender(appender);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
public class CryptoException extends Exception {
|
||||
|
||||
private CryptoException() {
|
||||
}
|
||||
|
||||
public CryptoException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CryptoException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public CryptoException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
private CryptoException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
136
common/src/main/java/io/bitsquare/common/crypto/CryptoUtil.java
Normal file
136
common/src/main/java/io/bitsquare/common/crypto/CryptoUtil.java
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 io.bitsquare.common.util.Utilities;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.Utils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
public class CryptoUtil {
|
||||
private static final Logger log = LoggerFactory.getLogger(CryptoUtil.class);
|
||||
public static final String STORAGE_SIGN_KEY_ALGO = "DSA";
|
||||
public static final String MSG_SIGN_KEY_ALGO = "DSA";
|
||||
public static final String MSG_ENCR_KEY_ALGO = "RSA";
|
||||
|
||||
public static final String SYM_ENCR_KEY_ALGO = "AES";
|
||||
public static final String SYM_CIPHER = "AES";
|
||||
public static final String ASYM_CIPHER = "RSA"; //RSA/ECB/PKCS1Padding
|
||||
public static final String MSG_SIGN_ALGO = "SHA1withDSA";
|
||||
|
||||
|
||||
public static KeyPair generateStorageSignatureKeyPair() throws NoSuchAlgorithmException {
|
||||
long ts = System.currentTimeMillis();
|
||||
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(STORAGE_SIGN_KEY_ALGO);
|
||||
keyPairGenerator.initialize(1024);
|
||||
KeyPair keyPair = keyPairGenerator.genKeyPair();
|
||||
log.trace("Generate storageSignatureKeyPair needed {} ms", System.currentTimeMillis() - ts);
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
public static KeyPair generateMsgSignatureKeyPair() throws NoSuchAlgorithmException {
|
||||
long ts = System.currentTimeMillis();
|
||||
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(MSG_SIGN_KEY_ALGO);
|
||||
keyPairGenerator.initialize(1024);
|
||||
KeyPair keyPair = keyPairGenerator.genKeyPair();
|
||||
log.trace("Generate msgSignatureKeyPair needed {} ms", System.currentTimeMillis() - ts);
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
public static KeyPair generateMsgEncryptionKeyPair() throws NoSuchAlgorithmException {
|
||||
long ts = System.currentTimeMillis();
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(MSG_ENCR_KEY_ALGO);
|
||||
keyPairGenerator.initialize(2048);
|
||||
KeyPair keyPair = keyPairGenerator.genKeyPair();
|
||||
log.trace("Generate msgEncryptionKeyPair needed {} ms", System.currentTimeMillis() - ts);
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
public static String signMessage(PrivateKey privateKey, String message)
|
||||
throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
|
||||
Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
|
||||
sig.initSign(privateKey);
|
||||
sig.update(message.getBytes());
|
||||
return Base64.toBase64String(sig.sign());
|
||||
}
|
||||
|
||||
public static boolean verifyMessage(PublicKey publicKey, String message, String signature)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
||||
Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
|
||||
sig.initVerify(publicKey);
|
||||
sig.update(message.getBytes());
|
||||
return sig.verify(Base64.decode(signature));
|
||||
}
|
||||
|
||||
public static byte[] signStorageData(PrivateKey privateKey, byte[] data)
|
||||
throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
|
||||
Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
|
||||
sig.initSign(privateKey);
|
||||
sig.update(data);
|
||||
return sig.sign();
|
||||
}
|
||||
|
||||
public static boolean verifyStorageData(PublicKey publicKey, byte[] data, byte[] signature)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
||||
Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
|
||||
sig.initVerify(publicKey);
|
||||
sig.update(data);
|
||||
return sig.verify(signature);
|
||||
}
|
||||
|
||||
public static byte[] getHash(Integer data) {
|
||||
return Sha256Hash.hash(ByteBuffer.allocate(4).putInt(data).array());
|
||||
}
|
||||
|
||||
public static byte[] getHash(Object data) {
|
||||
return Sha256Hash.hash(Utilities.objectToByteArray(data));
|
||||
}
|
||||
|
||||
public static byte[] getHash(String message) {
|
||||
return Sha256Hash.hash(Utils.formatMessageForSigning(message));
|
||||
}
|
||||
|
||||
public static String getHashAsHex(String text) {
|
||||
return Utils.HEX.encode(Sha256Hash.hash(Utils.formatMessageForSigning(text)));
|
||||
}
|
||||
|
||||
public static String pubKeyToString(PublicKey publicKey) {
|
||||
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
|
||||
return java.util.Base64.getEncoder().encodeToString(x509EncodedKeySpec.getEncoded());
|
||||
}
|
||||
|
||||
// TODO just temp for arbitrator
|
||||
public static PublicKey decodeDSAPubKeyHex(String pubKeyHex) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Utils.HEX.decode(pubKeyHex));
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
|
||||
return keyFactory.generatePublic(pubKeySpec);
|
||||
}
|
||||
}
|
||||
|
101
common/src/main/java/io/bitsquare/common/crypto/KeyRing.java
Normal file
101
common/src/main/java/io/bitsquare/common/crypto/KeyRing.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.security.KeyPair;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class KeyRing {
|
||||
private static final Logger log = LoggerFactory.getLogger(KeyRing.class);
|
||||
|
||||
// Used for signing storage data
|
||||
private KeyPair storageSignatureKeyPair;
|
||||
// Used for signing messages sent over the wire
|
||||
private KeyPair msgSignatureKeyPair;
|
||||
// Used for encrypting messages sent over the wire (hybrid encryption scheme is used, so it is used only to encrypt a symmetric session key)
|
||||
private KeyPair msgEncryptionKeyPair;
|
||||
|
||||
private PubKeyRing pubKeyRing;
|
||||
private final KeyStorage keyStorage;
|
||||
|
||||
@Inject
|
||||
public KeyRing(KeyStorage keyStorage) throws CryptoException {
|
||||
this.keyStorage = keyStorage;
|
||||
|
||||
init(keyStorage);
|
||||
}
|
||||
|
||||
// consider extra thread for loading (takes about 264 ms at first startup, then load only takes nearly no time)
|
||||
private void init(KeyStorage keyStorage) throws CryptoException {
|
||||
if (keyStorage.allKeyFilesExist()) {
|
||||
storageSignatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.STORAGE_SIGNATURE);
|
||||
msgSignatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_SIGNATURE);
|
||||
msgEncryptionKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_ENCRYPTION);
|
||||
} else {
|
||||
// First time we create key pairs
|
||||
try {
|
||||
this.storageSignatureKeyPair = CryptoUtil.generateStorageSignatureKeyPair();
|
||||
this.msgSignatureKeyPair = CryptoUtil.generateMsgSignatureKeyPair();
|
||||
this.msgEncryptionKeyPair = CryptoUtil.generateMsgEncryptionKeyPair();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new CryptoException("Error at KeyRing constructor ", e);
|
||||
}
|
||||
keyStorage.saveKeyRing(this);
|
||||
}
|
||||
|
||||
pubKeyRing = new PubKeyRing(storageSignatureKeyPair.getPublic(), msgSignatureKeyPair.getPublic(), msgEncryptionKeyPair.getPublic());
|
||||
}
|
||||
|
||||
// For unit testing
|
||||
KeyRing() throws NoSuchAlgorithmException {
|
||||
keyStorage = null;
|
||||
this.storageSignatureKeyPair = CryptoUtil.generateStorageSignatureKeyPair();
|
||||
this.msgSignatureKeyPair = CryptoUtil.generateMsgSignatureKeyPair();
|
||||
this.msgEncryptionKeyPair = CryptoUtil.generateMsgEncryptionKeyPair();
|
||||
pubKeyRing = new PubKeyRing(storageSignatureKeyPair.getPublic(), msgSignatureKeyPair.getPublic(), msgEncryptionKeyPair.getPublic());
|
||||
}
|
||||
|
||||
KeyRing(KeyPair storageSignatureKeyPair, KeyPair msgSignatureKeyPair, KeyPair msgEncryptionKeyPair) {
|
||||
this.keyStorage = null;
|
||||
this.storageSignatureKeyPair = storageSignatureKeyPair;
|
||||
this.msgSignatureKeyPair = msgSignatureKeyPair;
|
||||
this.msgEncryptionKeyPair = msgEncryptionKeyPair;
|
||||
pubKeyRing = new PubKeyRing(storageSignatureKeyPair.getPublic(), msgSignatureKeyPair.getPublic(), msgEncryptionKeyPair.getPublic());
|
||||
}
|
||||
|
||||
public KeyPair getStorageSignatureKeyPair() {
|
||||
return storageSignatureKeyPair;
|
||||
}
|
||||
|
||||
public KeyPair getMsgSignatureKeyPair() {
|
||||
return msgSignatureKeyPair;
|
||||
}
|
||||
|
||||
public KeyPair getMsgEncryptionKeyPair() {
|
||||
return msgEncryptionKeyPair;
|
||||
}
|
||||
|
||||
public PubKeyRing getPubKeyRing() {
|
||||
return pubKeyRing;
|
||||
}
|
||||
}
|
162
common/src/main/java/io/bitsquare/common/crypto/KeyStorage.java
Normal file
162
common/src/main/java/io/bitsquare/common/crypto/KeyStorage.java
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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.inject.Inject;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Named;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
public class KeyStorage {
|
||||
private static final Logger log = LoggerFactory.getLogger(KeyStorage.class);
|
||||
|
||||
public static final String DIR_KEY = "key.storage.dir";
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
public enum Key {
|
||||
STORAGE_SIGNATURE("storageSignature", CryptoUtil.STORAGE_SIGN_KEY_ALGO),
|
||||
MSG_SIGNATURE("msgSignature", CryptoUtil.MSG_SIGN_KEY_ALGO),
|
||||
MSG_ENCRYPTION("msgEncryption", CryptoUtil.MSG_ENCR_KEY_ALGO);
|
||||
|
||||
private final String fileName;
|
||||
private final String algorithm;
|
||||
|
||||
Key(String fileName, String algorithm) {
|
||||
this.fileName = fileName;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Key{" +
|
||||
"fileName='" + fileName + '\'' +
|
||||
", algorithm='" + algorithm + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
private final File storageDir;
|
||||
|
||||
@Inject
|
||||
public KeyStorage(@Named(DIR_KEY) File storageDir) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
|
||||
this.storageDir = storageDir;
|
||||
}
|
||||
|
||||
public boolean allKeyFilesExist() throws CryptoException {
|
||||
return fileExists(KeyStorage.Key.STORAGE_SIGNATURE) && fileExists(KeyStorage.Key.MSG_SIGNATURE) && fileExists(KeyStorage.Key.MSG_ENCRYPTION);
|
||||
}
|
||||
|
||||
private boolean fileExists(Key key) {
|
||||
return new File(storageDir + "/" + key.getFileName() + "Pub.key").exists();
|
||||
}
|
||||
|
||||
public KeyPair loadKeyPair(Key key) throws CryptoException {
|
||||
// long now = System.currentTimeMillis();
|
||||
try {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
|
||||
PublicKey publicKey;
|
||||
PrivateKey privateKey;
|
||||
|
||||
File filePublicKey = new File(storageDir + "/" + key.getFileName() + "Pub.key");
|
||||
try (FileInputStream fis = new FileInputStream(filePublicKey.getPath())) {
|
||||
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
|
||||
fis.read(encodedPublicKey);
|
||||
|
||||
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
|
||||
publicKey = keyFactory.generatePublic(publicKeySpec);
|
||||
} catch (InvalidKeySpecException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
throw new CryptoException("Could not load key " + key.toString(), e);
|
||||
}
|
||||
|
||||
File filePrivateKey = new File(storageDir + "/" + key.getFileName() + "Priv.key");
|
||||
try (FileInputStream fis = new FileInputStream(filePrivateKey.getPath())) {
|
||||
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
|
||||
fis.read(encodedPrivateKey);
|
||||
|
||||
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
|
||||
privateKey = keyFactory.generatePrivate(privateKeySpec);
|
||||
} catch (InvalidKeySpecException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
throw new CryptoException("Could not load key " + key.toString(), e);
|
||||
}
|
||||
//log.info("load completed in {} msec", System.currentTimeMillis() - now);
|
||||
return new KeyPair(publicKey, privateKey);
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
throw new CryptoException("Could not load key " + key.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveKeyRing(KeyRing keyRing) throws CryptoException {
|
||||
saveKeyPair(keyRing.getStorageSignatureKeyPair(), Key.STORAGE_SIGNATURE.getFileName());
|
||||
saveKeyPair(keyRing.getMsgSignatureKeyPair(), Key.MSG_SIGNATURE.getFileName());
|
||||
saveKeyPair(keyRing.getMsgEncryptionKeyPair(), Key.MSG_ENCRYPTION.getFileName());
|
||||
}
|
||||
|
||||
public void saveKeyPair(KeyPair keyPair, String name) throws CryptoException {
|
||||
if (!storageDir.exists())
|
||||
storageDir.mkdir();
|
||||
|
||||
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyPair.getPublic().getEncoded());
|
||||
try (FileOutputStream fos = new FileOutputStream(storageDir + "/" + name + "Pub.key")) {
|
||||
fos.write(x509EncodedKeySpec.getEncoded());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
throw new CryptoException("Could not save key " + name, e);
|
||||
}
|
||||
|
||||
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
|
||||
try (FileOutputStream fos = new FileOutputStream(storageDir + "/" + name + "Priv.key")) {
|
||||
fos.write(pkcs8EncodedKeySpec.getEncoded());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
throw new CryptoException("Could not save key " + name, e);
|
||||
}
|
||||
}
|
||||
}
|
127
common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java
Normal file
127
common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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 io.bitsquare.app.Version;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Same as KeyRing but with public keys only.
|
||||
* Used to sent over the wire to other peer.
|
||||
*/
|
||||
public class PubKeyRing implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(PubKeyRing.class);
|
||||
|
||||
private final byte[] storageSignaturePubKeyBytes;
|
||||
private final byte[] msgSignaturePubKeyBytes;
|
||||
private final byte[] msgEncryptionPubKeyBytes;
|
||||
|
||||
transient private PublicKey storageSignaturePubKey;
|
||||
transient private PublicKey msgSignaturePubKey;
|
||||
transient private PublicKey msgEncryptionPubKey;
|
||||
|
||||
public PubKeyRing(PublicKey storageSignaturePubKey, PublicKey msgSignaturePubKey, PublicKey msgEncryptionPubKey) {
|
||||
this.storageSignaturePubKey = storageSignaturePubKey;
|
||||
this.msgSignaturePubKey = msgSignaturePubKey;
|
||||
this.msgEncryptionPubKey = msgEncryptionPubKey;
|
||||
|
||||
this.storageSignaturePubKeyBytes = new X509EncodedKeySpec(storageSignaturePubKey.getEncoded()).getEncoded();
|
||||
this.msgSignaturePubKeyBytes = new X509EncodedKeySpec(msgSignaturePubKey.getEncoded()).getEncoded();
|
||||
this.msgEncryptionPubKeyBytes = new X509EncodedKeySpec(msgEncryptionPubKey.getEncoded()).getEncoded();
|
||||
}
|
||||
|
||||
public PublicKey getStorageSignaturePubKey() {
|
||||
if (storageSignaturePubKey == null) {
|
||||
try {
|
||||
storageSignaturePubKey = KeyFactory.getInstance(CryptoUtil.STORAGE_SIGN_KEY_ALGO).generatePublic(new X509EncodedKeySpec(storageSignaturePubKeyBytes));
|
||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
return storageSignaturePubKey;
|
||||
}
|
||||
|
||||
|
||||
public PublicKey getMsgSignaturePubKey() {
|
||||
if (msgSignaturePubKey == null) {
|
||||
try {
|
||||
msgSignaturePubKey = KeyFactory.getInstance(CryptoUtil.MSG_SIGN_KEY_ALGO).generatePublic(new X509EncodedKeySpec(msgSignaturePubKeyBytes));
|
||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
return msgSignaturePubKey;
|
||||
}
|
||||
|
||||
public PublicKey getMsgEncryptionPubKey() {
|
||||
if (msgEncryptionPubKey == null) {
|
||||
try {
|
||||
msgEncryptionPubKey = KeyFactory.getInstance(CryptoUtil.MSG_ENCR_KEY_ALGO).generatePublic(new X509EncodedKeySpec(msgEncryptionPubKeyBytes));
|
||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
return msgEncryptionPubKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PubKeyRing that = (PubKeyRing) o;
|
||||
|
||||
if (!Arrays.equals(storageSignaturePubKeyBytes, that.storageSignaturePubKeyBytes)) return false;
|
||||
if (!Arrays.equals(msgSignaturePubKeyBytes, that.msgSignaturePubKeyBytes)) return false;
|
||||
return Arrays.equals(msgEncryptionPubKeyBytes, that.msgEncryptionPubKeyBytes);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = storageSignaturePubKeyBytes != null ? Arrays.hashCode(storageSignaturePubKeyBytes) : 0;
|
||||
result = 31 * result + (msgSignaturePubKeyBytes != null ? Arrays.hashCode(msgSignaturePubKeyBytes) : 0);
|
||||
result = 31 * result + (msgEncryptionPubKeyBytes != null ? Arrays.hashCode(msgEncryptionPubKeyBytes) : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PubKeyRing{" +
|
||||
"\nstorageSignaturePubKey=\n" + CryptoUtil.pubKeyToString(getStorageSignaturePubKey()) +
|
||||
"\n\nmsgSignaturePubKey=\n" + CryptoUtil.pubKeyToString(getMsgSignaturePubKey()) +
|
||||
"\n\nmsgEncryptionPubKey=\n" + CryptoUtil.pubKeyToString(getMsgEncryptionPubKey()) +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
250
common/src/main/java/io/bitsquare/common/util/DesktopUtil.java
Normal file
250
common/src/main/java/io/bitsquare/common/util/DesktopUtil.java
Normal file
|
@ -0,0 +1,250 @@
|
|||
package io.bitsquare.common.util;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
// Taken form https://stackoverflow.com/questions/18004150/desktop-api-is-not-supported-on-the-current-platform,
|
||||
// originally net.mightypork.rpack.utils.DesktopApi
|
||||
class DesktopUtil {
|
||||
|
||||
public static boolean browse(URI uri) {
|
||||
|
||||
if (openSystemSpecific(uri.toString())) return true;
|
||||
|
||||
return browseDESKTOP(uri);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static boolean open(File file) {
|
||||
|
||||
if (openSystemSpecific(file.getPath())) return true;
|
||||
|
||||
return openDESKTOP(file);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static boolean edit(File file) {
|
||||
|
||||
// you can try something like
|
||||
// runCommand("gimp", "%s", file.getPath())
|
||||
// based on user preferences.
|
||||
|
||||
if (openSystemSpecific(file.getPath())) return true;
|
||||
|
||||
return editDESKTOP(file);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static boolean openSystemSpecific(String what) {
|
||||
|
||||
EnumOS os = getOs();
|
||||
|
||||
if (os.isLinux()) {
|
||||
if (runCommand("kde-open", "%s", what)) return true;
|
||||
if (runCommand("gnome-open", "%s", what)) return true;
|
||||
if (runCommand("xdg-open", "%s", what)) return true;
|
||||
}
|
||||
|
||||
if (os.isMac()) {
|
||||
if (runCommand("open", "%s", what)) return true;
|
||||
}
|
||||
|
||||
if (os.isWindows()) {
|
||||
if (runCommand("explorer", "%s", what)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static boolean browseDESKTOP(URI uri) {
|
||||
|
||||
logOut("Trying to use Desktop.getDesktop().browse() with " + uri.toString());
|
||||
try {
|
||||
if (!Desktop.isDesktopSupported()) {
|
||||
logErr("Platform is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
||||
logErr("BORWSE is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Desktop.getDesktop().browse(uri);
|
||||
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
logErr("Error using desktop browse.", t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean openDESKTOP(File file) {
|
||||
|
||||
logOut("Trying to use Desktop.getDesktop().open() with " + file.toString());
|
||||
try {
|
||||
if (!Desktop.isDesktopSupported()) {
|
||||
logErr("Platform is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
|
||||
logErr("OPEN is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Desktop.getDesktop().open(file);
|
||||
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
logErr("Error using desktop open.", t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean editDESKTOP(File file) {
|
||||
|
||||
logOut("Trying to use Desktop.getDesktop().edit() with " + file);
|
||||
try {
|
||||
if (!Desktop.isDesktopSupported()) {
|
||||
logErr("Platform is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Desktop.getDesktop().isSupported(Desktop.Action.EDIT)) {
|
||||
logErr("EDIT is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Desktop.getDesktop().edit(file);
|
||||
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
logErr("Error using desktop edit.", t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean runCommand(String command, String args, String file) {
|
||||
|
||||
logOut("Trying to exec:\n cmd = " + command + "\n args = " + args + "\n %s = " + file);
|
||||
|
||||
String[] parts = prepareCommand(command, args, file);
|
||||
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(parts);
|
||||
if (p == null) return false;
|
||||
|
||||
try {
|
||||
int retval = p.exitValue();
|
||||
if (retval == 0) {
|
||||
logErr("Process ended immediately.");
|
||||
return false;
|
||||
} else {
|
||||
logErr("Process crashed.");
|
||||
return false;
|
||||
}
|
||||
} catch (IllegalThreadStateException itse) {
|
||||
logErr("Process is running.");
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logErr("Error running command.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String[] prepareCommand(String command, String args, String file) {
|
||||
|
||||
List<String> parts = new ArrayList<>();
|
||||
parts.add(command);
|
||||
|
||||
if (args != null) {
|
||||
for (String s : args.split(" ")) {
|
||||
s = String.format(s, file); // put in the filename thing
|
||||
|
||||
parts.add(s.trim());
|
||||
}
|
||||
}
|
||||
|
||||
return parts.toArray(new String[parts.size()]);
|
||||
}
|
||||
|
||||
private static void logErr(String msg, Throwable t) {
|
||||
System.err.println(msg);
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
private static void logErr(String msg) {
|
||||
System.err.println(msg);
|
||||
}
|
||||
|
||||
private static void logOut(String msg) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
|
||||
public enum EnumOS {
|
||||
linux, macos, solaris, unknown, windows;
|
||||
|
||||
public boolean isLinux() {
|
||||
|
||||
return this == linux || this == solaris;
|
||||
}
|
||||
|
||||
|
||||
public boolean isMac() {
|
||||
|
||||
return this == macos;
|
||||
}
|
||||
|
||||
|
||||
public boolean isWindows() {
|
||||
|
||||
return this == windows;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static EnumOS getOs() {
|
||||
|
||||
String s = System.getProperty("os.name").toLowerCase();
|
||||
|
||||
if (s.contains("win")) {
|
||||
return EnumOS.windows;
|
||||
}
|
||||
|
||||
if (s.contains("mac")) {
|
||||
return EnumOS.macos;
|
||||
}
|
||||
|
||||
if (s.contains("solaris")) {
|
||||
return EnumOS.solaris;
|
||||
}
|
||||
|
||||
if (s.contains("sunos")) {
|
||||
return EnumOS.solaris;
|
||||
}
|
||||
|
||||
if (s.contains("linux")) {
|
||||
return EnumOS.linux;
|
||||
}
|
||||
|
||||
if (s.contains("unix")) {
|
||||
return EnumOS.linux;
|
||||
} else {
|
||||
return EnumOS.unknown;
|
||||
}
|
||||
}
|
||||
}
|
356
common/src/main/java/io/bitsquare/common/util/Utilities.java
Normal file
356
common/src/main/java/io/bitsquare/common/util/Utilities.java
Normal file
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.gson.*;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.web.WebEngine;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
|
||||
/**
|
||||
* General utilities
|
||||
*/
|
||||
public class Utilities {
|
||||
private static final Logger log = LoggerFactory.getLogger(Utilities.class);
|
||||
private static long lastTimeStamp = System.currentTimeMillis();
|
||||
|
||||
public static String objectToJson(Object object) {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setExclusionStrategies(new AnnotationExclusionStrategy())
|
||||
/*.excludeFieldsWithModifiers(Modifier.TRANSIENT)*/
|
||||
/* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)*/
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
return gson.toJson(object);
|
||||
}
|
||||
|
||||
public static boolean isUnix() {
|
||||
return isOSX() || isLinux() || getOSName().contains("freebsd");
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
return getOSName().contains("win");
|
||||
}
|
||||
|
||||
public static boolean isOSX() {
|
||||
return getOSName().contains("mac") || getOSName().contains("darwin");
|
||||
}
|
||||
|
||||
private static boolean isLinux() {
|
||||
return getOSName().contains("linux");
|
||||
}
|
||||
|
||||
private static String getOSName() {
|
||||
return System.getProperty("os.name").toLowerCase();
|
||||
}
|
||||
|
||||
public static void openURI(URI uri) throws IOException {
|
||||
if (!isLinux()
|
||||
&& Desktop.isDesktopSupported()
|
||||
&& Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
||||
Desktop.getDesktop().browse(uri);
|
||||
} else {
|
||||
// Maybe Application.HostServices works in those cases?
|
||||
// HostServices hostServices = getHostServices();
|
||||
// hostServices.showDocument(uri.toString());
|
||||
|
||||
// On Linux Desktop is poorly implemented.
|
||||
// See https://stackoverflow.com/questions/18004150/desktop-api-is-not-supported-on-the-current-platform
|
||||
if (!DesktopUtil.browse(uri))
|
||||
throw new IOException("Failed to open URI: " + uri.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void openWebPage(String target) {
|
||||
try {
|
||||
openURI(new URI(target));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void printSystemLoad() {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
long free = runtime.freeMemory() / 1024 / 1024;
|
||||
long total = runtime.totalMemory() / 1024 / 1024;
|
||||
long used = total - free;
|
||||
log.info("System load (nr. threads/used memory (MB)): " + Thread.activeCount() + "/" + used);
|
||||
}
|
||||
|
||||
// Opens links with http and _blank in default web browser instead of webView
|
||||
// WebView has not feature to open link in default browser, so we use the hack recommended here:
|
||||
// https://stackoverflow.com/questions/15555510/javafx-stop-opening-url-in-webview-open-in-browser-instead
|
||||
public static void setupWebViewPopupHandler(WebEngine webEngine) {
|
||||
webEngine.setCreatePopupHandler(
|
||||
config -> {
|
||||
// grab the last hyperlink that has :hover pseudoclass
|
||||
Object result = webEngine
|
||||
.executeScript(
|
||||
"var list = document.querySelectorAll( ':hover' );"
|
||||
+ "for (i=list.length-1; i>-1; i--) "
|
||||
+ "{ if ( list.item(i).getAttribute('href') ) "
|
||||
+ "{ list.item(i).getAttribute('href'); break; } }");
|
||||
|
||||
if (result instanceof String && ((String) result).contains("http")) {
|
||||
openWebPage((String) result);
|
||||
return null;
|
||||
} else {
|
||||
return webEngine;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void openMail(String to, String subject, String body) {
|
||||
try {
|
||||
subject = URLEncoder.encode(subject, "UTF-8").replace("+", "%20");
|
||||
body = URLEncoder.encode(body, "UTF-8").replace("+", "%20");
|
||||
Desktop.getDesktop().mail(new URI("mailto:" + to + "?subject=" + subject + "&body=" + body));
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyToClipboard(String content) {
|
||||
if (content != null && content.length() > 0) {
|
||||
Clipboard clipboard = Clipboard.getSystemClipboard();
|
||||
ClipboardContent clipboardContent = new ClipboardContent();
|
||||
clipboardContent.putString(content);
|
||||
clipboard.setContent(clipboardContent);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] concatByteArrays(byte[]... arrays) {
|
||||
int totalLength = 0;
|
||||
for (byte[] array : arrays) {
|
||||
totalLength += array.length;
|
||||
}
|
||||
|
||||
byte[] result = new byte[totalLength];
|
||||
int currentIndex = 0;
|
||||
for (byte[] array : arrays) {
|
||||
System.arraycopy(array, 0, result, currentIndex, array.length);
|
||||
currentIndex += array.length;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> T jsonToObject(String jsonString, Class<T> classOfT) {
|
||||
Gson gson =
|
||||
new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting().create();
|
||||
return gson.fromJson(jsonString, classOfT);
|
||||
}
|
||||
|
||||
|
||||
/* public static Object deserializeHexStringToObject(String serializedHexString) {
|
||||
Object result = null;
|
||||
try {
|
||||
ByteArrayInputStream byteInputStream =
|
||||
new ByteArrayInputStream(org.bitcoinj.core.Utils.parseAsHexOrBase58(serializedHexString));
|
||||
|
||||
try (ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream)) {
|
||||
result = objectInputStream.readObject();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
byteInputStream.close();
|
||||
|
||||
}
|
||||
|
||||
} catch (IOException i) {
|
||||
i.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static String serializeObjectToHexString(Serializable serializable) {
|
||||
String result = null;
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try {
|
||||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
|
||||
objectOutputStream.writeObject(serializable);
|
||||
|
||||
result = org.bitcoinj.core.Utils.HEX.encode(byteArrayOutputStream.toByteArray());
|
||||
byteArrayOutputStream.close();
|
||||
objectOutputStream.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}*/
|
||||
|
||||
public static <T> T byteArrayToObject(byte[] data) {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||
ObjectInput in = null;
|
||||
Object result = null;
|
||||
try {
|
||||
in = new ObjectInputStream(bis);
|
||||
result = in.readObject();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
}
|
||||
return (T) result;
|
||||
}
|
||||
|
||||
public static byte[] objectToByteArray(Object object) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutput out = null;
|
||||
byte[] result = null;
|
||||
try {
|
||||
out = new ObjectOutputStream(bos);
|
||||
out.writeObject(object);
|
||||
result = bos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void deleteDirectory(File file) throws IOException {
|
||||
if (file.isDirectory()) {
|
||||
for (File c : file.listFiles())
|
||||
deleteDirectory(c);
|
||||
}
|
||||
if (!file.delete())
|
||||
throw new FileNotFoundException("Failed to delete file: " + file);
|
||||
}
|
||||
|
||||
private static void printElapsedTime(String msg) {
|
||||
if (!msg.isEmpty()) {
|
||||
msg += " / ";
|
||||
}
|
||||
long timeStamp = System.currentTimeMillis();
|
||||
log.debug(msg + "Elapsed: " + String.valueOf(timeStamp - lastTimeStamp));
|
||||
lastTimeStamp = timeStamp;
|
||||
}
|
||||
|
||||
public static void printElapsedTime() {
|
||||
printElapsedTime("");
|
||||
}
|
||||
|
||||
|
||||
public static Object copy(Serializable orig) {
|
||||
Object obj = null;
|
||||
try {
|
||||
// Write the object out to a byte array
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(bos);
|
||||
out.writeObject(orig);
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
// Make an input stream from the byte array and read
|
||||
// a copy of the object back in.
|
||||
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
|
||||
obj = in.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty and delete a folder (and subfolders).
|
||||
*
|
||||
* @param folder folder to empty
|
||||
*/
|
||||
private static void removeDirectory(final File folder) {
|
||||
// check if folder file is a real folder
|
||||
if (folder.isDirectory()) {
|
||||
File[] list = folder.listFiles();
|
||||
if (list != null) {
|
||||
for (File tmpF : list) {
|
||||
if (tmpF.isDirectory()) {
|
||||
removeDirectory(tmpF);
|
||||
}
|
||||
if (!tmpF.delete())
|
||||
log.warn("can't delete file : " + tmpF);
|
||||
}
|
||||
}
|
||||
if (!folder.delete())
|
||||
log.warn("can't delete folder : " + folder);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readTextFileFromServer(String url, String userAgent) throws IOException {
|
||||
URLConnection connection = URI.create(url).toURL().openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setUseCaches(false);
|
||||
connection.setConnectTimeout(10 * 1000);
|
||||
connection.addRequestProperty("User-Agent", userAgent);
|
||||
connection.connect();
|
||||
try (InputStream inputStream = connection.getInputStream()) {
|
||||
return CharStreams.toString(new InputStreamReader(inputStream, Charsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static class AnnotationExclusionStrategy implements ExclusionStrategy {
|
||||
@Override
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
return f.getAnnotation(JsonExclude.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue