Fix implementation, tests, and implement go modules

This commit is contained in:
kayos@tcp.direct 2022-07-09 10:16:08 -07:00
parent 251c6c0092
commit a381f5b298
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
5 changed files with 86 additions and 46 deletions

3
.gitignore vendored
View File

@ -10,3 +10,6 @@
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out
# Jetbrains
.idea/

View File

@ -8,9 +8,12 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/btcsuite/btcd/btcec"
"golang.org/x/crypto/sha3"
"time" "time"
"git.tcp.direct/kayos/common/entropy"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"golang.org/x/crypto/sha3"
) )
func (obj *SecureJson) encrypt(plainText []byte, iv []byte, key []byte) ([]byte, error) { func (obj *SecureJson) encrypt(plainText []byte, iv []byte, key []byte) ([]byte, error) {
@ -23,7 +26,7 @@ func (obj *SecureJson) encrypt(plainText []byte, iv []byte, key []byte) ([]byte,
return []byte{}, err return []byte{}, err
} }
cipherText := make([]byte, len(plainText)) cipherText := make([]byte, len(plainText))
//iv := make([]byte, aes.BlockSize) // iv := make([]byte, aes.BlockSize)
stream := cipher.NewCTR(block, iv[:aes.BlockSize]) stream := cipher.NewCTR(block, iv[:aes.BlockSize])
stream.XORKeyStream(cipherText, plainText) stream.XORKeyStream(cipherText, plainText)
@ -31,7 +34,7 @@ func (obj *SecureJson) encrypt(plainText []byte, iv []byte, key []byte) ([]byte,
} }
func (obj *SecureJson) genHash(userBytes []byte, encryptedBytes []byte, timeBytes []byte, pubkeyBytes []byte) (fullHash []byte) { func (obj *SecureJson) genHash(userBytes []byte, encryptedBytes []byte, timeBytes []byte, pubkeyBytes []byte) (fullHash []byte) {
userHash, _ := obj.hash(userBytes) userHash, _ := obj.hash(userBytes)
dataHash, _ := obj.hash(encryptedBytes) dataHash, _ := obj.hash(encryptedBytes)
timeHash, _ := obj.hash(timeBytes) timeHash, _ := obj.hash(timeBytes)
pubkeyHash, _ := obj.hash(pubkeyBytes[:65]) pubkeyHash, _ := obj.hash(pubkeyBytes[:65])
@ -40,8 +43,8 @@ func (obj *SecureJson) genHash(userBytes []byte, encryptedBytes []byte, timeByte
copy(full[:32], userHash) copy(full[:32], userHash)
copy(full[32:64], pubkeyHash) copy(full[32:64], pubkeyHash)
copy(full[64:96], timeHash) copy(full[64:96], timeHash)
copy(full[96:128], dataHash) copy(full[96:128], dataHash)
fullHash, _ = obj.hash(full[:128]) fullHash, _ = obj.hash(full[:128])
return return
} }
@ -63,11 +66,11 @@ func (obj *SecureJson) checkInputOutputJson(inputJson []byte, outputJson []byte)
return return
} }
if ji.PublicKey != jo.PublicKey { if ji.PublicKey != jo.PublicKey {
err = errors.New("Check fail for PublicKey") err = errors.New("check failed for PublicKey")
return return
} }
if obj.convertFromStringToInt64(ji.Timestamp) < obj.convertFromStringToInt64(jo.Timestamp) { if obj.convertFromStringToInt64(ji.Timestamp) < obj.convertFromStringToInt64(jo.Timestamp) {
err = errors.New("Check fail for Timestamp. Input timestamp must be greater then the ouput one.") err = errors.New("input timestamp must be greater then the ouput one")
return return
} }
ok = true ok = true
@ -101,14 +104,14 @@ func (obj *SecureJson) putJsonToStorage(inputJson []byte) (err error) {
} }
func (obj *SecureJson) convertFromStringToInt64(timeStr string) (timestamp int64) { func (obj *SecureJson) convertFromStringToInt64(timeStr string) (timestamp int64) {
fmt.Sscanf(timeStr, "%x", &timestamp) _, _ = fmt.Sscanf(timeStr, "%x", &timestamp)
return return
} }
func (obj *SecureJson) checkTimestampBeforeNow(timeStr string) (ok bool) { func (obj *SecureJson) checkTimestampBeforeNow(timeStr string) (ok bool) {
timestamp := obj.convertFromStringToInt64(timeStr) timestamp := obj.convertFromStringToInt64(timeStr)
timenow := time.Now().UnixNano() timenow := time.Now().UnixNano()
return (timenow > timestamp) return timenow > timestamp
} }
func (obj *SecureJson) bytesToString(msg []byte) string { func (obj *SecureJson) bytesToString(msg []byte) string {
@ -125,11 +128,11 @@ func (obj *SecureJson) stringToBytes(msg string) (res []byte) {
} }
func (obj *SecureJson) verify(msg []byte, pub []byte, sig []byte) bool { func (obj *SecureJson) verify(msg []byte, pub []byte, sig []byte) bool {
pubKey, err := btcec.ParsePubKey(pub, btcec.S256()) pubKey, err := btcec.ParsePubKey(pub)
if err != nil { if err != nil {
return false return false
} }
signature, err := btcec.ParseSignature(sig, btcec.S256()) signature, err := ecdsa.ParseSignature(sig)
if err != nil { if err != nil {
return false return false
} }
@ -137,40 +140,43 @@ func (obj *SecureJson) verify(msg []byte, pub []byte, sig []byte) bool {
} }
func (obj *SecureJson) sign(msg []byte, privKey []byte) ([]byte, error) { func (obj *SecureJson) sign(msg []byte, privKey []byte) ([]byte, error) {
priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKey) priv, _ := btcec.PrivKeyFromBytes(privKey)
sig, err := priv.Sign(msg) sig, err := priv.ToECDSA().Sign(entropy.GetOptimizedRand(), msg, nil)
if err != nil { if err != nil {
return []byte{}, err return []byte{}, err
} }
return sig.Serialize(), err return sig, err
} }
func (obj *SecureJson) getPubKey(privKey []byte) ([]byte, error) { func (obj *SecureJson) getPubKey(privKey []byte) ([]byte, error) {
pubKey := make([]byte, 65) pubKey := make([]byte, 65)
_, pub := btcec.PrivKeyFromBytes(btcec.S256(), privKey) _, pub := btcec.PrivKeyFromBytes(privKey)
pubKey = pub.SerializeUncompressed() pubKey = pub.SerializeUncompressed()
return pubKey, nil return pubKey, nil
} }
func (obj *SecureJson) getTimestamp() ([]byte, error) { func (obj *SecureJson) getTimestamp() ([]byte, error) {
timeNowBytes := make([]byte, 8) timeNowBytes := make([]byte, 8)
timeNowStr := fmt.Sprintf("%x", time.Now().Unix()) timeNowStr := fmt.Sprintf("%x", time.Now().Unix())
timeNowBytes, err := hex.DecodeString(timeNowStr) timeNowBytes, err := hex.DecodeString(timeNowStr)
return timeNowBytes, err return timeNowBytes, err
} }
func (obj *SecureJson) shake256(data []byte, length int) ([]byte, error) {
sum := make([]byte, length)
hashObj := sha3.NewShake256()
hashObj.Write(data)
hashObj.Read(sum)
return sum, nil
}
func (obj *SecureJson) hash(data []byte) ([]byte, error) { func (obj *SecureJson) shake256(data []byte, length int) ([]byte, error) {
sum := make([]byte, length)
hashObj := sha3.NewShake256()
_, writeErr := hashObj.Write(data)
if writeErr != nil {
return sum, writeErr
}
_, readErr := hashObj.Read(sum)
return sum, readErr
}
func (obj *SecureJson) hash(data []byte) ([]byte, error) {
return obj.shake256(data, 32) return obj.shake256(data, 32)
} }
func (obj *SecureJson) genIv(userName string) ([]byte, error) { func (obj *SecureJson) genIv(userName string) ([]byte, error) {
return obj.shake256([]byte(userName), 16) return obj.shake256([]byte(userName), 16)
} }

15
go.mod Normal file
View File

@ -0,0 +1,15 @@
module securejson
go 1.18
require (
git.tcp.direct/kayos/common v0.5.6-0.20220708105112-d07f8de10512
github.com/btcsuite/btcd/btcec/v2 v2.2.0
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
)
require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
nullprogram.com/x/rng v1.1.0 // indirect
)

