Merge pull request #295 from shocknet/number-encryption
Number encryption
This commit is contained in:
commit
0f0e428391
8 changed files with 244 additions and 23 deletions
1
.eslintignore
Normal file
1
.eslintignore
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.ts
|
||||
|
|
@ -88,7 +88,10 @@
|
|||
// I am now convinced TODO comments closer to the relevant code are better
|
||||
// than GH issues. Especially when it only concerns a single function /
|
||||
// routine.
|
||||
"no-warning-comments": "off"
|
||||
"no-warning-comments": "off",
|
||||
|
||||
// broken
|
||||
"sort-imports": "off"
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"env": {
|
||||
|
|
|
|||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -2,5 +2,6 @@
|
|||
"eslint.enable": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"debug.node.autoAttach": "on",
|
||||
"editor.formatOnSave": true
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"test:watch": "jest --no-cache --watch",
|
||||
"typecheck": "tsc",
|
||||
"lint": "eslint \"services/gunDB/**/*.js\"",
|
||||
"format": "prettier --write \"./**/*.js\""
|
||||
"format": "prettier --write \"./**/*.js\"",
|
||||
"test:gun": "ts-node src/__gun__tests__/*.ts && rimraf -rf GUN-TEST-*"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
|
|
@ -81,6 +82,8 @@
|
|||
"lint-staged": "^10.2.2",
|
||||
"nodemon": "^1.19.3",
|
||||
"prettier": "^1.18.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^9.1.1",
|
||||
"ts-type": "^1.2.16",
|
||||
"typescript": "^4.0.2"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,23 +26,13 @@ const SEAx = require('gun/sea')
|
|||
/** @type {import('../contact-api/SimpleGUN').ISEA} */
|
||||
const mySEA = {}
|
||||
|
||||
const $$__SHOCKWALLET__MSG__ = '$$__SHOCKWALLET__MSG__'
|
||||
// Avoid this: https://github.com/amark/gun/issues/804 and any other issues
|
||||
const $$__SHOCKWALLET__ENCRYPTED__ = '$$_SHOCKWALLET__ENCRYPTED__'
|
||||
const $$__SHOCKWALLET__MSG__ = '$$__SHOCKWALLET__MSG__'
|
||||
const $$__SHOCKWALLET__NUMBER__ = '$$__SHOCKWALLET__NUMBER__'
|
||||
const $$__SHOCKWALLET__BOOLEAN__ = '$$__SHOCKWALLET__BOOLEAN__'
|
||||
|
||||
mySEA.encrypt = (msg, secret) => {
|
||||
if (typeof msg !== 'string') {
|
||||
throw new TypeError(
|
||||
'mySEA.encrypt() -> expected msg to be an string instead got: ' +
|
||||
typeof msg
|
||||
)
|
||||
}
|
||||
|
||||
if (msg.length === 0) {
|
||||
throw new TypeError(
|
||||
'mySEA.encrypt() -> expected msg to be a populated string'
|
||||
)
|
||||
}
|
||||
|
||||
if (typeof secret !== 'string') {
|
||||
throw new TypeError(
|
||||
`mySEA.encrypt() -> expected secret to be a an string, args: |msg| -- ${JSON.stringify(
|
||||
|
|
@ -57,15 +47,35 @@ mySEA.encrypt = (msg, secret) => {
|
|||
)
|
||||
}
|
||||
|
||||
// Avoid this: https://github.com/amark/gun/issues/804 and any other issues
|
||||
const sanitizedMsg = $$__SHOCKWALLET__MSG__ + msg
|
||||
let strToEncode = ''
|
||||
|
||||
return SEAx.encrypt(sanitizedMsg, secret).then(encMsg => {
|
||||
if (typeof msg === 'string') {
|
||||
if (msg.length === 0) {
|
||||
throw new TypeError(
|
||||
'mySEA.encrypt() -> expected msg to be a populated string'
|
||||
)
|
||||
}
|
||||
|
||||
strToEncode = $$__SHOCKWALLET__MSG__ + msg
|
||||
} else if (typeof msg === 'boolean') {
|
||||
strToEncode = $$__SHOCKWALLET__BOOLEAN__ + msg
|
||||
} else if (typeof msg === 'number') {
|
||||
strToEncode = $$__SHOCKWALLET__NUMBER__ + msg
|
||||
} else {
|
||||
throw new TypeError('mySea.encrypt() -> Not a valid msg type.')
|
||||
}
|
||||
|
||||
return SEAx.encrypt(strToEncode, secret).then(encMsg => {
|
||||
return $$__SHOCKWALLET__ENCRYPTED__ + encMsg
|
||||
})
|
||||
}
|
||||
|
||||
mySEA.decrypt = (encMsg, secret) => {
|
||||
/**
|
||||
* @param {string} encMsg
|
||||
* @param {string} secret
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
const decryptBase = (encMsg, secret) => {
|
||||
if (typeof encMsg !== 'string') {
|
||||
throw new TypeError(
|
||||
'mySEA.encrypt() -> expected encMsg to be an string instead got: ' +
|
||||
|
|
@ -104,10 +114,41 @@ mySEA.decrypt = (encMsg, secret) => {
|
|||
throw new TypeError('Could not decrypt')
|
||||
}
|
||||
|
||||
if (decodedMsg.startsWith($$__SHOCKWALLET__MSG__)) {
|
||||
return decodedMsg.slice($$__SHOCKWALLET__MSG__.length)
|
||||
} else if (decodedMsg.startsWith($$__SHOCKWALLET__BOOLEAN__)) {
|
||||
const dec = decodedMsg.slice($$__SHOCKWALLET__BOOLEAN__.length)
|
||||
if (dec === 'true') {
|
||||
return true
|
||||
} else if (dec === 'false') {
|
||||
return false
|
||||
}
|
||||
throw new Error('Could not decrypt boolean value.')
|
||||
} else if (decodedMsg.startsWith($$__SHOCKWALLET__NUMBER__)) {
|
||||
return Number(decodedMsg.slice($$__SHOCKWALLET__NUMBER__.length))
|
||||
}
|
||||
|
||||
throw new TypeError(
|
||||
`mySea.encrypt() -> Unexpected type of prefix found inside decrypted value, first 20 characters: ${decodedMsg.slice(
|
||||
0,
|
||||
20
|
||||
)}`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
mySEA.decrypt = (encMsg, secret) => {
|
||||
return decryptBase(encMsg, secret)
|
||||
}
|
||||
|
||||
mySEA.decryptNumber = (encMsg, secret) => {
|
||||
return decryptBase(encMsg, secret)
|
||||
}
|
||||
|
||||
mySEA.decryptBoolean = (encMsg, secret) => {
|
||||
return decryptBase(encMsg, secret)
|
||||
}
|
||||
|
||||
mySEA.secret = async (recipientOrSenderEpub, recipientOrSenderSEA) => {
|
||||
if (typeof recipientOrSenderEpub !== 'string') {
|
||||
throw new TypeError(
|
||||
|
|
|
|||
|
|
@ -120,8 +120,19 @@ export interface UserGUNNode extends GUNNode {
|
|||
}
|
||||
|
||||
export interface ISEA {
|
||||
encrypt(message: string, senderSecret: string): Promise<string>
|
||||
encrypt(
|
||||
message: string | number | boolean,
|
||||
senderSecret: string
|
||||
): Promise<string>
|
||||
decrypt(encryptedMessage: string, recipientSecret: string): Promise<string>
|
||||
decryptNumber(
|
||||
encryptedMessage: string,
|
||||
recipientSecret: string
|
||||
): Promise<number>
|
||||
decryptBoolean(
|
||||
encryptedMessage: string,
|
||||
recipientSecret: string
|
||||
): Promise<boolean>
|
||||
secret(
|
||||
recipientOrSenderEpub: string,
|
||||
recipientOrSenderUserPair: UserPair
|
||||
|
|
|
|||
109
src/__gun__tests__/mySea.ts
Normal file
109
src/__gun__tests__/mySea.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* @format
|
||||
*/
|
||||
import Gun from 'gun'
|
||||
import uuid from 'uuid/v1'
|
||||
|
||||
import { mySEA } from '../../services/gunDB/Mediator'
|
||||
import { UserGUNNode } from '../../services/gunDB/contact-api/SimpleGUN'
|
||||
|
||||
const setupUser = async (): Promise<[UserGUNNode]> => {
|
||||
const gun = Gun({
|
||||
file: 'GUN-TEST-' + uuid()
|
||||
})
|
||||
|
||||
const user = (gun.user() as unknown) as UserGUNNode
|
||||
|
||||
await new Promise<void>((res, rej) => {
|
||||
user.create('testAlias-' + uuid(), 'testPass', ack => {
|
||||
if (typeof ack.err === 'string') {
|
||||
rej(new Error(ack.err))
|
||||
} else {
|
||||
res()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return [user]
|
||||
}
|
||||
|
||||
const encryptsDecryptsStrings = async () => {
|
||||
const [user] = await setupUser()
|
||||
|
||||
const stringMessage = 'Lorem ipsum dolor'
|
||||
|
||||
const sec = await mySEA.secret(user._.sea.epub, user._.sea)
|
||||
const encrypted = await mySEA.encrypt(stringMessage, sec)
|
||||
const decrypted = await mySEA.decrypt(encrypted, sec)
|
||||
|
||||
if (decrypted !== stringMessage) {
|
||||
throw new Error()
|
||||
}
|
||||
}
|
||||
|
||||
const encryptsDecryptsBooleans = async () => {
|
||||
const [user] = await setupUser()
|
||||
|
||||
const truth = true
|
||||
const lie = false
|
||||
|
||||
const sec = await mySEA.secret(user._.sea.epub, user._.sea)
|
||||
|
||||
const encryptedTruth = await mySEA.encrypt(truth, sec)
|
||||
const decryptedTruth = await mySEA.decryptBoolean(encryptedTruth, sec)
|
||||
|
||||
if (decryptedTruth !== truth) {
|
||||
throw new Error()
|
||||
}
|
||||
|
||||
const encryptedLie = await mySEA.encrypt(lie, sec)
|
||||
const decryptedLie = await mySEA.decryptBoolean(encryptedLie, sec)
|
||||
|
||||
if (decryptedLie !== lie) {
|
||||
throw new Error(
|
||||
`Expected false got: ${decryptedLie} - ${typeof decryptedLie}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const encryptsDecryptsNumbers = async () => {
|
||||
const [user] = await setupUser()
|
||||
|
||||
const number = Math.random() * 999999
|
||||
|
||||
const sec = await mySEA.secret(user._.sea.epub, user._.sea)
|
||||
const encrypted = await mySEA.encrypt(number, sec)
|
||||
const decrypted = await mySEA.decryptNumber(encrypted, sec)
|
||||
|
||||
if (decrypted !== number) {
|
||||
throw new Error()
|
||||
}
|
||||
}
|
||||
|
||||
const encryptsDecryptsZero = async () => {
|
||||
const [user] = await setupUser()
|
||||
|
||||
const zero = 0
|
||||
|
||||
const sec = await mySEA.secret(user._.sea.epub, user._.sea)
|
||||
const encrypted = await mySEA.encrypt(zero, sec)
|
||||
const decrypted = await mySEA.decryptNumber(encrypted, sec)
|
||||
|
||||
if (decrypted !== zero) {
|
||||
throw new Error()
|
||||
}
|
||||
}
|
||||
|
||||
const runAllTests = async () => {
|
||||
await encryptsDecryptsStrings()
|
||||
await encryptsDecryptsBooleans()
|
||||
await encryptsDecryptsNumbers()
|
||||
await encryptsDecryptsZero()
|
||||
|
||||
console.log('\n--------------------------------')
|
||||
console.log('All tests ran successfully')
|
||||
console.log('--------------------------------\n')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
52
yarn.lock
52
yarn.lock
|
|
@ -1026,6 +1026,11 @@ are-we-there-yet@~1.1.2:
|
|||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
arg@^4.1.0:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
|
|
@ -1992,6 +1997,11 @@ create-error-class@^3.0.0:
|
|||
dependencies:
|
||||
capture-stack-trace "^1.0.0"
|
||||
|
||||
create-require@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||
|
||||
cross-spawn@^5.0.1:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
||||
|
|
@ -2195,6 +2205,11 @@ diff-sequences@^24.9.0:
|
|||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
doctrine@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
|
||||
|
|
@ -4701,6 +4716,11 @@ make-dir@^2.1.0:
|
|||
pify "^4.0.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
make-error@^1.1.1:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||
|
||||
makeerror@1.0.x:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
|
||||
|
|
@ -6058,6 +6078,13 @@ rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
|
|||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rsvp@^4.8.4:
|
||||
version "4.8.5"
|
||||
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
|
||||
|
|
@ -6409,6 +6436,14 @@ source-map-resolve@^0.5.0:
|
|||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@^0.5.17:
|
||||
version "0.5.19"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-support@^0.5.6:
|
||||
version "0.5.13"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
||||
|
|
@ -6895,6 +6930,18 @@ triple-beam@^1.2.0, triple-beam@^1.3.0:
|
|||
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
|
||||
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
|
||||
|
||||
ts-node@^9.1.1:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
|
||||
integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
|
||||
dependencies:
|
||||
arg "^4.1.0"
|
||||
create-require "^1.1.0"
|
||||
diff "^4.0.1"
|
||||
make-error "^1.1.1"
|
||||
source-map-support "^0.5.17"
|
||||
yn "3.1.1"
|
||||
|
||||
ts-toolbelt@^6.6.2:
|
||||
version "6.7.7"
|
||||
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.7.7.tgz#4d7f34cafd519bf0f1d6da5a4b07889db6ba0184"
|
||||
|
|
@ -7495,3 +7542,8 @@ yeast@0.1.2:
|
|||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
|
||||
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
|
||||
|
||||
yn@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue