-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHello, Blockchain.java
More file actions
154 lines (123 loc) · 4.97 KB
/
Hello, Blockchain.java
File metadata and controls
154 lines (123 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.util.encoders.Hex;
import java.security.Security;
import java.security.SecureRandom;
public class BlockchainCryptoExamples {
static {
// Register Bouncy Castle provider
Security.addProvider(new BouncyCastleProvider());
}
/**
* Generate a SHA-256 hash of input data
*/
public static String sha256Hash(String input) {
SHA256Digest digest = new SHA256Digest();
byte[] inputBytes = input.getBytes();
digest.update(inputBytes, 0, inputBytes.length);
byte[] hashBytes = new byte[digest.getDigestSize()];
digest.doFinal(hashBytes, 0);
return Hex.toHexString(hashBytes);
}
/**
* Generate a secp256k1 key pair (commonly used in blockchain)
*/
public static AsymmetricCipherKeyPair generateKeyPair() {
ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
SecureRandom random = new SecureRandom();
// Use secp256k1 curve parameters
ECDomainParameters domainParams = SECNamedCurves.getByName("secp256k1");
ECKeyGenerationParameters params =
new ECKeyGenerationParameters(domainParams, random);
keyGen.init(params);
return keyGen.generateKeyPair();
}
/**
* Sign a message using ECDSA with the secp256k1 curve
*/
public static byte[] signMessage(AsymmetricCipherKeyPair keyPair, byte[] message) {
SHA256Digest digest = new SHA256Digest();
ECDSASigner signer = new ECDSASigner();
signer.init(true, keyPair.getPrivate());
digest.update(message, 0, message.length);
byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
BigInteger[] signature = signer.generateSignature(hash);
// Encode signature components (r,s) into DER format
return encodeDERSignature(signature[0], signature[1]);
}
/**
* Verify an ECDSA signature
*/
public static boolean verifySignature(
ECPublicKeyParameters publicKey,
byte[] message,
byte[] signature
) {
SHA256Digest digest = new SHA256Digest();
ECDSASigner signer = new ECDSASigner();
signer.init(false, publicKey);
digest.update(message, 0, message.length);
byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
// Decode DER signature into (r,s) components
BigInteger[] sigComponents = decodeDERSignature(signature);
return signer.verifySignature(hash, sigComponents[0], sigComponents[1]);
}
/**
* https://brilliant.org/wiki/merkle-tree/
* Generate a Merkle tree root from a list of transaction hashes
*/
public static String calculateMerkleRoot(List<String> txHashes) {
if (txHashes == null || txHashes.isEmpty()) {
return "";
}
List<String> tempHashes = new ArrayList<>(txHashes);
while (tempHashes.size() > 1) {
List<String> newHashes = new ArrayList<>();
for (int i = 0; i < tempHashes.size() - 1; i += 2) {
String combinedHash = sha256Hash(
tempHashes.get(i) + tempHashes.get(i + 1)
);
newHashes.add(combinedHash);
}
// Handle odd number of elements
if (tempHashes.size() % 2 == 1) {
String lastHash = tempHashes.get(tempHashes.size() - 1);
newHashes.add(sha256Hash(lastHash + lastHash));
}
tempHashes = newHashes;
}
return tempHashes.get(0);
}
/**
* Example usage
*/
public static void main(String[] args) {
// Generate key pair
AsymmetricCipherKeyPair keyPair = generateKeyPair();
// Sign a message
String message = "HHello, Blockchain!";
byte[] signature = signMessage(keyPair, message.getBytes());
// Verify signature
boolean isValid = verifySignature(
(ECPublicKeyParameters)keyPair.getPublic(),
message.getBytes(),
signature
);
System.out.println("Signature valid: " + isValid);
// Calculate Merkle root
List<String> txHashes = Arrays.asList(
sha256Hash("tx1"),
sha256Hash("tx2"),
sha256Hash("tx3"),
sha256Hash("tx4")
);
String merkleRoot = calculateMerkleRoot(txHashes);
System.out.println("Merkle root: " + merkleRoot);
}
}