diff --git a/native/native_rust_library/Cargo.lock b/native/native_rust_library/Cargo.lock --- a/native/native_rust_library/Cargo.lock +++ b/native/native_rust_library/Cargo.lock @@ -779,7 +779,6 @@ "derive_more", "grpc_clients", "lazy_static", - "rand", "regex", "serde", "serde_json", diff --git a/native/native_rust_library/Cargo.toml b/native/native_rust_library/Cargo.toml --- a/native/native_rust_library/Cargo.toml +++ b/native/native_rust_library/Cargo.toml @@ -11,9 +11,7 @@ tokio = { version = "1.24", features = ["macros", "rt-multi-thread"] } tonic = "0.9.1" lazy_static = "1.4" -rand = "0.8" tracing = "0.1" -regex = "1.6" comm-opaque2 = {path = "../../shared/comm-opaque2"} derive_more = "0.99" serde = { version = "1.0", features = ["derive"] } diff --git a/native/native_rust_library/src/crypto_tools.rs b/native/native_rust_library/src/crypto_tools.rs deleted file mode 100644 --- a/native/native_rust_library/src/crypto_tools.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::ffi::DeviceType; -use rand::distributions::{Alphanumeric, DistString}; -#[cfg(test)] -use regex::Regex; - -// DEVICE_ID_CHAR_LENGTH has to be kept in sync with deviceIDCharLength -// which is defined in web/utils/device-id.js -// and with DEVICE_CHAR_LENGTH -// defined in services/tunnelbroker/src/Constants.h -const DEVICE_ID_CHAR_LENGTH: usize = 64; -// DEVICE_ID_FORMAT_REGEX has to be kept in sync with deviceIDFormatRegex -// which is defined in web/utils/device-id.js -// and with DEVICEID_FORMAT_REGEX -// defined in services/tunnelbroker/src/Constants.h -#[cfg(test)] -const DEVICE_ID_FORMAT_REGEX: &str = "^(ks|mobile|web):[a-zA-Z0-9]{64}$"; - -// generate_device_id has to be kept in sync with generateDeviceID -// which is defined in web/utils/device-id.js -pub fn generate_device_id(device_type: DeviceType) -> Result { - let prefix = match device_type { - DeviceType::KEYSERVER => "ks", - DeviceType::WEB => "web", - DeviceType::MOBILE => "mobile", - _ => { - return Err(String::from("Incorrect device type provieded")); - } - }; - let mut rng = rand::thread_rng(); - let suffix: String = - Alphanumeric.sample_string(&mut rng, DEVICE_ID_CHAR_LENGTH); - - Ok(format!("{}:{}", &prefix, &suffix)) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn check_regex(s: &String) -> bool { - Regex::new(&DEVICE_ID_FORMAT_REGEX).unwrap().is_match(&s) - } - - #[test] - fn generate_device_id_ks() { - for _x in 1..100 { - let result = generate_device_id(DeviceType::KEYSERVER).unwrap(); - assert!( - check_regex(&result), - "result: {} does not match regex {}", - &result, - &DEVICE_ID_FORMAT_REGEX - ); - } - } - - #[test] - fn generate_device_id_web() { - for _x in 1..100 { - let result = generate_device_id(DeviceType::WEB).unwrap(); - assert!( - check_regex(&result), - "result: {} does not match regex {}", - &result, - &DEVICE_ID_FORMAT_REGEX - ); - } - } - - #[test] - fn generate_device_id_mobile() { - for _x in 1..100 { - let result = generate_device_id(DeviceType::MOBILE).unwrap(); - assert!( - check_regex(&result), - "result: {} does not match regex {}", - &result, - &DEVICE_ID_FORMAT_REGEX - ); - } - } -} diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -18,10 +18,8 @@ use tracing::instrument; mod argon2_tools; -mod crypto_tools; use argon2_tools::compute_backup_key; -use crypto_tools::generate_device_id; mod generated { // We get the CODE_VERSION from this generated file @@ -49,12 +47,6 @@ #[cxx::bridge] mod ffi { - enum DeviceType { - KEYSERVER, - WEB, - MOBILE, - } - extern "Rust" { #[cxx_name = "identityRegisterUser"] fn register_user( @@ -130,9 +122,6 @@ #[cxx_name = "identityGenerateNonce"] fn generate_nonce(promise_id: u32); - // Crypto Tools - fn generate_device_id(device_type: DeviceType) -> Result; - // Argon2 fn compute_backup_key(password: &str, backup_id: &str) -> Result<[u8; 32]>; } diff --git a/web/app.react.js b/web/app.react.js --- a/web/app.react.js +++ b/web/app.react.js @@ -54,7 +54,6 @@ import useBadgeHandler from './push-notif/badge-handler.react.js'; import { PushNotificationsHandler } from './push-notif/push-notifs-handler.js'; import { updateNavInfoActionType } from './redux/action-types.js'; -import DeviceIDUpdater from './redux/device-id-updater.js'; import DisconnectedBarVisibilityHandler from './redux/disconnected-bar-visibility-handler.js'; import DisconnectedBar from './redux/disconnected-bar.js'; import FocusHandler from './redux/focus-handler.react.js'; @@ -195,7 +194,6 @@ - diff --git a/web/redux/action-types.js b/web/redux/action-types.js --- a/web/redux/action-types.js +++ b/web/redux/action-types.js @@ -8,7 +8,6 @@ export const updateNavInfoActionType = 'UPDATE_NAV_INFO'; export const updateWindowDimensionsActionType = 'UPDATE_WINDOW_DIMENSIONS'; export const updateWindowActiveActionType = 'UPDATE_WINDOW_ACTIVE'; -export const setDeviceIDActionType = 'SET_DEVICE_ID'; export const setInitialReduxState = 'SET_INITIAL_REDUX_STATE'; const getInitialReduxStateCallServerEndpointOptions = { timeout: 300000 }; diff --git a/web/redux/default-state.js b/web/redux/default-state.js --- a/web/redux/default-state.js +++ b/web/redux/default-state.js @@ -44,7 +44,6 @@ notificationAccount: null, notificationIdentityKeys: null, }, - deviceID: null, windowDimensions: { width: window.width, height: window.height }, loadingStatuses: {}, calendarFilters: defaultCalendarFilters, diff --git a/web/redux/device-id-reducer.js b/web/redux/device-id-reducer.js deleted file mode 100644 --- a/web/redux/device-id-reducer.js +++ /dev/null @@ -1,28 +0,0 @@ -// @flow - -import { - deleteAccountActionTypes, - logOutActionTypes, -} from 'lib/actions/user-actions.js'; -import { setNewSessionActionType } from 'lib/utils/action-utils.js'; - -import { setDeviceIDActionType } from './action-types.js'; -import type { Action } from '../redux/redux-setup.js'; -import { deviceIDFormatRegex } from '../utils/device-id.js'; - -export function reduceDeviceID(state: ?string, action: Action): ?string { - if (action.type === setDeviceIDActionType) { - if (action.payload?.match(deviceIDFormatRegex)) { - return action.payload; - } - return null; - } else if ( - action.type === logOutActionTypes.success || - action.type === deleteAccountActionTypes.success || - (action.type === setNewSessionActionType && - action.payload.sessionChange.cookieInvalidated) - ) { - return null; - } - return state; -} diff --git a/web/redux/device-id-updater.js b/web/redux/device-id-updater.js deleted file mode 100644 --- a/web/redux/device-id-updater.js +++ /dev/null @@ -1,28 +0,0 @@ -// @flow -import * as React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; - -import { setDeviceIDActionType } from './action-types.js'; -import { generateDeviceID, deviceTypes } from '../utils/device-id.js'; - -function DeviceIDUpdater(): null { - const dispatch = useDispatch(); - const deviceID = useSelector(state => state.deviceID); - const hasDeviceID = !!deviceID; - const hadDeviceIDRef = React.useRef(null); - - React.useEffect(() => { - if (hadDeviceIDRef.current !== false && !hasDeviceID) { - const newDeviceID = generateDeviceID(deviceTypes.WEB); - dispatch({ - type: setDeviceIDActionType, - payload: newDeviceID, - }); - } - hadDeviceIDRef.current = hasDeviceID; - }, [hasDeviceID, dispatch]); - - return null; -} - -export default DeviceIDUpdater; diff --git a/web/redux/persist.js b/web/redux/persist.js --- a/web/redux/persist.js +++ b/web/redux/persist.js @@ -172,7 +172,6 @@ const persistWhitelist = [ 'enabledApps', - 'deviceID', 'cryptoStore', 'notifPermissionAlertInfo', 'commServicesAccessToken', diff --git a/web/redux/redux-setup.js b/web/redux/redux-setup.js --- a/web/redux/redux-setup.js +++ b/web/redux/redux-setup.js @@ -41,7 +41,6 @@ import { updateWindowActiveActionType, - setDeviceIDActionType, updateNavInfoActionType, updateWindowDimensionsActionType, setInitialReduxState, @@ -54,7 +53,6 @@ setPickledNotificationAccount, setPickledPrimaryAccount, } from './crypto-store-reducer.js'; -import { reduceDeviceID } from './device-id-reducer.js'; import reduceNavInfo from './nav-reducer.js'; import { getVisibility } from './visibility.js'; import { getDatabaseModule } from '../database/database-module-provider.js'; @@ -72,7 +70,6 @@ export type AppState = { +navInfo: NavInfo, - +deviceID: ?string, +currentUserInfo: ?CurrentUserInfo, +draftStore: DraftStore, +entryStore: EntryStore, @@ -117,10 +114,6 @@ type: 'UPDATE_WINDOW_ACTIVE', payload: boolean, } - | { - type: 'SET_DEVICE_ID', - payload: string, - } | { +type: 'SET_PRIMARY_IDENTITY_KEYS', payload: ?OLMIdentityKeys } | { +type: 'SET_NOTIFICATION_IDENTITY_KEYS', payload: ?OLMIdentityKeys } | { +type: 'SET_PICKLED_PRIMARY_ACCOUNT', payload: ?PickledOLMAccount } @@ -202,7 +195,6 @@ if ( action.type !== updateNavInfoActionType && - action.type !== setDeviceIDActionType && action.type !== setPrimaryIdentityKeys && action.type !== setNotificationIdentityKeys && action.type !== setPickledPrimaryAccount && @@ -246,7 +238,6 @@ action, state.threadStore.threadInfos, ), - deviceID: reduceDeviceID(state.deviceID, action), cryptoStore: reduceCryptoStore(state.cryptoStore, action), communityPickerStore, }; diff --git a/web/utils/device-id.js b/web/utils/device-id.js deleted file mode 100644 --- a/web/utils/device-id.js +++ /dev/null @@ -1,51 +0,0 @@ -// @flow - -import invariant from 'invariant'; - -import { generateRandomString } from './text-utils.js'; - -const deviceTypes = Object.freeze({ - KEYSERVER: 0, - WEB: 1, - MOBILE: 2, -}); -type DeviceType = $Values; - -const alphanumeric = - '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; -// deviceIDCharLength has to be kept in sync with DEVICEID_CHAR_LENGTH -// which is defined in services/tunnelbroker/src/Constants.h -// and with DEVICE_ID_CHAR_LENGTH -// defined in native/native_rust_library/src/crypto_tools.rs -const deviceIDCharLength = 64; -// deviceIDFormatRegex has to be kept in sync with DEVICEID_FORMAT_REGEX -// which is defined in services/tunnelbroker/src/Constants.h -// and with DEVICE_ID_FORMAT_REGEX -// defined in native/native_rust_library/src/crypto_tools.rs -const deviceIDFormatRegex: RegExp = new RegExp( - `^(ks|mobile|web):[a-zA-Z0-9]{${deviceIDCharLength.toString()}}$`, -); - -// generateDeviceID has to be kept in sync with generate_device_id -// which is defined in native/native_rust_library/src/crypto_tools.rs -// Next line is because ESLint doesn't recognize that invariant always throws -// eslint-disable-next-line consistent-return -function generateDeviceID(type: DeviceType): string { - const suffix = generateRandomString(deviceIDCharLength, alphanumeric); - - if (type === deviceTypes.KEYSERVER) { - return `ks:${suffix}`; - } else if (type === deviceTypes.WEB) { - return `web:${suffix}`; - } else if (type === deviceTypes.MOBILE) { - return `mobile:${suffix}`; - } - invariant(false, `Unhandled device type ${type}`); -} - -export { - generateDeviceID, - deviceIDCharLength, - deviceTypes, - deviceIDFormatRegex, -}; diff --git a/web/utils/device-id.test.js b/web/utils/device-id.test.js deleted file mode 100644 --- a/web/utils/device-id.test.js +++ /dev/null @@ -1,66 +0,0 @@ -// @flow - -import { - generateDeviceID, - deviceIDCharLength, - deviceTypes, - deviceIDFormatRegex, -} from './device-id.js'; - -describe('generateDeviceID', () => { - it( - 'passed deviceTypes.KEYSERVER retruns a randomly generated string, ' + - 'subject to ^(ks|mobile|web):[a-zA-Z0-9]{DEVICEID_CHAR_LENGTH}$', - () => { - expect(generateDeviceID(deviceTypes.KEYSERVER)).toMatch( - deviceIDFormatRegex, - ); - }, - ); - - it( - 'passed deviceTypes.WEB retruns a randomly generated string, ' + - 'subject to ^(ks|mobile|web):[a-zA-Z0-9]{DEVICEID_CHAR_LENGTH}$', - () => { - expect(generateDeviceID(deviceTypes.WEB)).toMatch(deviceIDFormatRegex); - }, - ); - - it( - 'passed deviceTypes.MOBILE retruns a randomly generated string, ' + - 'subject to ^(ks|mobile|web):[a-zA-Z0-9]{DEVICEID_CHAR_LENGTH}$', - () => { - expect(generateDeviceID(deviceTypes.MOBILE)).toMatch(deviceIDFormatRegex); - }, - ); - - it( - 'passed deviceTypes.KEYSERVER retruns a randomly generated string, ' + - 'subject to ^(ks):[a-zA-Z0-9]{DEVICEID_CHAR_LENGTH}$', - () => { - expect(generateDeviceID(deviceTypes.KEYSERVER)).toMatch( - new RegExp(`^(ks):[a-zA-Z0-9]{${deviceIDCharLength.toString()}}$`), - ); - }, - ); - - it( - 'passed deviceTypes.WEB retruns a randomly generated string, ' + - 'subject to ^(web):[a-zA-Z0-9]{DEVICEID_CHAR_LENGTH}$', - () => { - expect(generateDeviceID(deviceTypes.WEB)).toMatch( - new RegExp(`^(web):[a-zA-Z0-9]{${deviceIDCharLength.toString()}}$`), - ); - }, - ); - - it( - 'passed deviceTypes.MOBILE retruns a randomly generated string, ' + - 'subject to ^(mobile):[a-zA-Z0-9]{DEVICEID_CHAR_LENGTH}$', - () => { - expect(generateDeviceID(deviceTypes.MOBILE)).toMatch( - new RegExp(`^(mobile):[a-zA-Z0-9]{${deviceIDCharLength.toString()}}$`), - ); - }, - ); -}); diff --git a/web/utils/text-utils.js b/web/utils/text-utils.js --- a/web/utils/text-utils.js +++ b/web/utils/text-utils.js @@ -1,7 +1,5 @@ // @flow -import invariant from 'invariant'; - let canvas; function calculateMaxTextWidth( @@ -22,44 +20,4 @@ return Math.max(...widths); } -const numberOfPossibleByteValues = 256; - -function generateRandomString(length: number, availableSigns: string): string { - invariant(length >= 0, 'length must be non-negative'); - invariant( - availableSigns !== '' || length === 0, - "cannot create a random string of non-zero length from availableSigns = ''", - ); - invariant( - numberOfPossibleByteValues >= availableSigns.length, - `The number of available signs must not exceed ${numberOfPossibleByteValues}`, - ); - - const validByteUpperBound = - availableSigns.length * - Math.floor(numberOfPossibleByteValues / availableSigns.length); - // Generating more bytes than the required length, - // proportionally to how many values will be omitted - // due to uniformness requirement, - // to lower the chances of having to draw again - const drawBytes = Math.floor( - length * (1 + 2 * (1 - validByteUpperBound / numberOfPossibleByteValues)), - ); - - let str = ''; - - while (str.length < length) { - const rand = new Uint8Array(drawBytes); - crypto.getRandomValues(rand); - - for (let i = 0; str.length < length && i < drawBytes; i++) { - if (rand[i] < validByteUpperBound) { - const index = rand[i] % availableSigns.length; - str += availableSigns.charAt(index); - } - } - } - return str; -} - -export { calculateMaxTextWidth, generateRandomString }; +export { calculateMaxTextWidth }; diff --git a/web/utils/text-utils.test.js b/web/utils/text-utils.test.js deleted file mode 100644 --- a/web/utils/text-utils.test.js +++ /dev/null @@ -1,55 +0,0 @@ -// @flow - -import { generateRandomString } from './text-utils.js'; - -describe('generateRandomString', () => { - it('should return an empty string when passed length = 0', () => { - expect(generateRandomString(0, 'abcde')).toMatch(/^$/); - expect(generateRandomString(0, '')).toMatch(/^$/); - }); - - it( - 'should return a random string of length equal to length argument, ' + - 'containig only characters given in availableSigns', - () => { - const length1 = 100; - const availableSigns1 = 'abcde'; - expect(generateRandomString(length1, availableSigns1)).toMatch( - new RegExp(`^[${availableSigns1}]{${length1.toString()}}$`), - ); - - const length2 = 10; - const availableSigns2 = 'abcde0123456789!@#$%^&*'; - expect(generateRandomString(length2, availableSigns2)).toMatch( - new RegExp(`^[${availableSigns2}]{${length2.toString()}}$`), - ); - - const length3 = 10; - const availableSigns3 = 'a'; - expect(generateRandomString(length3, availableSigns3)).toMatch( - new RegExp(`^[${availableSigns3}]{${length3.toString()}}$`), - ); - }, - ); - - it('should throw an error when length is negative', () => { - expect(() => generateRandomString(-1, 'abc')).toThrow(); - expect(() => generateRandomString(-1, '')).toThrow(); - expect(() => generateRandomString(-123, 'abc')).toThrow(); - expect(() => generateRandomString(-123, '')).toThrow(); - }); - - it( - 'should throw an error when availableSigns is an empty string, ' + - 'and length is positive', - () => { - expect(() => generateRandomString(1, '')).toThrow(); - expect(() => generateRandomString(10, '')).toThrow(); - }, - ); - - it('should throw an error when availableSigns length exceeds 256', () => { - const longString = 'a'.repeat(257); - expect(() => generateRandomString(1, longString)).toThrow(); - }); -});