Skip to content

Commit

Permalink
Merge 58baedb into 4145776
Browse files Browse the repository at this point in the history
  • Loading branch information
liangyuanruo committed Jun 4, 2020
2 parents 4145776 + 58baedb commit ce187cf
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 37 deletions.
17 changes: 6 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opengovsg/formsg-sdk",
"version": "0.8.1",
"version": "0.8.2",
"repository": {
"type": "git",
"url": "https://github.com/opengovsg/formsg-javascript-sdk.git"
Expand All @@ -22,9 +22,8 @@
"author": "Open Government Products (FormSG)",
"license": "MIT",
"dependencies": {
"@stablelib/base64": "^1.0.0",
"@stablelib/utf8": "^1.0.0",
"tweetnacl": "^1.0.3"
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
Expand Down
16 changes: 16 additions & 0 deletions spec/crypto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
formPublicKey,
} from './resources/crypto-data-20200322'

import { plaintextMultiLang } from './resources/crypto-data-20200604'

const formsg = formsgPackage({ mode: 'test' })

const INTERNAL_TEST_VERSION = 1
Expand Down Expand Up @@ -90,6 +92,20 @@ describe('Crypto', function () {
expect(decrypted).toHaveProperty('responses', plaintext)
})

it('should be able to encrypt and decrypt multi-language submission from 2020-06-04 end-to-end successfully', () => {
// Arrange
const { publicKey, secretKey } = formsg.crypto.generate()

// Act
const ciphertext = formsg.crypto.encrypt(plaintextMultiLang, publicKey)
const decrypted = formsg.crypto.decrypt(secretKey, {
encryptedContent: ciphertext,
version: INTERNAL_TEST_VERSION,
})
// Assert
expect(decrypted).toHaveProperty('responses', plaintextMultiLang)
})

it('should be able to encrypt submissions without signing if signingPrivateKey is missing', () => {
// Arrange
const { publicKey, secretKey } = formsg.crypto.generate()
Expand Down
18 changes: 18 additions & 0 deletions spec/resources/crypto-data-20200604.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const plaintextMultiLang = [
{
_id: '5e771c8a6b3c5100240368e1',
question: 'Radio',
fieldType: 'radiobutton',
answer: '96%, or more / 96% (விழுக்காடு) அல்லது அதை விட அதிகமா? / ৯৬% বা বেশী / 96% या ज़्यादा / 96%以上',
},
{
_id: '5e771c8a6b3c5100240368e2',
question: 'Radio',
fieldType: 'radiobutton',
answer: 'less than 96% / 96% (விழுக்காட்டை) விட குறைவா? / ৯৬% চেয়ে কম / 96% से कम / 少于96%',
},
]

export {
plaintextMultiLang,
}
19 changes: 11 additions & 8 deletions src/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import nacl from 'tweetnacl'
import {
encode as encodeBase64,
decode as decodeBase64,
} from '@stablelib/base64'
import { encode as encodeUTF8, decode as decodeUTF8 } from '@stablelib/utf8'

import {
DecryptParams,
Expand All @@ -14,6 +9,14 @@ import {
Keypair,
PackageInitParams,
} from './types'

import {
encodeBase64,
decodeBase64,
encodeUTF8,
decodeUTF8,
} from 'tweetnacl-util'

import { getPublicKey } from './util/publicKey'
import { determineIsFormFields } from './util/validate'

Expand All @@ -29,7 +32,7 @@ function encrypt(
encryptionPublicKey: string,
signingPrivateKey?: string
): EncryptedContent {
let processedMsg = encodeUTF8(JSON.stringify(msg))
let processedMsg = decodeUTF8(JSON.stringify(msg))

if (signingPrivateKey) {
processedMsg = nacl.sign(processedMsg, decodeBase64(signingPrivateKey))
Expand Down Expand Up @@ -96,7 +99,7 @@ function _verifySignedMessage(
const openedMessage = nacl.sign.open(msg, decodeBase64(publicKey))
if (!openedMessage)
throw new Error('Failed to open signed message with given public key')
return JSON.parse(decodeUTF8(openedMessage))
return JSON.parse(encodeUTF8(openedMessage))
}

/**
Expand Down Expand Up @@ -127,7 +130,7 @@ function decrypt(signingPublicKey: string) {
if (!decryptedContent) {
throw new Error('Failed to decrypt content')
}
const decryptedObject: Object = JSON.parse(decodeUTF8(decryptedContent))
const decryptedObject: Object = JSON.parse(encodeUTF8(decryptedContent))
if (!determineIsFormFields(decryptedObject)) {
throw new Error('Decrypted object does not fit expected shape')
}
Expand Down
7 changes: 3 additions & 4 deletions src/util/signature.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as tweetnacl from 'tweetnacl'
import { encode as encodeUTF8 } from '@stablelib/utf8'
import { encode as encodeBase64, decode as decodeBase64 } from '@stablelib/base64'
import { decodeUTF8, encodeBase64, decodeBase64 } from 'tweetnacl-util'

/**
* Returns a signature from a basestring and secret key
Expand All @@ -10,7 +9,7 @@ import { encode as encodeBase64, decode as decodeBase64 } from '@stablelib/base6
*/
function sign(basestring: string, secretKey: string): string {
return encodeBase64(
tweetnacl.sign.detached(encodeUTF8(basestring), decodeBase64(secretKey))
tweetnacl.sign.detached(decodeUTF8(basestring), decodeBase64(secretKey))
)
}

Expand All @@ -27,7 +26,7 @@ function verify(
publicKey: string
): boolean {
return tweetnacl.sign.detached.verify(
encodeUTF8(message),
decodeUTF8(message),
decodeBase64(signature),
decodeBase64(publicKey)
)
Expand Down
5 changes: 2 additions & 3 deletions src/verification/authenticate.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import nacl from 'tweetnacl'
import { encode as encodeUTF8 } from '@stablelib/utf8'
import { decode as decodeBase64 } from '@stablelib/base64'

import { VerificationAuthenticateOptions } from '../types'
import { decodeUTF8, decodeBase64 } from 'tweetnacl-util'
import basestring from './basestring'

export default function (
Expand Down Expand Up @@ -62,7 +61,7 @@ export default function (
time: signatureDate,
})
return nacl.sign.detached.verify(
encodeUTF8(data),
decodeUTF8(data),
decodeBase64(signature),
decodeBase64(publicKey)
)
Expand Down
9 changes: 2 additions & 7 deletions src/verification/generate-signature.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import nacl from 'tweetnacl'
import { encode as encodeUTF8 } from '@stablelib/utf8'
import {
encode as encodeBase64,
decode as decodeBase64,
} from '@stablelib/base64'

import { VerificationSignatureOptions } from '../types'
import { decodeUTF8, decodeBase64, encodeBase64 } from 'tweetnacl-util'
import basestring from './basestring'

export default function (privateKey: string) {
Expand All @@ -18,7 +13,7 @@ export default function (privateKey: string) {
const time = Date.now()
const data = basestring({ transactionId, formId, fieldId, answer, time })
const signature = nacl.sign.detached(
encodeUTF8(data),
decodeUTF8(data),
decodeBase64(privateKey)
)
return `f=${formId},v=${transactionId},t=${time},s=${encodeBase64(
Expand Down

0 comments on commit ce187cf

Please sign in to comment.