-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Zmq secure connect implementation #641
Changes from 15 commits
56a07ca
9fc903a
49c46a7
f994aea
56998ef
91c64b1
3d570d6
17fc73c
8067f6f
49c0ea7
3f84a20
1c75109
33c68bd
0f14ba4
04672de
415caea
27caad4
a51c944
117a502
699080a
2208f82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
/log/ | ||
/rt/ | ||
/web3/ | ||
/zmq_keystore/ | ||
/jars/ | ||
|
||
# ide | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright (c) 2017-2018 Aion foundation. | ||
* | ||
* This file is part of the aion network project. | ||
* | ||
* The aion network project 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 any later version. | ||
* | ||
* The aion network project 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 the aion network project source files. | ||
* If not, see <https://www.gnu.org/licenses/>. | ||
* | ||
* Contributors: | ||
* Aion foundation. | ||
*/ | ||
|
||
package org.aion.base.io; | ||
|
||
import java.nio.file.Path; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
public class File { | ||
public static List<java.io.File> getFiles(final Path path) { | ||
if (path == null) { | ||
System.out.println("getFiles null path input!"); | ||
return Collections.emptyList(); | ||
} | ||
|
||
try { | ||
java.io.File[] files = path.toFile().listFiles(); | ||
return files != null ? Arrays.asList(files) : Collections.emptyList(); | ||
} catch (UnsupportedOperationException | NullPointerException e) { | ||
System.out.println("getFiles exception: " + e.toString()); | ||
return Collections.emptyList(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,26 +24,43 @@ | |
|
||
package org.aion.zero.impl.cli; | ||
|
||
import static org.aion.mcf.account.Keystore.exist; | ||
|
||
import com.google.common.base.Preconditions; | ||
import com.google.common.collect.ImmutableList; | ||
import java.io.BufferedReader; | ||
import java.io.Console; | ||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.util.*; | ||
|
||
import com.google.common.base.Preconditions; | ||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.io.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.nio.file.attribute.FileAttribute; | ||
import java.nio.file.attribute.PosixFilePermission; | ||
import java.nio.file.attribute.PosixFilePermissions; | ||
import java.text.DateFormat; | ||
import java.text.SimpleDateFormat; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Date; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.TimeZone; | ||
import java.util.UUID; | ||
import javax.annotation.Nonnull; | ||
import org.aion.base.util.Hex; | ||
import org.aion.crypto.ECKey; | ||
import org.aion.crypto.ECKeyFac; | ||
import org.aion.mcf.account.Keystore; | ||
import org.aion.mcf.config.Cfg; | ||
import org.aion.mcf.config.CfgApiZmq; | ||
import org.aion.mcf.config.CfgSsl; | ||
import org.aion.zero.impl.Version; | ||
import org.aion.zero.impl.config.CfgAion; | ||
import org.aion.zero.impl.db.RecoveryUtils; | ||
import org.zeromq.ZMQ; | ||
|
||
import java.io.Console; | ||
|
||
/** | ||
* Command line interface. | ||
|
@@ -52,6 +69,12 @@ | |
*/ | ||
public class Cli { | ||
|
||
private File keystoreDir = new File( | ||
System.getProperty("user.dir") + File.separator + CfgSsl.SSL_KEYSTORE_DIR); | ||
|
||
private File zmqkeyDir = new File( | ||
System.getProperty("user.dir") + File.separator + CfgApiZmq.ZMQ_KEY_DIR); | ||
|
||
private final String BASE_PATH = System.getProperty("user.dir"); | ||
|
||
private String BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); | ||
|
@@ -60,8 +83,6 @@ public class Cli { | |
|
||
private String dstGenesis = BASE_PATH_WITH_NETWORK + "/genesis.json"; | ||
|
||
File keystoreDir = new File(System.getProperty("user.dir") + File.separator + CfgSsl.SSL_KEYSTORE_DIR); | ||
|
||
enum Network { | ||
MAINNET, CONQUEST; | ||
|
||
|
@@ -213,6 +234,17 @@ public int call(final String[] args, Cfg cfg, String path) { | |
return 1; | ||
} | ||
break; | ||
case "-zs": | ||
checkZmqKeystoreDir(); | ||
if (existZmqSecKeyFile()) { | ||
System.out.println("Found existing secret key file. Please backup or remove it!"); | ||
return 1; | ||
} | ||
|
||
ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); | ||
genKeyFile(kp.publicKey, kp.secretKey); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on this implementation a user can generate multiple keys. Does having multiple keys have any advantage? Based on the key loading implementation I see a disadvantage in the fact that the chosen pair is relatively random. It may be preferable to overwrite the old key if the key generation is called a second time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Alternatively, refuse to generate another one unless they manually remove the existing one, so they don't accidentally delete their private key and lose it forever. Or just prompt them before overwriting. |
||
System.out.println("Generate ZmqKeyPairFinished!"); | ||
break; | ||
case "-r": | ||
if (args.length < 2) { | ||
System.out.println("Starting database clean-up."); | ||
|
@@ -448,15 +480,67 @@ else if (isValid(args[3])) { | |
return 1; | ||
} | ||
|
||
System.out.println(""); | ||
System.out.println(); | ||
} catch (Throwable e) { | ||
System.out.println(""); | ||
System.out.println(e.toString()); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
private boolean existZmqSecKeyFile() { | ||
List<File> files = org.aion.base.io.File.getFiles(zmqkeyDir.toPath()); | ||
|
||
for (File file : files) { | ||
if (file.getName().contains("zmqCurveSeckey")) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
private void genKeyFile(@Nonnull final String publicKey, @Nonnull final String secretKey) | ||
throws IOException { | ||
|
||
DateFormat df = new SimpleDateFormat("yy-MM-dd'T'HH-mm-ss'Z'"); | ||
df.setTimeZone(TimeZone.getTimeZone("UTC")); | ||
String iso_date = df.format(new Date(System.currentTimeMillis())); | ||
|
||
String fileName = "UTC--" + iso_date + "--zmqCurvePubkey"; | ||
writeKeyToFile(fileName, publicKey); | ||
|
||
fileName = "UTC--" + iso_date + "--zmqCurveSeckey"; | ||
writeKeyToFile(fileName, secretKey); | ||
} | ||
|
||
private void writeKeyToFile(@Nonnull final String fileName, @Nonnull final String key) throws IOException { | ||
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-----"); | ||
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms); | ||
|
||
Path p = Paths.get(zmqkeyDir.getPath()); | ||
Path keyFile = p.resolve(fileName); | ||
if (!java.nio.file.Files.exists(keyFile)) { | ||
keyFile = java.nio.file.Files.createFile(keyFile, attr); | ||
} | ||
|
||
FileOutputStream fos = new FileOutputStream(keyFile.toString()); | ||
fos.write(key.getBytes()); | ||
fos.close(); | ||
} | ||
|
||
private void checkZmqKeystoreDir() { | ||
if (!zmqkeyDir.isDirectory()) { | ||
if (!zmqkeyDir.mkdir()) { | ||
System.out.println("zmq keystore directory could not be created. " + | ||
"Please check user permissions or create directory manually."); | ||
System.exit(1); | ||
} | ||
System.out.println(); | ||
} | ||
} | ||
|
||
/** | ||
* Print the CLI help info. | ||
*/ | ||
|
@@ -586,7 +670,7 @@ private boolean listAccounts() { | |
* @return boolean | ||
*/ | ||
private boolean exportPrivateKey(String address) { | ||
if (!Keystore.exist(address)) { | ||
if (!exist(address)) { | ||
System.out.println("The account does not exist!"); | ||
return false; | ||
} | ||
|
@@ -786,7 +870,7 @@ private static boolean copyRecursively(File src, File target) | |
} | ||
else { | ||
try { | ||
Files.copy(src, target); | ||
com.google.common.io.Files.copy(src, target); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a reason this was removed from imports? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there are 2 different Files classes using in this class |
||
return true; | ||
} | ||
catch (IOException e) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the
zmq_keystore
should be added to.gitignore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for Alexandra's suggestion
Also, can we have the value of System.getProperty() be passed into Cli's constructor instead of referring to it directly? The dependence on static methtod calls will make the class hard to test / modularize.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aion-kelvin created an issue for tracking System.getProperty()
#652