Skip to content

Commit

Permalink
Fix checksum code for browsers (duckduckgo#2120)
Browse files Browse the repository at this point in the history
* Fix HTTPs checksum when Buffer is not available

* Move https storage test out of legacy

* Fix lint
  • Loading branch information
sammacbeth authored Jul 20, 2023
1 parent 2db391a commit 3c1ae26
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ JS_BUNDLES = background.js base.js feedback.js options.js devtools-panel.js list
BUILD_TARGETS = $(addprefix $(BUILD_DIR)/public/js/, $(JS_BUNDLES))

## Unit tests scripts.
UNIT_TEST_SRC = unit-test/legacy/*.js unit-test/legacy/reference-tests/*.js unit-test/legacy/storage/*.js
UNIT_TEST_SRC = unit-test/legacy/*.js unit-test/legacy/reference-tests/*.js
build/test:
mkdir -p $@

Expand Down
43 changes: 25 additions & 18 deletions shared/js/background/storage/https.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@ const load = require('./../load')
const constants = require('../../../data/constants')
const settings = require('./../settings')

/**
* Calculate an sha256 checksum (in base64) of the provided base64 string
* @param {string} data
*/
export async function checksum (data) {
// Convert base64 string into a Uint8Array
const binaryString = atob(data)
const buffer = new Uint8Array(binaryString.length)
for (let i = 0; i < binaryString.length; i++) {
buffer[i] = binaryString.charCodeAt(i)
}
// Calculate SHA-256 of the buffer
const sha256Buffer = new Uint8Array(await crypto.subtle.digest('SHA-256', buffer))
// Convert the buffer back into base64
let binary = ''
for (let i = 0; i < sha256Buffer.byteLength; i++) {
binary += String.fromCharCode(sha256Buffer[i])
}
return btoa(binary)
}

class HTTPSStorage {
constructor () {
// @ts-ignore - TypeScript is not following the Dexie import property.
Expand Down Expand Up @@ -124,26 +145,12 @@ class HTTPSStorage {
})
}

hasCorrectChecksum (data) {
async hasCorrectChecksum (data) {
// not everything has a checksum
if (!data.checksum) return Promise.resolve(true)
if (!data.checksum) return true

// TODO: rewrite this check without needing a Buffer polyfill
if (typeof Buffer === 'undefined') {
return Promise.resolve(true)
}

// need a buffer to send to crypto.subtle
const buffer = Buffer.from(data.data, 'base64')

return crypto.subtle.digest('SHA-256', buffer).then(arrayBuffer => {
const sha256 = Buffer.from(arrayBuffer).toString('base64')
if (data.checksum.sha256 && data.checksum.sha256 === sha256) {
return true
} else {
return false
}
})
const sha256 = await checksum(data.data)
return data.checksum.sha256 && data.checksum.sha256 === sha256
}
}
export default new HTTPSStorage()
12 changes: 12 additions & 0 deletions unit-test/background/storage/checksum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { checksum } from '../../../shared/js/background/storage/https'
import httpsBloom from './../../data/httpsBloom.json'

describe('legacy checksum', () => {
it('calculates the sha256 checksum of data', async () => {
expect(await checksum('test')).toEqual('ZheqiKcua1JriMvO2jiKe1Kg6FYUihLZuEKc0qU6PqQ=')
})

it('correctly calculates the checksum of a bloom filter', async () => {
expect(await checksum(httpsBloom.data)).toEqual(httpsBloom.checksum.sha256)
})
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require('../../helpers/mock-browser-api')

const httpsStorage = require('../../../shared/js/background/storage/https').default
const httpsBloom = require('./../../data/httpsBloom.json')
const httpsAllowlist = require('./../../data/httpsAllowlist.json')
Expand Down

0 comments on commit 3c1ae26

Please sign in to comment.