From 7aebb03b6cf560e1860c66a6bffd2d18927779c0 Mon Sep 17 00:00:00 2001 From: "kayos@tcp.direct" Date: Sat, 9 Jul 2022 10:49:04 -0700 Subject: [PATCH] Adjust naming schemes to conform to standard, improve testing --- README.md | 18 +++--- compute.go | 54 ++++++++--------- js/securejson.js | 144 ++++++++++++++++++++++----------------------- securejson.go | 57 ++++++++++-------- securejson_test.go | 46 ++++++++------- 5 files changed, 164 insertions(+), 155 deletions(-) diff --git a/README.md b/README.md index 6466296..2805770 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,10 @@ Below is an example to include the require.js from a CDN, and indicate the main ### In js In your main file of javascript, the path of dependency libs should be defined in order to let require.js find the dependency. Then, a object of securejson should be created, using require() function provided by require.js. -Then, call the function "GenerateJson" to generate a secured json string. +Then, call the function "GenerateJSON" to generate a secured json string. Below is an example of main.js ```javascript -var secureJson; +var secureJSON; require.config({ baseUrl: 'js', @@ -40,9 +40,9 @@ require.config({ }, }); require(['securejson'], function(sj){ - secureJson = sj; + secureJSON = sj; }); -var jsonString = secureJson.GenerateJson("My User Name", "My Password", "My sucure data"); +var jsonString = secureJSON.GenerateJSON("My User Name", "My Password", "My sucure data"); console.log(jsonString); ``` @@ -64,7 +64,7 @@ js/main.js ### API for Front-end ``` -GenerateJson(userName, passwd, data) +GenerateJSON(userName, passwd, data) ``` - userName: The user name to identify the owner of the data. - passwd: User password. It's used to generate the private key used for signing the json, and also used to encrypt the plain data. @@ -104,14 +104,14 @@ func (obj *StubStorage) Get(key string) ([]byte, error) { jsonBytes := []byte(`{"UserName":"MyUser","Signature":"MEUCIDJmafX+XGJV+Ws2jz0lF2YdJLcrEXAw1ZBPB0/+KjJyAiEA1CR3f/pbngSl0P0mqb7McKSbveSsQ1ir5L4ulpKamuw=","EncryptedData":"F4Zw1vYy","Timestamp":"W5D07g==","PublicKey":"BCNhwc+1nmUYLSDJnacQaKQB1YyT26gdwHCZZd1iwsB14rfGvwv9fuAHjyln9Alap2Voxp/rrdiU2QvE8HuMt5s="}`) storage := new(StubStorage) obj := securejson.New(storage) -ok, err := obj.VerifyJson(jsonBytes) +ok, err := obj.VerifyJSON(jsonBytes) if ok { - obj.PutJson(jsonBytes) + obj.PutJSON(jsonBytes) } ``` ### Get json bytes from storage ```golang -outJsonBytes, err := obj.GetJson(jsonBytes) +outJSONBytes, err := obj.GetJSON(jsonBytes) ``` -- GetJson need to input a jsonBytes generated by GenerateJson() function of both FE and BE. It's used to verify the data requester is a valid owner of the specific secure data. +- GetJSON need to input a jsonBytes generated by GenerateJSON() function of both FE and BE. It's used to verify the data requester is a valid owner of the specific secure data. diff --git a/compute.go b/compute.go index 3007023..ba15283 100644 --- a/compute.go +++ b/compute.go @@ -16,7 +16,7 @@ import ( "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) { if len(iv) < aes.BlockSize { return []byte{}, errors.New("iv size error") } @@ -33,7 +33,7 @@ func (obj *SecureJson) encrypt(plainText []byte, iv []byte, key []byte) ([]byte, return cipherText, err } -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) dataHash, _ := obj.hash(encryptedBytes) timeHash, _ := obj.hash(timeBytes) @@ -48,15 +48,15 @@ func (obj *SecureJson) genHash(userBytes []byte, encryptedBytes []byte, timeByte return } -func (obj *SecureJson) checkInputOutputJson(inputJson []byte, outputJson []byte) (ok bool, err error) { +func (obj *SecureJSON) checkInputOutputJSON(inputJSON []byte, outputJSON []byte) (ok bool, err error) { ok = false - var ji Json - err = json.Unmarshal(inputJson, &ji) + var ji JSON + err = json.Unmarshal(inputJSON, &ji) if err != nil { return } - var jo Json - err = json.Unmarshal(outputJson, &jo) + var jo JSON + err = json.Unmarshal(outputJSON, &jo) if err != nil { return } @@ -77,48 +77,48 @@ func (obj *SecureJson) checkInputOutputJson(inputJson []byte, outputJson []byte) return } -func (obj *SecureJson) getUserNameFromJson(inputJson []byte) (userName string, err error) { - var jsonStruct Json +func (obj *SecureJSON) getUserNameFromJSON(inputJSON []byte) (userName string, err error) { + var jsonStruct JSON userName = "" - err = json.Unmarshal(inputJson, &jsonStruct) + err = json.Unmarshal(inputJSON, &jsonStruct) if err == nil { userName = jsonStruct.UserName } return } -func (obj *SecureJson) getJsonFromStorage(inputJson []byte) (outputJson []byte, err error) { - userName, err := obj.getUserNameFromJson(inputJson) +func (obj *SecureJSON) getJSONFromStorage(inputJSON []byte) (outputJSON []byte, err error) { + userName, err := obj.getUserNameFromJSON(inputJSON) if err == nil { - outputJson, err = obj.storageStrategy.Get(userName) + outputJSON, err = obj.storageStrategy.Get(userName) } return } -func (obj *SecureJson) putJsonToStorage(inputJson []byte) (err error) { - userName, err := obj.getUserNameFromJson(inputJson) +func (obj *SecureJSON) putJSONToStorage(inputJSON []byte) (err error) { + userName, err := obj.getUserNameFromJSON(inputJSON) if err == nil { - err = obj.storageStrategy.Put(userName, inputJson) + err = obj.storageStrategy.Put(userName, inputJSON) } return } -func (obj *SecureJson) convertFromStringToInt64(timeStr string) (timestamp int64) { +func (obj *SecureJSON) convertFromStringToInt64(timeStr string) (timestamp int64) { _, _ = fmt.Sscanf(timeStr, "%x", ×tamp) return } -func (obj *SecureJson) checkTimestampBeforeNow(timeStr string) (ok bool) { +func (obj *SecureJSON) checkTimestampBeforeNow(timeStr string) (ok bool) { timestamp := obj.convertFromStringToInt64(timeStr) timenow := time.Now().UnixNano() return timenow > timestamp } -func (obj *SecureJson) bytesToString(msg []byte) string { +func (obj *SecureJSON) bytesToString(msg []byte) string { return base64.StdEncoding.EncodeToString(msg) } -func (obj *SecureJson) stringToBytes(msg string) (res []byte) { +func (obj *SecureJSON) stringToBytes(msg string) (res []byte) { var err error res, err = base64.StdEncoding.DecodeString(msg) if err != nil { @@ -127,7 +127,7 @@ func (obj *SecureJson) stringToBytes(msg string) (res []byte) { return } -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) if err != nil { return false @@ -139,7 +139,7 @@ func (obj *SecureJson) verify(msg []byte, pub []byte, sig []byte) bool { return signature.Verify(msg, pubKey) } -func (obj *SecureJson) sign(msg []byte, privKey []byte) ([]byte, error) { +func (obj *SecureJSON) sign(msg []byte, privKey []byte) ([]byte, error) { priv, _ := btcec.PrivKeyFromBytes(privKey) sig, err := priv.ToECDSA().Sign(entropy.GetOptimizedRand(), msg, nil) if err != nil { @@ -148,21 +148,21 @@ func (obj *SecureJson) sign(msg []byte, privKey []byte) ([]byte, error) { return sig, err } -func (obj *SecureJson) getPubKey(privKey []byte) ([]byte, error) { +func (obj *SecureJSON) getPubKey(privKey []byte) ([]byte, error) { pubKey := make([]byte, 65) _, pub := btcec.PrivKeyFromBytes(privKey) pubKey = pub.SerializeUncompressed() return pubKey, nil } -func (obj *SecureJson) getTimestamp() ([]byte, error) { +func (obj *SecureJSON) getTimestamp() ([]byte, error) { timeNowBytes := make([]byte, 8) timeNowStr := fmt.Sprintf("%x", time.Now().Unix()) timeNowBytes, err := hex.DecodeString(timeNowStr) return timeNowBytes, err } -func (obj *SecureJson) shake256(data []byte, length int) ([]byte, error) { +func (obj *SecureJSON) shake256(data []byte, length int) ([]byte, error) { sum := make([]byte, length) hashObj := sha3.NewShake256() _, writeErr := hashObj.Write(data) @@ -173,10 +173,10 @@ func (obj *SecureJson) shake256(data []byte, length int) ([]byte, error) { return sum, readErr } -func (obj *SecureJson) hash(data []byte) ([]byte, error) { +func (obj *SecureJSON) hash(data []byte) ([]byte, error) { 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) } diff --git a/js/securejson.js b/js/securejson.js index 3c0ff00..ffb9e88 100644 --- a/js/securejson.js +++ b/js/securejson.js @@ -1,63 +1,63 @@ -/* -var EC = require('elliptic/elliptic.min').ec; +/* +var EC = require('elliptic/elliptic.min').ec; var SHA3 = require('sha3/sha3.min'); var AES = require('aes/index.min'); var BASE64 = require('base64/base64js.min'); - -var jsonStr = GenerateJson("MyUser", "1234", "MyData"); -console.log(jsonStr); -*/ -var EC; -var SHA3; -var AES; -var BASE64; - -define(['elliptic','sha3','aes','base64'], function(elliptic, sha3, aes, base64){ - EC = elliptic.ec; - SHA3 = sha3; - AES = aes; - BASE64 = base64; - var GenerateJson = function(user, passwd, data) { - return generateJson(user, passwd, data); - }; - var Decrypt = function(user, passwd, data) { - var ec = new EC('secp256k1'); - - var iv = SHA3.shake256(user, 128); - var prikeyHex = SHA3.shake256(passwd, 256); - - var decryptedBytes = encrypt(base64ToBytes(data), hexToBytes(iv), hexToBytes(prikeyHex)); - return bytesToString(decryptedBytes); - }; - return { - "GenerateJson": GenerateJson, - "Decrypt": Decrypt - }; -}); - -function bytesToBase64(bytes) { + +var jsonStr = GenerateJSON("MyUser", "1234", "MyData"); +console.log(jsonStr); +*/ +var EC; +var SHA3; +var AES; +var BASE64; + +define(['elliptic','sha3','aes','base64'], function(elliptic, sha3, aes, base64){ + EC = elliptic.ec; + SHA3 = sha3; + AES = aes; + BASE64 = base64; + var GenerateJSON = function(user, passwd, data) { + return generateJSON(user, passwd, data); + }; + var Decrypt = function(user, passwd, data) { + var ec = new EC('secp256k1'); + + var iv = SHA3.shake256(user, 128); + var prikeyHex = SHA3.shake256(passwd, 256); + + var decryptedBytes = encrypt(base64ToBytes(data), hexToBytes(iv), hexToBytes(prikeyHex)); + return bytesToString(decryptedBytes); + }; + return { + "GenerateJSON": GenerateJSON, + "Decrypt": Decrypt + }; +}); + +function bytesToBase64(bytes) { return BASE64.fromByteArray(bytes); } - + function base64ToBytes(str) { return BASE64.toByteArray(str); } - -function base64ToHex(str) { - return bytesToHex(base64ToBytes(str)); -} - -function hexToBase64(hex) { - return bytesToBase64(hexToBytes(hex)); -} - -function encrypt(dataBytes, ivBytes, keyBytes) { + +function base64ToHex(str) { + return bytesToHex(base64ToBytes(str)); +} + +function hexToBase64(hex) { + return bytesToBase64(hexToBytes(hex)); +} + +function encrypt(dataBytes, ivBytes, keyBytes) { var aesCtr = new AES.ModeOfOperation.ctr(keyBytes, ivBytes); var encryptedBytes = aesCtr.encrypt(dataBytes); return encryptedBytes; -} - -function generateJson(user, passwd, data) { +} + +function generateJSON(user, passwd, data) { var ec = new EC('secp256k1'); var prikeyHex = SHA3.shake256(passwd, 256); @@ -68,48 +68,48 @@ function generateJson(user, passwd, data) { var iv = SHA3.shake256(user, 128); var encryptedDataBytes = encrypt(stringToBytes(data), hexToBytes(iv), hexToBytes(prikeyHex)); var encryptedDataHex = bytesToHex(encryptedDataBytes); - + var timestampHex = bytesToHex(intToBytes(getTimestamp())); var userHex = bytesToHex(stringToBytes(user)); - + var fullHash = genHash(userHex, encryptedDataHex, timestampHex, pubkeyHex); var sigHex = bytesToHex(prikey.sign(fullHash).toDER()); - var obj = { + var obj = { UserName : user, Signature : hexToBase64(sigHex), EncryptedData : hexToBase64(encryptedDataHex), Timestamp : hexToBase64(timestampHex), PublicKey : hexToBase64(pubkeyHex) - }; - + }; + jsonStr = JSON.stringify(obj); return jsonStr; } - -function getPriKey(prikeyHex) { + +function getPriKey(prikeyHex) { var ec = new EC('secp256k1'); return } -function getPubKey(prikeyHex) { +function getPubKey(prikeyHex) { var pubhex = keys.getPublic(false, 'hex'); pubkey = ec.keyFromPublic(pubhex, 'hex'); return pubkey; -} +} -function getTimestamp() { +function getTimestamp() { return Math.round((new Date()).getTime() / 1000); -} - +} + function intToBytes(numb) { - var bytesLen = 4; + var bytesLen = 4; var bytes = new Array(bytesLen-1); - for(var i=bytesLen; i>0; i--) { + for(var i=bytesLen; i>0; i--) { bytes[i-1] = numb & 0xff; numb = numb>>8; } - return bytes; -} + return bytes; +} function genHash(userHex, dataHex, timeHex, pubkeyHex) { var userHash = SHA3.shake256.array(hexToBytes(userHex), 256); @@ -121,14 +121,14 @@ function genHash(userHex, dataHex, timeHex, pubkeyHex) { var fullHash = SHA3.shake256.array(full, 256); return fullHash } - -function bytesToString(bytes) { + +function bytesToString(bytes) { return AES.utils.utf8.fromBytes(bytes); -} - -function stringToBytes(str) { - return AES.utils.utf8.toBytes(str); -} +} + +function stringToBytes(str) { + return AES.utils.utf8.toBytes(str); +} function hexToBytes(hex) { var len = hex.length; diff --git a/securejson.go b/securejson.go index f8dcf23..3dd165d 100644 --- a/securejson.go +++ b/securejson.go @@ -3,6 +3,7 @@ package securejson import ( "encoding/json" "errors" + "fmt" ) type Storage interface { @@ -10,33 +11,33 @@ type Storage interface { Get(key string) ([]byte, error) } -type SecureJson struct { +type SecureJSON struct { storageStrategy Storage } -type Json struct { +type JSON struct { UserName string Signature string EncryptedData string Timestamp string PublicKey string - //TODO: NewPublicKey string + // TODO: NewPublicKey string } -func (obj *SecureJson) Encrypt(data string, userName string, key []byte) (string, error) { +func (obj *SecureJSON) Encrypt(data string, userName string, key []byte) (string, error) { iv, _ := obj.genIv(userName) cipherBytes, err := obj.encrypt([]byte(data), iv, key) return obj.bytesToString(cipherBytes), err } -func (obj *SecureJson) Decrypt(data string, userName string, key []byte) (string, error) { +func (obj *SecureJSON) Decrypt(data string, userName string, key []byte) (string, error) { iv, _ := obj.hash([]byte(userName)) cipherBytes := obj.stringToBytes(data) plainBytes, err := obj.encrypt(cipherBytes, iv, key) return string(plainBytes), err } -func (obj *SecureJson) GenerateJson(user string, passwd string, data string) (outputJson []byte, err error) { +func (obj *SecureJSON) GenerateJSON(user string, passwd string, data string) (outputJSON []byte, err error) { privKey, _ := obj.hash([]byte(passwd)) iv, _ := obj.hash([]byte(user)) @@ -48,26 +49,30 @@ func (obj *SecureJson) GenerateJson(user string, passwd string, data string) (ou fullHash := obj.genHash(userBytes, encryptedBytes, timeBytes, pubkeyBytes) sigBytes, _ := obj.sign(fullHash, privKey) - var jsonMap Json + var jsonMap JSON jsonMap.UserName = user jsonMap.Signature = obj.bytesToString(sigBytes) jsonMap.EncryptedData = obj.bytesToString(encryptedBytes) jsonMap.Timestamp = obj.bytesToString(timeBytes) jsonMap.PublicKey = obj.bytesToString(pubkeyBytes) - outputJson, err = json.Marshal(jsonMap) + outputJSON, err = json.Marshal(jsonMap) return } -func (obj *SecureJson) VerifyJson(jsonBytes []byte) (ok bool, err error) { - var jsonMap Json +func (obj *SecureJSON) VerifyJSON(jsonBytes []byte) (ok bool, err error) { + var jsonMap JSON err = json.Unmarshal(jsonBytes, &jsonMap) if err != nil { - return false, err + return false, fmt.Errorf("json.Unmarshal failure during verification: %x", err) + } + if jsonMap.UserName == "" || jsonMap.Signature == "" || + jsonMap.EncryptedData == "" || jsonMap.Timestamp == "" || jsonMap.PublicKey == "" { + return false, errors.New("json.Unmarshal failure during verification: missing fields") } if !obj.checkTimestampBeforeNow(jsonMap.Timestamp) { - err = errors.New("Timestamp check fail") + err = errors.New("timestamp check failed") return false, err } @@ -82,47 +87,47 @@ func (obj *SecureJson) VerifyJson(jsonBytes []byte) (ok bool, err error) { if ok { return } else { - err = errors.New("Signature verify fail") + err = errors.New("signature verify failed") return false, err } } -func (obj *SecureJson) PutJson(inputJson []byte) (err error) { +func (obj *SecureJSON) PutJSON(inputJSON []byte) (err error) { var ok bool - if ok, err = obj.VerifyJson(inputJson); !ok || err != nil { + if ok, err = obj.VerifyJSON(inputJSON); !ok || err != nil { return } - outputJson, err := obj.getJsonFromStorage(inputJson) + outputJSON, err := obj.getJSONFromStorage(inputJSON) if err != nil { - err = obj.putJsonToStorage(inputJson) + err = obj.putJSONToStorage(inputJSON) return } - if ok, err = obj.checkInputOutputJson(inputJson, outputJson); err != nil || !ok { + if ok, err = obj.checkInputOutputJSON(inputJSON, outputJSON); err != nil || !ok { return } - err = obj.putJsonToStorage(inputJson) + err = obj.putJSONToStorage(inputJSON) return } -func (obj *SecureJson) GetJson(inputJson []byte) (outputJson []byte, err error) { +func (obj *SecureJSON) getJSON(inputJSON []byte) (outputJSON []byte, err error) { var ok bool - if ok, err = obj.VerifyJson(inputJson); !ok || err != nil { + if ok, err = obj.VerifyJSON(inputJSON); !ok || err != nil { return } - outputJson, err = obj.getJsonFromStorage(inputJson) + outputJSON, err = obj.getJSONFromStorage(inputJSON) if err != nil { return } - if ok, err = obj.checkInputOutputJson(inputJson, outputJson); err != nil || !ok { - outputJson = []byte{} + if ok, err = obj.checkInputOutputJSON(inputJSON, outputJSON); err != nil || !ok { + outputJSON = []byte{} return } return } -func New(storageObj Storage) *SecureJson { - obj := new(SecureJson) +func New(storageObj Storage) *SecureJSON { + obj := new(SecureJSON) obj.storageStrategy = storageObj return obj } diff --git a/securejson_test.go b/securejson_test.go index 208c372..f214833 100644 --- a/securejson_test.go +++ b/securejson_test.go @@ -3,34 +3,37 @@ package securejson import ( "encoding/json" "errors" - "fmt" "testing" ) type StubStorage struct { jsonBytes []byte + t *testing.T } func (obj *StubStorage) Put(key string, value []byte) error { + if value == nil || len(value) == 0 { + return errors.New("nil value") + } obj.jsonBytes = value - fmt.Println("Put", string(obj.jsonBytes)) + obj.t.Log("Put: ", string(obj.jsonBytes)) return nil } func (obj *StubStorage) Get(key string) ([]byte, error) { if len(obj.jsonBytes) == 0 { - return []byte{}, errors.New("Empty") + return []byte{}, errors.New("empty") } - fmt.Println("Get", string(obj.jsonBytes)) + obj.t.Log("Get: ", string(obj.jsonBytes)) return obj.jsonBytes, nil } -func testJson(jsonBytes []byte, logPrefix string, obj *SecureJson, t *testing.T) { - ok, err := obj.VerifyJson(jsonBytes) +func testJSON(t *testing.T, jsonBytes []byte, logPrefix string, obj *SecureJSON) { + ok, err := obj.VerifyJSON(jsonBytes) if err != nil || !ok { - t.Errorf("%s: VerifyJson failed: %s", logPrefix, err) + t.Errorf("%s: VerifyJSON failed: %s", logPrefix, err) } - var data Json + var data JSON err = json.Unmarshal(jsonBytes, &data) if err != nil { t.Errorf("%s: Unmarshal failed: %s", logPrefix, err) @@ -47,30 +50,31 @@ func testJson(jsonBytes []byte, logPrefix string, obj *SecureJson, t *testing.T) func TestNew(t *testing.T) { storage := new(StubStorage) + storage.t = t obj := New(storage) jsonBytes := []byte(`{"UserName":"MyUser","Signature":"MEUCIDJmafX+XGJV+Ws2jz0lF2YdJLcrEXAw1ZBPB0/+KjJyAiEA1CR3f/pbngSl0P0mqb7McKSbveSsQ1ir5L4ulpKamuw=","EncryptedData":"F4Zw1vYy","Timestamp":"W5D07g==","PublicKey":"BCNhwc+1nmUYLSDJnacQaKQB1YyT26gdwHCZZd1iwsB14rfGvwv9fuAHjyln9Alap2Voxp/rrdiU2QvE8HuMt5s="}`) - testJson(jsonBytes, "Hardcoded", obj, t) + testJSON(t, jsonBytes, "Hardcoded", obj) - jsonBytes, err := obj.GenerateJson("MyUser", "1234", "MyData") + jsonBytes, err := obj.GenerateJSON("MyUser", "1234", "MyData") if err != nil { panic(err) } - testJson(jsonBytes, "Generated", obj, t) + testJSON(t, jsonBytes, "Generated", obj) - _, err = obj.GetJson(jsonBytes) + t.Log("trying to get a value before it's stored...") + _, err = obj.getJSON(jsonBytes) if err == nil { - fmt.Println("Expecting error when no value stored") + t.Errorf("Expecting error when no value stored") } - err = obj.PutJson(jsonBytes) + t.Log("trying to store a value...") + err = obj.PutJSON(jsonBytes) if err != nil { - fmt.Println("Put Json fail") + t.Errorf("Put JSON failed: %s", err) } - _, err = obj.GetJson(jsonBytes) + t.Log("trying to get the stored value...") + _, err = obj.getJSON(jsonBytes) if err != nil { - fmt.Println("Get Json Fail") + t.Errorf("Get JSON failed: %x", err) } - testJson(jsonBytes, "Get", obj, t) - fmt.Println(true) - // output: - // true + testJSON(t, jsonBytes, "Get", obj) }