Skip to content
Snippets Groups Projects
Commit ade1fde2 authored by saintdi25u's avatar saintdi25u
Browse files

feat-transaction : implémentation de la signature

parent 4766f5ec
Branches
No related tags found
No related merge requests found
No preview for this file type
...@@ -15,14 +15,14 @@ public class App { ...@@ -15,14 +15,14 @@ public class App {
public static void main(String[] args) throws NoSuchAlgorithmException, InterruptedException { public static void main(String[] args) throws NoSuchAlgorithmException, InterruptedException {
System.out.println("Début de la blockchain"); System.out.println("Début de la blockchain");
// Création de 2 wallets // Création de 2 wallets
Wallet bobWallet = new Wallet("jesuislacleprivedebob", "bob"); Wallet bobWallet = new Wallet("bob");
Wallet aliceWallet = new Wallet("je suis la clé privé de alice", "alice"); Wallet aliceWallet = new Wallet("alice");
List<Wallet> wallets = Arrays.asList(bobWallet, aliceWallet); List<Wallet> wallets = Arrays.asList(bobWallet, aliceWallet);
Blockchain blockchain = new Blockchain("BloBlockchain", wallets); Blockchain blockchain = new Blockchain("BloBlockchain", wallets);
System.out.println("Wallet de bob : " + bobWallet.getUtxos()); // System.out.println("Wallet de bob : " + bobWallet.getUtxos());
System.out.println("Wallet de alice : " + aliceWallet.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 bob : " + bobWallet.getUtxos());
// System.out.println("Utxos du wallet de alice : " + aliceWallet.getUtxos()); // System.out.println("Utxos du wallet de alice : " + aliceWallet.getUtxos());
// Transaction transaction = new Transaction(bobWallet, aliceWallet, 2, // Transaction transaction = new Transaction(bobWallet, aliceWallet, 2,
...@@ -38,7 +38,8 @@ public class App { ...@@ -38,7 +38,8 @@ public class App {
blockchain.createTrasaction(); blockchain.createTrasaction();
i++; 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 // // print all utxo in the utxo set
// for (UTxO utxo : Blockchain.utxos) { // for (UTxO utxo : Blockchain.utxos) {
......
...@@ -51,7 +51,7 @@ public class Bloc { ...@@ -51,7 +51,7 @@ public class Bloc {
List<Transaction> transactions = new ArrayList<Transaction>(); List<Transaction> transactions = new ArrayList<Transaction>();
for (Wallet wallet : wallets) { for (Wallet wallet : wallets) {
int amount = RandomNumberGenerator.getRandomNumber(1, 20); 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); wallet.addUTxO(utxo);
Blockchain.utxos.add(utxo); Blockchain.utxos.add(utxo);
List<UTxO> utxos = new ArrayList<UTxO>() { List<UTxO> utxos = new ArrayList<UTxO>() {
...@@ -60,10 +60,10 @@ public class Bloc { ...@@ -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); 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); BlocHeader blocHeader = new BlocHeader("", Instant.now().toEpochMilli(), 0);
String header = blocHeader.toString(); String header = blocHeader.toString();
......
package fr.miage; 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.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
...@@ -42,22 +48,56 @@ public class Blockchain { ...@@ -42,22 +48,56 @@ public class Blockchain {
double amountWalletSender = walletSender.getUtxos().stream().mapToDouble(utxo -> utxo.getMontant()).sum(); double amountWalletSender = walletSender.getUtxos().stream().mapToDouble(utxo -> utxo.getMontant()).sum();
double randomAmountToSend = new Random().nextDouble(amountWalletSender); double randomAmountToSend = new Random().nextDouble(amountWalletSender);
System.out.println("Amount to send : " + randomAmountToSend); // System.out.println("Amount to send : " + randomAmountToSend);
System.out.println("Envoie de " + walletSender.getName() + " à " + walletReceiver.getName()); // System.out.println("Envoie de " + walletSender.getName() + " à " +
System.out.println(); // walletReceiver.getName());
System.out.println("Utxos de " + walletSender.getName() + " : " + walletSender.getUtxos()); // System.out.println();
System.out.println("Utxos de " + walletReceiver.getName() + " : " + walletReceiver.getUtxos()); // System.out.println("Utxos de " + walletSender.getName() + " : " +
System.out.println(); // walletSender.getUtxos());
// System.out.println("Utxos de " + walletReceiver.getName() + " : " +
// walletReceiver.getUtxos());
// System.out.println();
if (walletSender.getUtxos().isEmpty() || walletReceiver.getUtxos().isEmpty()) { if (walletSender.getUtxos().isEmpty() || walletReceiver.getUtxos().isEmpty()) {
System.out.println("Wallets vides"); System.out.println("Wallets vides");
return; return;
} }
Transaction tx = new Transaction(walletSender, walletReceiver, randomAmountToSend, EnumTypeTransaction.NORMAL); 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); 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) { public Wallet selectWallet(List<Wallet> wallets) {
if (wallets.size() == 0) { if (wallets.size() == 0) {
return null; return null;
......
package fr.miage; package fr.miage;
import java.security.PublicKey;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Coinbase extends Transaction { 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); 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); super(new ArrayList<UTxO>(), outputs, signature, EnumTypeTransaction.COINBASE);
} }
} }
...@@ -2,6 +2,7 @@ package fr.miage; ...@@ -2,6 +2,7 @@ package fr.miage;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature; import java.security.Signature;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -15,8 +16,10 @@ public class Transaction { ...@@ -15,8 +16,10 @@ public class Transaction {
private List<UTxO> inputs; private List<UTxO> inputs;
private List<UTxO> outputs; private List<UTxO> outputs;
private EnumTypeTransaction typeTransaction; 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.inputs = inputs;
this.outputs = outputs; this.outputs = outputs;
this.typeTransaction = typeTransaction; this.typeTransaction = typeTransaction;
...@@ -33,12 +36,13 @@ public class Transaction { ...@@ -33,12 +36,13 @@ public class Transaction {
this.receiver = receiver; this.receiver = receiver;
this.typeTransaction = typeTransaction.NORMAL; this.typeTransaction = typeTransaction.NORMAL;
this.id = UUID.randomUUID(); this.id = UUID.randomUUID();
UTxO utxoAmount = new UTxO(this.id, receiver.getPublicKey(), amount); // peut UTxO utxoAmount = new UTxO(this.id, receiver.getKeyPair().getPublic(), amount); // peut
// etre // etre
// changr par // changr par
// amout // amout
this.receiver.addUTxO(utxoAmount); 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.sender.addUTxO(utxoRest);
this.outputs = Arrays.asList(utxoAmount, utxoRest); this.outputs = Arrays.asList(utxoAmount, utxoRest);
Blockchain.utxos.addAll(this.outputs); Blockchain.utxos.addAll(this.outputs);
...@@ -94,6 +98,22 @@ public class Transaction { ...@@ -94,6 +98,22 @@ public class Transaction {
return this.typeTransaction; 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 @Override
public String toString() { public String toString() {
return "{" + return "{" +
......
package fr.miage; package fr.miage;
import java.security.PublicKey;
import java.util.UUID; import java.util.UUID;
public class UTxO implements Comparable { 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 UUID uuid; // identifiant (transaction de provenances)
private String ownerAdresss; // clé publique du wallet private PublicKey ownerAdresss; // clé publique du wallet
private double montant; private double montant;
public UTxO(UUID provenance, String ownerAdresss, double montant) { public UTxO(UUID provenance, PublicKey ownerAdresss, double montant) {
this.uuid = provenance; this.uuid = provenance;
this.ownerAdresss = ownerAdresss; this.ownerAdresss = ownerAdresss;
this.montant = montant; this.montant = montant;
} }
public String ownerAdress() { public PublicKey ownerAdress() {
return this.ownerAdresss; return this.ownerAdresss;
} }
public double getMontant() { public double getMontant() {
return this.montant; return this.montant;
} }
public UUID getUuid() { public UUID getUuid() {
return uuid; return uuid;
} }
@Override @Override
public String toString() { public String toString() {
return "UTxO [uuid=" + uuid + ", ownerAdress=" + ownerAdresss + ", montant=" + montant + "]"; return "UTxO [uuid=" + uuid + ", ownerAdress=" + ownerAdresss + ", montant=" + montant + "]";
......
package fr.miage; package fr.miage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets; 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.MessageDigest;
import java.security.NoSuchAlgorithmException; 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.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class Wallet { public class Wallet {
private String publicKey; // private PublicKey publicKey;
private String privateKey; // pour la signature // private PrivateKey privateKey; // pour la signature
private KeyPair keyPair;
private double solde; private double solde;
private List<UTxO> utxos; private List<UTxO> utxos;
private String name; // temp private String name; // temp
public Wallet(String privateKey, String name) throws NoSuchAlgorithmException, InterruptedException { public Wallet(String name) throws NoSuchAlgorithmException, InterruptedException {
this.name = name; this.name = name;
this.privateKey = privateKey; this.keyPair = generateKeyPair();
initWallet(); this.utxos = new ArrayList<UTxO>();
createKeyPair(privateKey, name);
} }
public void initWallet() throws NoSuchAlgorithmException { // public void initWallet() throws NoSuchAlgorithmException {
this.publicKey = hashSha256(this.privateKey); // this.publicKey = hashSha256(this.privateKey);
this.utxos = new ArrayList<>(); // this.utxos = new ArrayList<>();
} // }
public void createKeyPair(String privateKey, String name) throws InterruptedException { // 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 + "\""; // String command = "keytool -genkeypair -alias wallet_" + name + " -keyalg RSA
// -keysize 2048 -dname \"CN=" + name
System.out.println(command); // + "\" -validity 365 -storetype JKS -keystore keystore.jks -storepass \"" +
ProcessBuilder processBuilder = new ProcessBuilder(command.split("\\s+")); // privateKey + "\"";
processBuilder.redirectErrorStream(true);
// try { // System.out.println(command);
// // Process process = processBuilder.start(); // ProcessBuilder processBuilder = new ProcessBuilder(command.split("\\s+"));
// // OutputStream outputStream = process.getOutputStream(); // processBuilder.redirectErrorStream(true);
// // outputStream.write("\n".getBytes(StandardCharsets.UTF_8)); // try {
// // outputStream.flush(); // Process process = processBuilder.start();
// // outputStream.close(); // OutputStream outputStream = process.getOutputStream();
// outputStream.write("\n".getBytes(StandardCharsets.UTF_8));
// // InputStream inputStream = process.getInputStream(); // outputStream.flush();
// // InputStream errorStream = process.getErrorStream(); // outputStream.close();
// InputStream inputStream = process.getInputStream();
// // byte[] buffer = new byte[1024]; // InputStream errorStream = process.getErrorStream();
// // int bytesRead; // byte[] buffer = new byte[1024];
// int bytesRead;
// // while ((bytesRead = inputStream.read(buffer)) != -1) { // while ((bytesRead = inputStream.read(buffer)) != -1) {
// // System.out.write(buffer, 0, bytesRead); // System.out.write(buffer, 0, bytesRead);
// // } // }
// while ((bytesRead = errorStream.read(buffer)) != -1) {
// // while ((bytesRead = errorStream.read(buffer)) != -1) { // System.err.write(buffer, 0, bytesRead);
// // System.err.write(buffer, 0, bytesRead);
// }
// } // } catch (IOException e) {
// }catch( // e.printStackTrace();
// System.out.println("Erreur lors de la création du keypair");
// IOException e) // }
// { // System.out.println("Le wallet de " + name + " a été créé avec succès");
// 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 { private String hashSha256(String privateKey) throws NoSuchAlgorithmException {
...@@ -97,10 +114,39 @@ public class Wallet { ...@@ -97,10 +114,39 @@ public class Wallet {
} }
public String getPublicKey() { public void loadPrivateKey() throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException,
return this.publicKey; 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() { public String getName() {
return name; return name;
} }
...@@ -109,9 +155,9 @@ public class Wallet { ...@@ -109,9 +155,9 @@ public class Wallet {
this.name = name; this.name = name;
} }
public String getPrivateKey() { // public String getPrivateKey() {
return this.privateKey; // return this.privateKey;
} // }
public List<UTxO> getUtxos() { public List<UTxO> getUtxos() {
return this.utxos; return this.utxos;
...@@ -123,10 +169,15 @@ public class Wallet { ...@@ -123,10 +169,15 @@ public class Wallet {
@Override @Override
public String toString() { public String toString() {
return "{" + return "Wallet [keyPair=" + keyPair + ", solde=" + solde + ", utxos=" + utxos + ", name=" + name + "]";
" publicKey='" + getPublicKey() + "'" + }
", privateKey='" + getPrivateKey() + "'" +
", utxos='" + getUtxos() + "'" + public KeyPair getKeyPair() {
"}"; return keyPair;
}
public void setKeyPair(KeyPair keyPair) {
this.keyPair = keyPair;
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment