-
Notifications
You must be signed in to change notification settings - Fork 0
/
transactions.go
131 lines (111 loc) · 3.09 KB
/
transactions.go
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
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
"strconv"
)
type Wallet struct {
PublicKey *rsa.PublicKey
PrivateKey *rsa.PrivateKey
}
type Transaction struct {
Sender, Receiver *rsa.PublicKey
Signature []byte
Amount int
Inputs []TransactionInput // Proof that send has funds to send
Outputs []TransactionOutput //
}
type TransactionInput struct {
TransactionOutputId string
UTXO TransactionOutput // Unspent Transaction Output
}
// These are referenced when new transactions are made as proof the sender has coins
type TransactionOutput struct {
Id string
Receiver *rsa.PublicKey;
Amout int;
parentTransactionId string;
}
func initializeNewWallet() Wallet{
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
publicKey := privateKey.PublicKey
newWallet := Wallet{
PublicKey: &publicKey,
PrivateKey: privateKey,
}
return newWallet
}
func encryptTransaction(publicKey *rsa.PublicKey) []byte{
encryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
publicKey,
[]byte("transaction data"),
nil)
if err != nil {
panic(err)
}
fmt.Println("encrypted bytes: ", encryptedBytes)
return encryptedBytes
}
func decryptTransaction(privateKey *rsa.PrivateKey, cipherText []byte) string{
decryptedBytes, err := privateKey.Decrypt(
nil,
cipherText,
&rsa.OAEPOptions{Hash: crypto.SHA256}, // Same hashing we used to encrypt the message
)
if err != nil {
panic(err)
}
fmt.Println("decrypted message: ", string(decryptedBytes))
return string(decryptedBytes)
}
// Generate the data to be signed by a private key
func generateUniqueTransactionHashSum(transaction Transaction) []byte{
h := sha256.New()
unique := strconv.Itoa(transaction.Sender.E) + strconv.Itoa(transaction.Receiver.E) + strconv.Itoa(transaction.Amount)
_, err := h.Write([]byte(unique))
if err != nil {
panic(err)
}
hashSum := h.Sum(nil)
return hashSum
}
// Sign unique data(msgHashSum) using a private key
// Returns the signature and data that was signed
func signTransaction(privateKey *rsa.PrivateKey, transaction Transaction) ([]byte, []byte){
msgHashSum := generateUniqueTransactionHashSum(transaction)
signature, err := rsa.SignPSS(
rand.Reader,
privateKey, // private key of sender
crypto.SHA256,
msgHashSum,
nil,
)
if err != nil {
panic(err)
}
return signature, msgHashSum
}
// Verify that the signature is indeed signed of the input data(msgHashSum) by the owner of the sender in the transaction
func verifySignature(signature []byte, transaction Transaction, msgHashSum []byte) bool{
err := rsa.VerifyPSS(
transaction.Sender,
crypto.SHA256,
msgHashSum,
signature,
nil,
)
if err != nil {
fmt.Println("Could not verify signature: ", err)
return false
}
// Signature is valid
return true
}