1.2.11 • Published 6 years ago

sp8de.crypto v1.2.11

Weekly downloads
5
License
ISC
Repository
github
Last release
6 years ago

Sp8de crypto SDK

SDK for client and server

Install

NPM

npm install sp8de-client-sdk

For use NPM-package in applications, you need to add references to cryptographic libraries to the index.html file:

<script src="https://www.mobilefish.com/scripts/ethereumjs/ethereumjs-util.js"></script>
<script src="https://cdn.ethers.io/scripts/ethers-v3.min.js"></script>

Browser

Run creating js-bundle

npm run tocdnmin

Then include sp8deSDK.js in the HTML pages.

<script src="sp8deSDK.js"></script>

NPM commands

doc: Run generate documentation from jsdoc

test: Run karma test

dev: Run watching ts-generator and karma tests

tocdnmin: Create single file with browserify and minification

Usage

NPM

import {Sp8deClientSDK} from 'sp8de-client-sdk';
// or
const Sp8deClientSDK = require('sp8de-client-sdk');

const sp8deClientSDK = new Sp8deClientSDK.Methods();

const seed = sp8deClientSDK.generateSeed();
// returns seed

Browser

const seed = sp8deClientSDK.generateSeed();
// returns seed

Store wallets in localstorage

Methods for storing wallet in the storage use the choice between wallets and user keys in localstorage (for situations where the user-object in the application). If in localstorage has a user key, then wallet will be added to him in key wallets.

About

The SDK contains functions that allow you to perform signature signing operations, verify signatures of other services. Also contains methods for adding created wallets to localstorage.

Examples

Wallet procedures

Save on init

public init() {
    // Check wallets in storage
    if (this.sp8deClientSDK.isWalletsInStorage()) {
      // Get wallet and decript him
      from(this.sp8deClientSDK.decryptWallet(this.sp8deClientSDK.getActiveWalletFromStorage(), this.password))
        .pipe(
          map(item => <any>item)
        )
        .subscribe(wallet => {
          // Save private key
          this.privateKey = wallet.privateKey;
          // Generate public key
          this.pubKey = this.sp8deClientSDK.getPubKey(this.privateKey);
        });
    } else {
      // Generate wallet containing private key.
      let wallet;
      this.privateKey = wallet.privateKey;
          // Generate public key from private key
          this.pubKey = this.sp8deClientSDK.getPubKey(this.privateKey);
          // Encrypting the wallet before uploading it to the storage for data security.
          from(this.sp8deClientSDK.encryptWallet(this.sp8deClientSDK.generateWallet(), password))
            .pipe(
              map(item => <any>item)
            )
            .subscribe(res => {
              // Save encrypted wallet to localstorage
              this.sp8deClientSDK.addWalletToStorage(res);
            });
    }
  }

Open for use

    // Getting wallet from storage
    let storageWallet = this.sp8deClientSDK.getActiveWalletFromStorage();
    // Decrypt wallet for edxecute private key
    this.sp8deClientSDK.decryptWallet(storageWallet, password).then(decryptRes => {
        // Getting private key
        this.privateKey = decryptRes.privateKey
    })

Signing

    // set current date in milliseconds as nonce
    const nonce = +(new Date());
    // generate seed
    const seed = this.sp8deClientSDK.generateSeed();
    // signing message
    const sign = this.sp8deClientSDK.signMessage({privateKey: this.privateKey, seed: seed, nonce: nonce});

Validate

Validating random number from array-seed

  public validateWin(array: number[], serverNumber: number[]): boolean {
    // generate random number from array
    const clientNumber = this.getRandomFromArray({array: array, min: 1, max: 6, length: winNumber.length});
    if (!clientNumber) {
      console.error('Server value invalid!');
      return;
    }
    return clientNumber[0] === serverNumber[0];
  }

API

generatePrivateKey() ⇒ number

Returns a new private key

Returns: number - A public key of 66 characters long

generateWallet() ⇒ object

Returns a new wallet

Returns: object - Object contains wallet

