securejson

package module
v0.0.0-...-251c6c0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 21, 2018 License: MIT Imports: 10 Imported by: 0

README

securejson

A solution to secure the json content between BE and FE. The secure content only handled by FE, BE verify user's signature and store the encrypted secure content, but never know what is it.

Why to use this project:

  • Server never know the content of secure data, it's handled by client only.
  • Server never konw the user's password, it's handled by client only.

How does this project implemented:

  • FE implemented by js, BE implemented by go.
  • It's using AES-CTR to encrypt the secure data
  • It's using SHA3-256 (SHAKE) to hash the json content.
  • It's using ECDSA to signing the hash
  • It's using base64 to encode the data.

How to use in browser (javascript)

In HTML

In your html file, require.js is needed to be included. Below is an example to include the require.js from a CDN, and indicate the main file of javascript is "js/main.js".

<script data-main="js/main.js" src="https://cdn.bootcss.com/require.js/2.3.5/require.js"></script>
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. Below is an example of main.js

var secureJson;

require.config({
	baseUrl: 'js',
	paths: {
		securejson: '3rd/securejson',
		elliptic: "3rd/elliptic/elliptic.min",
		sha3: "3rd/sha3/sha3.min",
		aes: "3rd/aes/index.min",
		base64: "3rd/base64/base64js.min"
	},
});
require(['securejson'], function(sj){
	secureJson = sj;
});
var jsonString = secureJson.GenerateJson("My User Name", "My Password", "My sucure data");
console.log(jsonString);

And, for this example, the file structure shoud be like this:

js/
js/3rd/
js/3rd/aes/
js/3rd/aes/index.min.js
js/3rd/base64/
js/3rd/base64/base64js.min.js
js/3rd/elliptic/
js/3rd/elliptic/elliptic.min.js
js/3rd/sha3/
js/3rd/sha3/sha3.min.js
js/securejson.js
js/main.js
API for Front-end
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.
  • data: The plain data to be secured.

How to use in server (golang)

Implement Storage interface

This package does not implement the storage. The storage can be memory, file, database depend on your use cases. The storage interface is very simple, only 2 functions should be implemented:

  • Get() to get the value identified by key.
  • Put() to set the value identified by key. Below given a stub implementation of Storage interface
type StubStorage struct {
	jsonBytes []byte
}

func (obj *StubStorage) Put(key string, value []byte) error {
	obj.jsonBytes = value
	//fmt.Println("Put", string(obj.jsonBytes))
	return nil
}

func (obj *StubStorage) Get(key string) ([]byte, error) {
	if len(obj.jsonBytes) == 0 {
		return []byte{}, errors.New("Empty")
	}
	//fmt.Println("Get", string(obj.jsonBytes))
	return obj.jsonBytes, nil
}
Verify then store a json bytes
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)
if ok {
	obj.PutJson(jsonBytes)
}
Get json bytes from storage
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.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Json

type Json struct {
	UserName      string
	Signature     string
	EncryptedData string
	Timestamp     string
	PublicKey     string
}

type SecureJson

type SecureJson struct {
	// contains filtered or unexported fields
}

func New

func New(storageObj Storage) *SecureJson
Example
package main

import (
	"encoding/json"
	"errors"
	"fmt"
)

type StubStorage struct {
	jsonBytes []byte
}

func (obj *StubStorage) Put(key string, value []byte) error {
	obj.jsonBytes = value
	//fmt.Println("Put", string(obj.jsonBytes))
	return nil
}

func (obj *StubStorage) Get(key string) ([]byte, error) {
	if len(obj.jsonBytes) == 0 {
		return []byte{}, errors.New("Empty")
	}
	//fmt.Println("Get", string(obj.jsonBytes))
	return obj.jsonBytes, nil
}

func testJson(jsonBytes []byte, logprifix string, obj *SecureJson) {
	ok, err := obj.VerifyJson(jsonBytes)
	if err != nil || !ok {
		fmt.Println(err)
		fmt.Println(logprifix, "Verify the Json Fail")
	}
	var data Json
	err = json.Unmarshal(jsonBytes, &data)
	if err != nil {
		fmt.Println(logprifix, "Json Unmarshal Fail")
	}
	passwd, _ := obj.hash([]byte("1234"))
	plain, err := obj.Decrypt(data.EncryptedData, data.UserName, passwd)
	if err != nil {
		fmt.Println(logprifix, "Decrypt Fail")
	}
	if string(plain) != "MyData" {
		fmt.Println(logprifix, "Decrypted data Fail")
	}
}

func main() {
	storage := new(StubStorage)
	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)

	jsonBytes, err := obj.GenerateJson("MyUser", "1234", "MyData")
	if err != nil {
		panic(err)
	}
	testJson(jsonBytes, "Generated", obj)

	_, err = obj.GetJson(jsonBytes)
	if err == nil {
		fmt.Println("Expecting error when no value stored")
	}
	err = obj.PutJson(jsonBytes)
	if err != nil {
		fmt.Println("Put Json fail")
	}
	_, err = obj.GetJson(jsonBytes)
	if err != nil {
		fmt.Println("Get Json Fail")
	}
	testJson(jsonBytes, "Get", obj)
	fmt.Println(true)
}
Output:

true

func (*SecureJson) Decrypt

func (obj *SecureJson) Decrypt(data string, userName string, key []byte) (string, error)

func (*SecureJson) Encrypt

func (obj *SecureJson) Encrypt(data string, userName string, key []byte) (string, error)

func (*SecureJson) GenerateJson

func (obj *SecureJson) GenerateJson(user string, passwd string, data string) (outputJson []byte, err error)

func (*SecureJson) GetJson

func (obj *SecureJson) GetJson(inputJson []byte) (outputJson []byte, err error)

func (*SecureJson) PutJson

func (obj *SecureJson) PutJson(inputJson []byte) (err error)

func (*SecureJson) VerifyJson

func (obj *SecureJson) VerifyJson(jsonBytes []byte) (ok bool, err error)

type Storage

type Storage interface {
	Put(key string, value []byte) error
	Get(key string) ([]byte, error)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL