Skip to content
This repository has been archived by the owner on Nov 24, 2022. It is now read-only.

feat: encryption and decryption #313

Merged
merged 5 commits into from
Jan 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"reselect": "^4.0.0",
"resolve": "1.6.0",
"sass-resources-loader": "^2.0.0",
"scrypt-js": "^3.0.1",
"source-map-loader": "^0.2.1",
"styled-components": "^4.1.3",
"ts-jest": "22.0.1",
Expand Down
33 changes: 26 additions & 7 deletions src/state/PersistentStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { combineReducers, createStore, Store } from 'redux'
import nacl from 'tweetnacl'
import { u8aToHex } from '@kiltprotocol/sdk-js/build/crypto'
import {
encryption,
decryption,
passwordHashing,
} from '../utils/Encryption/Encryption'

import * as Attestations from './ducks/Attestations'
import * as Balances from './ducks/Balances'
Expand Down Expand Up @@ -50,10 +57,12 @@ class PersistentStore {
}

private static NAME = 'reduxState'
private static SALT = 'salt'

private static async deserialize(
obj: SerializedState
encryptedState: string
): Promise<Partial<State>> {
const obj = JSON.parse(encryptedState)
return {
attestations: Attestations.Store.deserialize(obj.attestations),
claims: Claims.Store.deserialize(obj.claims),
Expand Down Expand Up @@ -85,12 +94,21 @@ class PersistentStore {

public async init(): Promise<Store> {
const localState = localStorage.getItem(PersistentStore.NAME)
let salt = localStorage.getItem(PersistentStore.SALT)

if (!salt) {
salt = u8aToHex(nacl.randomBytes(24))
localStorage.setItem(PersistentStore.SALT, salt)
}

const password = await passwordHashing('password', salt)
let persistedState: Partial<State> = {}
if (localState) {
try {
persistedState = await PersistentStore.deserialize(
JSON.parse(localState)
)
const decryptedState = decryption(localState, password)
if (decryptedState) {
persistedState = await PersistentStore.deserialize(decryptedState)
}
} catch (error) {
console.error('Could not construct persistentStore', error)
}
Expand All @@ -117,10 +135,11 @@ class PersistentStore {
)

this.storeInternal.subscribe(() => {
localStorage.setItem(
PersistentStore.NAME,
PersistentStore.serialize(this.storeInternal.getState())
const serializedState = PersistentStore.serialize(
this.storeInternal.getState()
)
const encryptedState = encryption(serializedState, password)
localStorage.setItem(PersistentStore.NAME, JSON.stringify(encryptedState))
})

return this.storeInternal
Expand Down
30 changes: 30 additions & 0 deletions src/utils/Encryption/Encryption.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
encryptSymmetricAsStr,
decryptSymmetricStr,
CryptoInput,
EncryptedSymmetricString,
coToUInt8,
} from '@kiltprotocol/sdk-js/build/crypto'
import { scrypt } from 'scrypt-js'

export function encryption(
message: string,
secret: CryptoInput
): EncryptedSymmetricString {
return encryptSymmetricAsStr(message, secret)
}

export function decryption(data: string, secret: CryptoInput): string | null {
return decryptSymmetricStr(JSON.parse(data), secret)
}
Dudleyneedham marked this conversation as resolved.
Show resolved Hide resolved

export function passwordHashing(
password: string,
salt: string
): Promise<Uint8Array> {
const N = 1024
const r = 8
const p = 1
const dkLen = 32
return scrypt(coToUInt8(password), coToUInt8(salt), N, r, p, dkLen)
}