encryptWallet(wallet, password) ⇒ promise

Returns a new wallet

Returns: promise - promise with json

ParamTypeDescription
walletobjectobject with wallet
passwordstringpassword

decryptWallet(wallet, password) ⇒ promise

Returns a new wallet

Returns: promise - promise with json

ParamTypeDescription
walletstringEncrypted JSON with wallet
passwordstringpassword

getPubKey(privateKey) ⇒ string

Returns the public key obtains from the private key

Returns: string - A public key of 42 characters long

ParamTypeDescription
privateKeystringprivate key

generateArraySeed(signs) ⇒ Array.<number>

Returns an seed-array (use keccak-384 algorithm)

Returns: Array.<number> - An array containing random numbers

ParamTypeDescription
signsArray.<string>array of signs

getHash(string) ⇒ ArrayBuffer

Returns an hash from string

Returns: ArrayBuffer - An ArrayBuffer contains hash

ParamType
stringstring

generateArrayFromHash(hash) ⇒ Array.<number>

Returns an array of Uint32 numbers from hash

Returns: Array.<number> - array of of Uint32 numbers

ParamType
hashArrayBuffer

getRandomFromArray(parameters) ⇒ Array.<number>

Returns an array of random numbers from seed-array (use mt19937 algorithm)

Returns: Array.<number> - An array of length given by a "count" containing random numbers

ParamTypeDescription
parametersObject{array: [], min: number, max: number, count: number}

generateSeed() ⇒ number

Returns a random number to use as a seed

Returns: number - Random seed number. Length 9-10

signMessage(parameters) ⇒ string

Signs a message from privateKey, seed, nonce. Returns message signed with private key.

Returns: string - Message signed with private key

ParamTypeDescription
parametersObject{privateKey: string, seed: number, nonce: number}

validateSign(parameters) ⇒ boolean

Validates the message. Use sign, nonce, public key and seed. Returns true if the validation was successful.

Returns: boolean - True if successful, false if unsuccessful

ParamTypeDescription
parametersObject{sign: string, pubKey: string, seed: number, nonce: number}

addWalletToStorage(value, storageWallets)

Add to localstorage to key Wallets in key "User" or root. If user without field "Wallets" add it.

ParamTypeDescription
valuestringPrivate key
storageWalletsobject | arrayoptional. Object wallet contained in storage

removeLastWalletFromStorage(storageWallets)

Removing last private key from array in localstorage

ParamTypeDescription
storageWalletsobject | arrayoptional. Object wallet contained in storage

clearWalletStorage(storageWallets)

Clear array of private keys (delete key from localstorage

ParamTypeDescription
storageWalletsobject | arrayObject wallet contained in storage)

getActiveWalletFromStorage(Wallets) ⇒ string

Returns active private key in localstorage

Returns: string - Active private key or null if no array

ParamTypeDescription
Walletsarrayoptional. Array wallets contained in storage

getWalletsListFromStorage(storageWallets) ⇒ Array.<string>

Returns array of string contains all private keys from localstorage

Returns: Array.<string> - Array of private keys or null if no array

ParamTypeDescription
storageWalletsobject | arrayoptional. Object wallet contained in storage

isWalletsInStorage(storageWallets) ⇒ boolean

Check if there are keys in vault

Returns: boolean - True if there is, false is not

ParamTypeDescription
storageWalletsobjectoptional. User in storage, if it there is

Get started

Intro

Next, we show how you can create a minimal-functional game "Dices" on Angular2, in which the library sp8de-client-sdk will be used to ensure the reliability of gaming operations.

Installing

For use sp8de-client-sdk functions it is necessary install him from NPM:

npm install sp8de-client-sdk

And for Angular2 + applications, you need to add references to cryptographic libraries to the index.html file:

<script src="https://www.mobilefish.com/scripts/ethereumjs/ethereumjs-util.js"></script>
<script src="https://cdn.ethers.io/scripts/ethers-v3.min.js"></script>

In module.ts need to import module sp8de-client-sdk and add to the array providers:

import {Sp8deClientSDK} from 'sp8de-client-sdk';

@NgModule({
...
  providers: [Sp8deClientSDK]
...
})

Create services

Crypto service

Create a service containing a cryptographic functions.

ng g s crypto

In the service import sp8de-client-sdk and declare it in the constructor.

import {Sp8deClientSDK} from 'sp8de-client-sdk';
...
constructor(public sp8deClientSDK: Sp8deClientSDK) {
  }

Implements methods of the game.

Init

Method creates a private key, if it is not in storage and generates a public key for further work:

public init() {
    // Check wallets in storage
    if (this.sp8deClientSDK.isWalletsInStorage()) {
      // Get wallet and decript him
      from(this.sp8deClientSDK.decryptWallet(this.sp8deClientSDK.getActiveWalletFromStorage(), this.password))
        .pipe(
          map(item => <any>item)
        )
        .subscribe(wallet => {
          // Save private key
          this.privateKey = wallet.privateKey;
          // Generate public key
          this.pubKey = this.sp8deClientSDK.getPubKey(this.privateKey);
        });
    } else {
      // Generate wallet containing private key.
      let wallet;
      this.privateKey = wallet.privateKey;
          // Generate public key from private key
          this.pubKey = this.sp8deClientSDK.getPubKey(this.privateKey);
          // Encrypting the wallet before uploading it to the storage for data security.
          from(this.sp8deClientSDK.encryptWallet(this.sp8deClientSDK.generateWallet(), password))
            .pipe(
              map(item => <any>item)
            )
            .subscribe(res => {
              // Save encrypted wallet to localstorage
              this.sp8deClientSDK.addWalletToStorage(res);
            });
    }
  }

Generate crypto-parameters

Return values, required for the request to start game:

public generateCryptoParameters(): any {
    //  Create object
    //  Wtite current date to nonce, current public key to pubKey
    //  and generate seed
    const resultParameters = {
        nonce: +(new Date()),
        seed: this.sp8deClientSDK.generateSeed(),
        sign: '',
        pubKey: this.pubKey
      },
      signParameters = {
        privateKey: this.privateKey,
        seed: resultParameters.seed,
        nonce: resultParameters.nonce
      };
    // Signing message
    resultParameters.sign = this.sp8deClientSDK.signMessage(signParameters);
    return resultParameters;
  }

Getting random from array

Check the random value returned from server at the end of game. Accept servers array and parameters of game:

public getRandomFromArray(parameters: { array: any[]; min: number, max: number, length: number }): number[] {
    return this.sp8deClientSDK.getRandomFromArray(parameters);
}

Validate win

Uses the previous method to validate server values. Accepted server array and random number.

public validateWin(array: number[], serverNumber: number[]): boolean {
    const clientNumber = this.getRandomFromArray({array: array, min: 1, max: 6, length: serverNumber.length});
    if (!clientNumber) {
      console.error('Server value invalid!');
      return;
    }
    return clientNumber[0] === serverNumber[0];
  }

Validate players

Validate correctness of the information transmitted by the server about other players.

public validatePlayers(response: GameFinishResponse): boolean[] {
    const result: boolean[] = [];
    for (const item of response.items) {
      result.push(this.sp8deClientSDK.validateSign({
          sign: item.sign,
          pubKey: item.pubKey,
          seed: item.seed,
          nonce: item.nonce
        }
      ));
    }
    return result;
  }

Game service

We will create a service containing functions that work with the api and control the beginning and end of the game.

ng g s game

Implements methods for work the game.

Start game

Through api sends a request with parameters of start the game.

public startGame(parameters: GameStartRequest): Observable<GameStartResponse> {
    return this.api.apiDemoGameStartPost(parameters)
      .pipe(
        map(
          item => {
            return <GameFinishResponse>item;
          }));
  }

To request parameters, use the following interface:

export interface GameStartRequest {
    type?: GameStartRequest.TypeEnum;
    bet?: Array<number>;
    betAmount?: number;
    pubKey?: string;
    sign?: string;
    nonce?: number;
}

