diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..804d8bd --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/monoblock.iml b/.idea/monoblock.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/monoblock.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/chain/block.go b/chain/block.go new file mode 100644 index 0000000..6f83730 --- /dev/null +++ b/chain/block.go @@ -0,0 +1,79 @@ +package chain + +import ( + "bytes" + "encoding/gob" + "fmt" + "golang.org/x/crypto/sha3" + "log" + "math/rand" +) + +type block struct { + Transactions []transaction + HashPrevious []byte + Nonce []byte +} + +func NewBlock(hashPrevious []byte) block { + return block{ + Transactions: nil, + HashPrevious: hashPrevious, + } +} + +func (b *block) AddTransaction(t transaction) { + b.Transactions = append(b.Transactions, t) +} + +func (b block) GenerateHash(difficulty int) []byte { + found := false + var compBytes []byte + for i := 0; i < difficulty; i++ { + compBytes = append(compBytes, []byte("0x00")...) + } + for !found { + random := make([]byte, 64) + rand.Read(random) + b.Nonce = random + var buf bytes.Buffer + err := gob.NewEncoder(&buf).Encode(b.Nonce) + if err != nil { + log.Fatal(err) + } + hasher := sha3.New512() + hasher.Write(b.ToBytes()) + hash := hasher.Sum(nil) + fmt.Printf("\033[2K\r%x\n", hash) + if checkAllZero(XorSlice(hash[:difficulty], compBytes)) { + return hash + } + } + return nil +} + +func (b block) ToBytes() []byte { + var bytes []byte + for i := 0; i < len(b.Transactions); i++ { + bytes = append(bytes, b.Transactions[i].ToBytes()...) + } + bytes = append(bytes, b.Nonce...) + return bytes +} + +func XorSlice(a []byte, b []byte) []byte { + for i, _ := range a { + a[i] = a[i] ^ b[i] + } + return a +} + +func checkAllZero(a []byte) bool { + fmt.Printf("Checking if all zero: %x\n", a) + for i, _ := range a { + if a[i] != 0x00 { + return false + } + } + return true +} diff --git a/chain/chain.go b/chain/chain.go new file mode 100644 index 0000000..fef1d20 --- /dev/null +++ b/chain/chain.go @@ -0,0 +1 @@ +package chain diff --git a/chain/transaction.go b/chain/transaction.go new file mode 100644 index 0000000..1f8ac52 --- /dev/null +++ b/chain/transaction.go @@ -0,0 +1,43 @@ +package chain + +import ( + "bytes" + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "encoding/gob" + "time" +) + +type transaction struct { + Src string + Dst string + Amount int + Timestamp time.Time +} + +func NewTransaction(source string, dst string, amount int) transaction { + return transaction{Src: source, Dst: dst, Amount: amount, Timestamp: time.Now()} +} + +func (ta transaction) SignTransaction(privKey *rsa.PrivateKey, d int) ([]byte, error) { + + return rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, ta.HashTransaction()) +} + +func (ta transaction) HashTransaction() []byte { + var buf bytes.Buffer + gob.NewEncoder(&buf).Encode(ta) + hash := sha256.New().Sum(buf.Bytes()) + return hash +} + +func (ta transaction) ToBytes() []byte { + bytes := []byte(ta.Src) + bytes = append(bytes, []byte(ta.Dst)...) + //fmt.Printf("%s", ta.Dst) + bytes = append(bytes, byte(ta.Amount)) + bytes = append(bytes, []byte(ta.Timestamp.String())...) + return bytes +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4ea6608 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module monoblock + +go 1.14 + +require golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a5090e1 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/go_build_monoblock.exe b/go_build_monoblock.exe new file mode 100644 index 0000000..752b197 Binary files /dev/null and b/go_build_monoblock.exe differ diff --git a/keymgmt/keymgmt.go b/keymgmt/keymgmt.go new file mode 100644 index 0000000..3ce54e2 --- /dev/null +++ b/keymgmt/keymgmt.go @@ -0,0 +1,34 @@ +package keymgmt + +import ( + "crypto/rand" + "crypto/rsa" + "encoding/base64" + "golang.org/x/crypto/sha3" + "log" + "math/big" +) + +type Address struct { + pubkey int + privkey *rsa.PrivateKey + mod *big.Int +} + +func GenerateAddress() *Address { + key, err := rsa.GenerateKey(rand.Reader, 1024) + + if err != nil { + log.Fatal(err) + } + newAddress := Address{pubkey: key.E, privkey: key, mod: key.N} + return &newAddress +} + +func (a Address) GetAddress() string { + hasher := sha3.New224() + hash := hasher.Sum(a.privkey.N.Bytes()) + b64 := "!MBPA#" + base64.StdEncoding.EncodeToString(hash)[:64] + + return b64 +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..ac43c4a --- /dev/null +++ b/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "bufio" + "encoding/hex" + "fmt" + "monoblock/chain" + "monoblock/keymgmt" + "os" +) + +const AMOUNT int = 100 + +func main() { + by1, _ := hex.DecodeString("0001020304") + by2, _ := hex.DecodeString("0001020304") + + fmt.Printf("%x", chain.XorSlice(by1, by2)) + + addr1 := keymgmt.GenerateAddress() + addr2 := keymgmt.GenerateAddress() + addr3 := keymgmt.GenerateAddress() + addr4 := keymgmt.GenerateAddress() + ta1 := chain.NewTransaction(addr3.GetAddress(), addr1.GetAddress(), 100) + ta2 := chain.NewTransaction(addr2.GetAddress(), addr4.GetAddress(), 100) + b1 := chain.NewBlock(nil) + b1.AddTransaction(ta1) + b1.AddTransaction(ta2) + hash := b1.GenerateHash(4) + fmt.Printf("Hash found:\n\n%x\n\n", hash) + bufio.NewReader(os.Stdin).ReadBytes('\n') +} + +func generateKey(ch chan *keymgmt.Address, amount int) { + for i := 0; i < amount; i++ { + addr := keymgmt.GenerateAddress() + ch <- addr + } + +}