16
go.sum Normal file
View File

@ -0,0 +1,16 @@
git.tcp.direct/kayos/common v0.5.6-0.20220708105112-d07f8de10512 h1:2Ti+OV+z5ld7Ivb2TmmLPTK7+KxgjlnGY1Md6b2QnMs=
git.tcp.direct/kayos/common v0.5.6-0.20220708105112-d07f8de10512/go.mod h1:jG1yXbN+5PrRZwGe32qIGWgLC4x5JWdyNBbMj1gIWB0=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
nullprogram.com/x/rng v1.1.0 h1:SMU7DHaQSWtKJNTpNFIFt8Wd/KSmOuSDPXrMFp/UMro=
nullprogram.com/x/rng v1.1.0/go.mod h1:glGw6V87vyfawxCzqOABL3WfL95G65az9Z2JZCylCkg=

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"testing"
) )
type StubStorage struct { type StubStorage struct {
@ -12,7 +13,7 @@ type StubStorage struct {
func (obj *StubStorage) Put(key string, value []byte) error { func (obj *StubStorage) Put(key string, value []byte) error {
obj.jsonBytes = value obj.jsonBytes = value
//fmt.Println("Put", string(obj.jsonBytes)) fmt.Println("Put", string(obj.jsonBytes))
return nil return nil
} }
@ -20,43 +21,42 @@ func (obj *StubStorage) Get(key string) ([]byte, error) {
if len(obj.jsonBytes) == 0 { if len(obj.jsonBytes) == 0 {
return []byte{}, errors.New("Empty") return []byte{}, errors.New("Empty")
} }
//fmt.Println("Get", string(obj.jsonBytes)) fmt.Println("Get", string(obj.jsonBytes))
return obj.jsonBytes, nil return obj.jsonBytes, nil
} }
func testJson(jsonBytes []byte, logprifix string, obj *SecureJson) { func testJson(jsonBytes []byte, logPrefix string, obj *SecureJson, t *testing.T) {
ok, err := obj.VerifyJson(jsonBytes) ok, err := obj.VerifyJson(jsonBytes)
if err != nil || !ok { if err != nil || !ok {
fmt.Println(err) t.Errorf("%s: VerifyJson failed: %s", logPrefix, err)
fmt.Println(logprifix, "Verify the Json Fail")
} }
var data Json var data Json
err = json.Unmarshal(jsonBytes, &data) err = json.Unmarshal(jsonBytes, &data)
if err != nil { if err != nil {
fmt.Println(logprifix, "Json Unmarshal Fail") t.Errorf("%s: Unmarshal failed: %s", logPrefix, err)
} }
passwd, _ := obj.hash([]byte("1234")) passwd, _ := obj.hash([]byte("1234"))
plain, err := obj.Decrypt(data.EncryptedData, data.UserName, passwd) plain, err := obj.Decrypt(data.EncryptedData, data.UserName, passwd)
if err != nil { if err != nil {
fmt.Println(logprifix, "Decrypt Fail") t.Errorf("%s: Decrypt failed: %s", logPrefix, err)
} }
if string(plain) != "MyData" { if plain != "MyData" {
fmt.Println(logprifix, "Decrypted data Fail") t.Errorf("%s: Decrypt failed: %s", logPrefix, err)
} }
} }
func ExampleNew() { func TestNew(t *testing.T) {
storage := new(StubStorage) storage := new(StubStorage)
obj := New(storage) obj := New(storage)
jsonBytes := []byte(`{"UserName":"MyUser","Signature":"MEUCIDJmafX+XGJV+Ws2jz0lF2YdJLcrEXAw1ZBPB0/+KjJyAiEA1CR3f/pbngSl0P0mqb7McKSbveSsQ1ir5L4ulpKamuw=","EncryptedData":"F4Zw1vYy","Timestamp":"W5D07g==","PublicKey":"BCNhwc+1nmUYLSDJnacQaKQB1YyT26gdwHCZZd1iwsB14rfGvwv9fuAHjyln9Alap2Voxp/rrdiU2QvE8HuMt5s="}`) jsonBytes := []byte(`{"UserName":"MyUser","Signature":"MEUCIDJmafX+XGJV+Ws2jz0lF2YdJLcrEXAw1ZBPB0/+KjJyAiEA1CR3f/pbngSl0P0mqb7McKSbveSsQ1ir5L4ulpKamuw=","EncryptedData":"F4Zw1vYy","Timestamp":"W5D07g==","PublicKey":"BCNhwc+1nmUYLSDJnacQaKQB1YyT26gdwHCZZd1iwsB14rfGvwv9fuAHjyln9Alap2Voxp/rrdiU2QvE8HuMt5s="}`)
testJson(jsonBytes, "Hardcoded", obj) testJson(jsonBytes, "Hardcoded", obj, t)
jsonBytes, err := obj.GenerateJson("MyUser", "1234", "MyData") jsonBytes, err := obj.GenerateJson("MyUser", "1234", "MyData")
if err != nil { if err != nil {
panic(err) panic(err)
} }
testJson(jsonBytes, "Generated", obj) testJson(jsonBytes, "Generated", obj, t)
_, err = obj.GetJson(jsonBytes) _, err = obj.GetJson(jsonBytes)
if err == nil { if err == nil {
fmt.Println("Expecting error when no value stored") fmt.Println("Expecting error when no value stored")
@ -69,8 +69,8 @@ func ExampleNew() {
if err != nil { if err != nil {
fmt.Println("Get Json Fail") fmt.Println("Get Json Fail")
} }
testJson(jsonBytes, "Get", obj) testJson(jsonBytes, "Get", obj, t)
fmt.Println(true) fmt.Println(true)
//output: // output:
//true // true
} }