End game

Through api sends a request with parameters of start the game.

  public endGame(parameters: GameFinishRequest): Observable<GameFinishResponse> {
    return this.api.apiDemoGameEndPost(parameters).pipe(
      map(
        item => {
          return <GameFinishResponse>item;
        }));
  }

To request parameters, use the following interface:

export interface GameFinishRequest {
    gameId?: string;
    pubKey?: string;
    sign?: string;
    seed?: number;
    nonce?: number;
}

Create game component

Let's create the logic of the component. Set user parameters on initialize the component and write logic of game.

On init

On initialisation create public and private key for the user.

ngOnInit() {
    this.cryptoService.init();
}

Start game

The logic of the game is as follows: 1. In the event parameter, values relating to the game conditions are passed. This is the type of the game, the selected dices values and the bet. 2. In the method create parameters, necessary for cryptographic operations. This is a public key, a signed message and a nonce. 3. These parameters are collected together and sent to the server as a request to start games. The server returns an object in which the following fields are required for the game: gameId — game identification items — array with the data of other players 4. Send to the server request to the end of game with the previously obtained cryptographic parameters and gameId. 5. Server should send a response, that contains the following information: isWinner — did the player win winNumbers — dropped dices winAmount — amount of winnings items — array with data from other players * sharedSeedArray — seed-array from which a random value of the dropped dice is generated. The last two values can be validated on the client. 6. We'll find out whether the data is correct by running the sp8de-client-sdk library to validate data about other players and the dropped value

Below is the code of the method that implements this logic, using previously created services:

public start(event): void {
    const cryptoParameters = this.cryptoService.generateCryptoParameters();
    this.gameService.startGame({
        type: event.type,
        bet: event.currentBet,
        betAmount: event.currentBetAmount,
        pubKey: cryptoParameters.pubKey,
        sign: cryptoParameters.sign,
        nonce: cryptoParameters.nonce
      }).pipe(
      switchMap(startResponse => {
        return this.gameService.endGame({
          gameId: startResponse.gameId,
          sign: cryptoParameters.sign,
          seed: cryptoParameters.seed,
          nonce: cryptoParameters.nonce,
          pubKey: cryptoParameters.pubKey
        });
      })).subscribe(res => {
        const validWin = this.cryptoService.validateWin(res.sharedSeedArray, res.winNumbers),
          validItems = this.cryptoService.validatePlayers(res),
          win = this.checkWin(res.winNumbers, event.currentBet);
        console.log('Validate items: ', validItems);
        console.log('Validate win: ', validWin);
        console.log(win ? `You win ${res.winAmount}` : 'You lose');
      },
      error => {
        console.error(error.message);
      });
  }

Now you can call method start(event) with game parameters and get to the console result:

js:
start({
    type: 'Dice',
    bet: [1, 2],
    betAmount: 100
})

console:
Validate items: true
Validate win: [true, true, true]
You win 50
1.2.11

6 years ago

1.2.10

6 years ago

1.2.9

6 years ago

1.2.8

6 years ago

1.2.7

6 years ago

1.2.6

6 years ago

1.2.5

6 years ago

1.2.4

6 years ago

1.2.3

6 years ago

1.2.2

6 years ago

1.2.1

6 years ago

1.2.0

6 years ago

1.1.29

6 years ago

1.1.28

6 years ago

1.1.27

6 years ago

1.1.26

6 years ago

1.1.25

6 years ago

1.1.24

6 years ago

1.1.23

6 years ago

1.1.22

6 years ago

1.1.21

6 years ago

1.1.20

6 years ago

1.1.19

6 years ago

1.1.18

6 years ago

1.1.17

6 years ago

1.1.16

6 years ago

1.1.15

6 years ago

1.1.14

6 years ago

1.1.13

6 years ago

1.1.12

6 years ago

1.1.11

6 years ago

1.1.10

6 years ago

1.1.9

6 years ago

1.0.9

6 years ago

1.0.8

6 years ago

1.0.7

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago