Adjust naming schemes to conform to standard, improve testing

master
kayos@tcp.direct 3 months ago
parent a381f5b298
commit 7aebb03b6c
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
  1. 18
      README.md
  2. 54
      compute.go
  3. 144
      js/securejson.js
  4. 57
      securejson.go
  5. 46
      securejson_test.go

@ -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.

@ -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", &timestamp)
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)
}

@ -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;

@ -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
}

@ -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)
}

Loading…
Cancel
Save