diff --git a/keystore.jks b/keystore.jks index 4113915d016bb4e87cb93f1512cc2661b45a4271..82d03eec604254def7822df5a4565c03e67b1a8c 100644 Binary files a/keystore.jks and b/keystore.jks differ diff --git a/src/main/java/fr/miage/App.java b/src/main/java/fr/miage/App.java index c0f367308ccf4cff9796efb8700f38f776a1c106..14560e436a32a673d974d89fe728b445650940c5 100644 --- a/src/main/java/fr/miage/App.java +++ b/src/main/java/fr/miage/App.java @@ -15,14 +15,14 @@ public class App { public static void main(String[] args) throws NoSuchAlgorithmException, InterruptedException { System.out.println("Début de la blockchain"); // Création de 2 wallets - Wallet bobWallet = new Wallet("jesuislacleprivedebob", "bob"); - Wallet aliceWallet = new Wallet("je suis la clé privé de alice", "alice"); + Wallet bobWallet = new Wallet("bob"); + Wallet aliceWallet = new Wallet("alice"); List<Wallet> wallets = Arrays.asList(bobWallet, aliceWallet); Blockchain blockchain = new Blockchain("BloBlockchain", wallets); - System.out.println("Wallet de bob : " + bobWallet.getUtxos()); - System.out.println("Wallet de alice : " + aliceWallet.getUtxos()); + // System.out.println("Wallet de bob : " + bobWallet.getUtxos()); + // System.out.println("Wallet de alice : " + aliceWallet.getUtxos()); // System.out.println("Utxos du wallet de bob : " + bobWallet.getUtxos()); // System.out.println("Utxos du wallet de alice : " + aliceWallet.getUtxos()); // Transaction transaction = new Transaction(bobWallet, aliceWallet, 2, @@ -38,7 +38,8 @@ public class App { blockchain.createTrasaction(); i++; } - System.out.println("Transactions pool count : " + blockchain.transactionsPool.size()); + System.out.println("Transactions pool count : " + + blockchain.transactionsPool.size()); // // print all utxo in the utxo set // for (UTxO utxo : Blockchain.utxos) { diff --git a/src/main/java/fr/miage/Bloc.java b/src/main/java/fr/miage/Bloc.java index f0a5a42f26a6bea96266904a9e4ec153bcf18496..2b941f9f531778ee58adb706820133d0e8e8d79f 100644 --- a/src/main/java/fr/miage/Bloc.java +++ b/src/main/java/fr/miage/Bloc.java @@ -51,7 +51,7 @@ public class Bloc { List<Transaction> transactions = new ArrayList<Transaction>(); for (Wallet wallet : wallets) { int amount = RandomNumberGenerator.getRandomNumber(1, 20); - UTxO utxo = new UTxO(null, wallet.getPublicKey(), amount); + UTxO utxo = new UTxO(null, wallet.getKeyPair().getPublic(), amount); wallet.addUTxO(utxo); Blockchain.utxos.add(utxo); List<UTxO> utxos = new ArrayList<UTxO>() { @@ -60,10 +60,10 @@ public class Bloc { } }; - Coinbase coinbase = new Coinbase(utxos, wallet.getPublicKey(), EnumTypeTransaction.COINBASE); + Coinbase coinbase = new Coinbase(utxos, wallet.getKeyPair().getPublic(), EnumTypeTransaction.COINBASE); transactions.add(coinbase); } - System.out.println("Set UTxO INITIAL " + Blockchain.utxos); + // System.out.println("Set UTxO INITIAL " + Blockchain.utxos); BlocHeader blocHeader = new BlocHeader("", Instant.now().toEpochMilli(), 0); String header = blocHeader.toString(); diff --git a/src/main/java/fr/miage/Blockchain.java b/src/main/java/fr/miage/Blockchain.java index bab320cdeb24e7ed430b894ca1dd0506da7b7975..4cc5db7ef04c33473483583f2e32cd612d69f43b 100644 --- a/src/main/java/fr/miage/Blockchain.java +++ b/src/main/java/fr/miage/Blockchain.java @@ -1,5 +1,11 @@ package fr.miage; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -42,22 +48,56 @@ public class Blockchain { double amountWalletSender = walletSender.getUtxos().stream().mapToDouble(utxo -> utxo.getMontant()).sum(); double randomAmountToSend = new Random().nextDouble(amountWalletSender); - System.out.println("Amount to send : " + randomAmountToSend); - System.out.println("Envoie de " + walletSender.getName() + " à " + walletReceiver.getName()); - System.out.println(); - System.out.println("Utxos de " + walletSender.getName() + " : " + walletSender.getUtxos()); - System.out.println("Utxos de " + walletReceiver.getName() + " : " + walletReceiver.getUtxos()); - System.out.println(); + // System.out.println("Amount to send : " + randomAmountToSend); + // System.out.println("Envoie de " + walletSender.getName() + " à " + + // walletReceiver.getName()); + // System.out.println(); + // System.out.println("Utxos de " + walletSender.getName() + " : " + + // walletSender.getUtxos()); + // System.out.println("Utxos de " + walletReceiver.getName() + " : " + + // walletReceiver.getUtxos()); + // System.out.println(); if (walletSender.getUtxos().isEmpty() || walletReceiver.getUtxos().isEmpty()) { System.out.println("Wallets vides"); return; } Transaction tx = new Transaction(walletSender, walletReceiver, randomAmountToSend, EnumTypeTransaction.NORMAL); - + String transactionData = getTransactionData(tx); + try { + byte[] signature = sign(transactionData, walletSender.getKeyPair().getPrivate()); + tx.setSignature(signature); + if (verifySignature(transactionData, signature, walletSender.getKeyPair().getPublic())) { + System.out.println("Signature vérifiée"); + } else { + System.out.println("Signature non vérifiée"); + } + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } this.transactionsPool.add(tx); } + public String getTransactionData(Transaction tx) { + return tx.getInputs().toString() + tx.getOutputs().toString() + tx.getId(); + } + + public byte[] sign(String data, PrivateKey privateKey) + throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { + Signature signature = Signature.getInstance("SHA256withRSA"); + signature.initSign(privateKey); + signature.update(data.getBytes()); + return signature.sign(); + } + + public boolean verifySignature(String data, byte[] signature, PublicKey publicKey) + throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { + Signature sign = Signature.getInstance("SHA256withRSA"); + sign.initVerify(publicKey); + sign.update(data.getBytes()); + return sign.verify(signature); + } + public Wallet selectWallet(List<Wallet> wallets) { if (wallets.size() == 0) { return null; diff --git a/src/main/java/fr/miage/Coinbase.java b/src/main/java/fr/miage/Coinbase.java index 1f2ab8f52d96cfa579f17aafe5ff5f99e8b113ed..4a8273985a9e320dc2edb365409fb7a143691d8a 100644 --- a/src/main/java/fr/miage/Coinbase.java +++ b/src/main/java/fr/miage/Coinbase.java @@ -1,14 +1,15 @@ package fr.miage; +import java.security.PublicKey; import java.util.ArrayList; import java.util.List; public class Coinbase extends Transaction { - public Coinbase(List<UTxO> inputs, List<UTxO> outputs, String signature, EnumTypeTransaction typeTransaction) { + public Coinbase(List<UTxO> inputs, List<UTxO> outputs, PublicKey signature, EnumTypeTransaction typeTransaction) { super(inputs, outputs, signature, EnumTypeTransaction.COINBASE); } - public Coinbase(List<UTxO> outputs, String signature, EnumTypeTransaction typeTransaction) { + public Coinbase(List<UTxO> outputs, PublicKey signature, EnumTypeTransaction typeTransaction) { super(new ArrayList<UTxO>(), outputs, signature, EnumTypeTransaction.COINBASE); } } diff --git a/src/main/java/fr/miage/Transaction.java b/src/main/java/fr/miage/Transaction.java index 4835dcd305b5a68e965680b90806ae18c74699bc..fa4b91c4f226cc71e4b56b43e151d97376fcb324 100644 --- a/src/main/java/fr/miage/Transaction.java +++ b/src/main/java/fr/miage/Transaction.java @@ -2,6 +2,7 @@ package fr.miage; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; +import java.security.PublicKey; import java.security.Signature; import java.util.Arrays; import java.util.List; @@ -15,8 +16,10 @@ public class Transaction { private List<UTxO> inputs; private List<UTxO> outputs; private EnumTypeTransaction typeTransaction; + private byte[] signature; - public Transaction(List<UTxO> inputs, List<UTxO> outputs, String signature, EnumTypeTransaction typeTransaction) { + public Transaction(List<UTxO> inputs, List<UTxO> outputs, PublicKey PublicKey, + EnumTypeTransaction typeTransaction) { this.inputs = inputs; this.outputs = outputs; this.typeTransaction = typeTransaction; @@ -33,12 +36,13 @@ public class Transaction { this.receiver = receiver; this.typeTransaction = typeTransaction.NORMAL; this.id = UUID.randomUUID(); - UTxO utxoAmount = new UTxO(this.id, receiver.getPublicKey(), amount); // peut - // etre + UTxO utxoAmount = new UTxO(this.id, receiver.getKeyPair().getPublic(), amount); // peut + // etre // changr par // amout this.receiver.addUTxO(utxoAmount); - UTxO utxoRest = new UTxO(this.id, sender.getPublicKey(), getTotalAmountUtxoInput(inputs) - amount); + UTxO utxoRest = new UTxO(this.id, sender.getKeyPair().getPublic(), + getTotalAmountUtxoInput(inputs) - amount); this.sender.addUTxO(utxoRest); this.outputs = Arrays.asList(utxoAmount, utxoRest); Blockchain.utxos.addAll(this.outputs); @@ -94,6 +98,22 @@ public class Transaction { return this.typeTransaction; } + public Wallet getReceiver() { + return receiver; + } + + public Wallet getSender() { + return sender; + } + + public byte[] getSignature() { + return signature; + } + + public void setSignature(byte[] signature) { + this.signature = signature; + } + @Override public String toString() { return "{" + diff --git a/src/main/java/fr/miage/UTxO.java b/src/main/java/fr/miage/UTxO.java index 626101d2fc155f2bfc517bec1d1b748ae64706da..c4884a3eb95e297116ab68f8ad1df44b88efa26f 100644 --- a/src/main/java/fr/miage/UTxO.java +++ b/src/main/java/fr/miage/UTxO.java @@ -1,32 +1,32 @@ package fr.miage; +import java.security.PublicKey; import java.util.UUID; public class UTxO implements Comparable { - //UTXO : Hash qui renvoie a la transaction d'avant + // UTXO : Hash qui renvoie a la transaction d'avant private UUID uuid; // identifiant (transaction de provenances) - private String ownerAdresss; // clé publique du wallet + private PublicKey ownerAdresss; // clé publique du wallet private double montant; - public UTxO(UUID provenance, String ownerAdresss, double montant) { + public UTxO(UUID provenance, PublicKey ownerAdresss, double montant) { this.uuid = provenance; this.ownerAdresss = ownerAdresss; this.montant = montant; } - public String ownerAdress() { + public PublicKey ownerAdress() { return this.ownerAdresss; } public double getMontant() { return this.montant; } + public UUID getUuid() { return uuid; } - - @Override public String toString() { return "UTxO [uuid=" + uuid + ", ownerAdress=" + ownerAdresss + ", montant=" + montant + "]"; diff --git a/src/main/java/fr/miage/Wallet.java b/src/main/java/fr/miage/Wallet.java index 17f6e854f3bc2c803138e7f51a03fb196a67eb25..034f0be84c6573a7ae8858eeb0b2ed75eb65c429 100644 --- a/src/main/java/fr/miage/Wallet.java +++ b/src/main/java/fr/miage/Wallet.java @@ -1,70 +1,87 @@ package fr.miage; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.KeyStoreException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Wallet { - private String publicKey; - private String privateKey; // pour la signature + // private PublicKey publicKey; + // private PrivateKey privateKey; // pour la signature + private KeyPair keyPair; private double solde; private List<UTxO> utxos; private String name; // temp - public Wallet(String privateKey, String name) throws NoSuchAlgorithmException, InterruptedException { + public Wallet(String name) throws NoSuchAlgorithmException, InterruptedException { this.name = name; - this.privateKey = privateKey; - initWallet(); - createKeyPair(privateKey, name); + this.keyPair = generateKeyPair(); + this.utxos = new ArrayList<UTxO>(); } - public void initWallet() throws NoSuchAlgorithmException { - this.publicKey = hashSha256(this.privateKey); - this.utxos = new ArrayList<>(); - } - - public void createKeyPair(String privateKey, String name) throws InterruptedException { - - String command = "keytool -genkeypair -alias wallet_" + name + " -keyalg RSA -keysize 2048 -dname \"CN=" + name - + "\" -validity 365 -storetype JKS -keystore keystore.jks -storepass \"" + privateKey + "\""; - - System.out.println(command); - ProcessBuilder processBuilder = new ProcessBuilder(command.split("\\s+")); - processBuilder.redirectErrorStream(true); - // try { - // // Process process = processBuilder.start(); - // // OutputStream outputStream = process.getOutputStream(); - // // outputStream.write("\n".getBytes(StandardCharsets.UTF_8)); - // // outputStream.flush(); - // // outputStream.close(); - - // // InputStream inputStream = process.getInputStream(); - // // InputStream errorStream = process.getErrorStream(); - - // // byte[] buffer = new byte[1024]; - // // int bytesRead; - - // // while ((bytesRead = inputStream.read(buffer)) != -1) { - // // System.out.write(buffer, 0, bytesRead); - // // } - - // // while ((bytesRead = errorStream.read(buffer)) != -1) { - // // System.err.write(buffer, 0, bytesRead); - - // } - // }catch( - - // IOException e) - // { - // e.printStackTrace(); - System.out.println("Erreur lors de la création du keypair"); - System.out.println("Le wallet de " + name + " a été créé avec succès"); + // public void initWallet() throws NoSuchAlgorithmException { + // this.publicKey = hashSha256(this.privateKey); + // this.utxos = new ArrayList<>(); + // } + + // public void createKeyPair(String privateKey, String name) throws + // InterruptedException { + + // String command = "keytool -genkeypair -alias wallet_" + name + " -keyalg RSA + // -keysize 2048 -dname \"CN=" + name + // + "\" -validity 365 -storetype JKS -keystore keystore.jks -storepass \"" + + // privateKey + "\""; + + // System.out.println(command); + // ProcessBuilder processBuilder = new ProcessBuilder(command.split("\\s+")); + // processBuilder.redirectErrorStream(true); + // try { + // Process process = processBuilder.start(); + // OutputStream outputStream = process.getOutputStream(); + // outputStream.write("\n".getBytes(StandardCharsets.UTF_8)); + // outputStream.flush(); + // outputStream.close(); + // InputStream inputStream = process.getInputStream(); + // InputStream errorStream = process.getErrorStream(); + // byte[] buffer = new byte[1024]; + // int bytesRead; + // while ((bytesRead = inputStream.read(buffer)) != -1) { + // System.out.write(buffer, 0, bytesRead); + // } + // while ((bytesRead = errorStream.read(buffer)) != -1) { + // System.err.write(buffer, 0, bytesRead); + + // } + // } catch (IOException e) { + // e.printStackTrace(); + // System.out.println("Erreur lors de la création du keypair"); + // } + // System.out.println("Le wallet de " + name + " a été créé avec succès"); + // } + + public KeyPair generateKeyPair() throws NoSuchAlgorithmException { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(2048); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + return keyPair; } private String hashSha256(String privateKey) throws NoSuchAlgorithmException { @@ -97,10 +114,39 @@ public class Wallet { } - public String getPublicKey() { - return this.publicKey; + public void loadPrivateKey() throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, + CertificateException, FileNotFoundException, IOException { + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new FileInputStream("keystore.jks"), null); // replace null by privateKey + PrivateKey privateKey = (PrivateKey) keyStore.getKey("wallet_" + this.name, null); // replace null by // + // privateKey// // (password) } + // public void publishPublicKey() { + // String command = "keytool -exportcert -alias wallet_" + name + // + " -storetype JKS -keystore keystore.jks -file certificate.cer -rfc + // -storepass \"" + privateKey + "\""; + // System.out.println(command); + // ProcessBuilder processBuilder = new ProcessBuilder(command.split("\\s+")); + // try { + // Process process = processBuilder.start(); + // } catch (IOException e) { + // e.printStackTrace(); + // System.out.println("Erreur lors de la publication de la clé publique"); + // } + // } + + // public void loadPublicKeyForVerification() { + // String command = "keytool -exportcert -alias wallet_" + name + // + " -storetype JKS -keystore keystore.jks -file certificate.cer -rfc + // -storepass \"" + privateKey + "\""; + + // } + + // public String getPublicKey() { + // return this.publicKey; + // } + public String getName() { return name; } @@ -109,9 +155,9 @@ public class Wallet { this.name = name; } - public String getPrivateKey() { - return this.privateKey; - } + // public String getPrivateKey() { + // return this.privateKey; + // } public List<UTxO> getUtxos() { return this.utxos; @@ -123,10 +169,15 @@ public class Wallet { @Override public String toString() { - return "{" + - " publicKey='" + getPublicKey() + "'" + - ", privateKey='" + getPrivateKey() + "'" + - ", utxos='" + getUtxos() + "'" + - "}"; + return "Wallet [keyPair=" + keyPair + ", solde=" + solde + ", utxos=" + utxos + ", name=" + name + "]"; + } + + public KeyPair getKeyPair() { + return keyPair; + } + + public void setKeyPair(KeyPair keyPair) { + this.keyPair = keyPair; } + }