Skip to content

Commit 2b4a4c7

Browse files
authored
A-1213877919321098: migrate Cipher to Web Crypto API (#252)
* refactor: migrate Cipher to Web Crypto API and add KDF iteration support Replace node-forge and pbkdf2 with native crypto.subtle for PBKDF2, AES-GCM, and random byte generation. Store kdfIterations per account and auto-migrate legacy accounts from 10k to 600k iterations on login. * refactor: remove entropy drawing board, use crypto.getRandomValues for mnemonic generation Replace mouse-drawn entropy with cryptographically secure crypto.getRandomValues(16 bytes) for BIP39 mnemonic generation. Remove Entropy component, related state, and renumber CreateAccount steps from 6 to 5. * refactor: replace unnecessary state+useEffect with derived values and useMemo * feat: update constants * test: update unit tests * fix: simplify mnemonic generation * refactor: replace kdfIterations with versioned encryption config Use encryptionVersion field in accounts instead of raw kdfIterations. Each version inherits from previous, making it easy to add new encryption parameters (encoding, hexWrap, etc.) in future versions. * test: add encryption tests
1 parent e97e16c commit 2b4a4c7

43 files changed

Lines changed: 885 additions & 884 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

jsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"compilerOptions": {
33
"baseUrl": ".",
4+
"ignoreDeprecations": "6.0",
45
"paths": {
56
"@BasicComponents": ["./src/components/basic/index.js"],
67
"@ComposedComponents": ["./src/components/composed/index.js"],

package-lock.json

Lines changed: 0 additions & 90 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"private": true,
55
"dependencies": {
66
"@bitcoinerlab/secp256k1": "^1.2.0",
7-
"@mintlayer/entropy-generator": "^1.0.6",
87
"@mintlayer/sdk": "1.0.30",
98
"@noble/secp256k1": "^3.0.0",
109
"bip32": "^5.0.0",
@@ -20,8 +19,6 @@
2019
"decimal.js": "^10.6.0",
2120
"ecpair": "3.0.0",
2221
"konva": "^10.2.0",
23-
"node-forge": "^1.3.3",
24-
"pbkdf2": "^3.1.5",
2522
"process": "^0.11.10",
2623
"react": "^19.2.4",
2724
"react-dom": "^19.2.4",
@@ -64,7 +61,6 @@
6461
"@babel/preset-env": "^7.29.0",
6562
"@babel/preset-react": "^7.28.5",
6663
"@eslint/js": "^9.39.2",
67-
"eslint": "^9.39.2",
6864
"@playwright/test": "^1.58.2",
6965
"@svgr/webpack": "^8.1.0",
7066
"@testing-library/dom": "^10.4.1",
@@ -74,35 +70,36 @@
7470
"@types/node": "^25.2.3",
7571
"@types/tiny-secp256k1": "^2.0.1",
7672
"babel-jest": "^30.2.0",
73+
"babel-loader": "^10.0.0",
74+
"copy-webpack-plugin": "^13.0.1",
75+
"css-loader": "^7.1.3",
7776
"dotenv": "^17.2.4",
7877
"dotenv-webpack": "^8.1.1",
7978
"env-cmd": "^11.0.0",
79+
"eslint": "^9.39.2",
8080
"eslint-plugin-react": "^7.37.5",
8181
"eslint-plugin-react-hooks": "^7.0.1",
8282
"fake-indexeddb": "^6.2.5",
8383
"globals": "^17.3.0",
84+
"html-webpack-plugin": "^5.6.6",
8485
"http-server": "^14.1.1",
8586
"husky": "^9.1.7",
8687
"identity-obj-proxy": "^3.0.0",
8788
"jest": "^30.2.0",
8889
"jest-canvas-mock": "^2.5.2",
8990
"jest-environment-jsdom": "^30.2.0",
9091
"jest-webgl-canvas-mock": "^2.5.3",
92+
"mini-css-extract-plugin": "^2.10.0",
9193
"prettier": "^3.8.1",
9294
"pretty-quick": "^4.2.2",
9395
"style-loader": "^4.0.0",
94-
"css-loader": "^7.1.3",
95-
"url-loader": "^4.1.1",
96-
"babel-loader": "^10.0.0",
97-
"html-webpack-plugin": "^5.6.6",
98-
"mini-css-extract-plugin": "^2.10.0",
99-
"copy-webpack-plugin": "^13.0.1",
100-
"webpack": "^5.105.1",
101-
"webpack-cli": "^6.0.1",
102-
"webpack-dev-server": "^5.2.3",
10396
"typescript": "^5.9.3",
97+
"url-loader": "^4.1.1",
10498
"vm-browserify": "^1.1.2",
10599
"wallet-address-validator": "^0.2.4",
106-
"webextension-polyfill": "^0.12.0"
100+
"webextension-polyfill": "^0.12.0",
101+
"webpack": "^5.105.1",
102+
"webpack-cli": "^6.0.1",
103+
"webpack-dev-server": "^5.2.3"
107104
}
108105
}

public/background.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@
174174
}
175175
}
176176

177+
if (!message.method && message.action !== 'popupResponse') return
178+
177179
// Handle popup responses
178180
if (message.action === 'popupResponse') {
179181
const { requestId, origin, result, error } = message
@@ -209,7 +211,7 @@
209211
storedSendResponse({ result, error })
210212
pendingResponses.delete(requestId)
211213
} else {
212-
api.runtime.sendMessage({ requestId, result, error }, (response) => {
214+
api.runtime.sendMessage({ requestId, result, error }, () => {
213215
if (api.runtime.lastError) {
214216
console.error(
215217
'[Mintlayer] Send response error:',

src/components/basic/Button/Button.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const Button = ({
1313
dataTestId = 'button',
1414
onMouseEnter,
1515
onMouseLeave,
16+
autoFocus = false,
1617
}) => {
17-
// Вычисляем классы сразу, без useEffect
1818
const classList = ['btn', ...extraStyleClasses]
1919
if (dark) {
2020
classList.push('dark')
@@ -32,6 +32,7 @@ const Button = ({
3232
type={buttonType}
3333
onMouseEnter={onMouseEnter}
3434
onMouseLeave={onMouseLeave}
35+
autoFocus={autoFocus}
3536
>
3637
{children}
3738
</button>

src/components/basic/Input/InputFloat.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { AppInfo, Expressions } from '@Constants'
22
import { NumbersHelper } from '@Helpers'
3-
import { useEffect, useState } from 'react'
43
import Input from './Input'
54

65
const InputFloat = (props) => {
@@ -12,7 +11,7 @@ const InputFloat = (props) => {
1211
const [regexIntegerPartIndex, regexDecimalPartIndex] = [1, 5]
1312
const breakersRegex = /[.,]/g
1413

15-
const [value, setValue] = useState(props.value || '')
14+
const value = props.value || ''
1615

1716
const removeBreakers = (value) => value.replaceAll(breakersRegex, '')
1817

@@ -76,10 +75,6 @@ const InputFloat = (props) => {
7675
return parsedVal.value || ev.target.value
7776
}
7877

79-
useEffect(() => {
80-
setValue(props.value)
81-
}, [props.value])
82-
8378
return (
8479
<Input
8580
{...props}

src/components/basic/Input/InputInteger.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import { useEffect, useState } from 'react'
1+
import { useMemo } from 'react'
22
import Input from './Input'
33

44
import { Expressions } from '@Constants'
55
import { NumbersHelper } from '@Helpers'
66

77
const InputInteger = (props) => {
88
const mask = Expressions.FIELDS.INTEGER
9-
const [value, setValue] = useState(0)
109

11-
useEffect(() => {
12-
setValue(~~props.value)
13-
!NumbersHelper.isInteger(props.value) &&
10+
const value = useMemo(() => {
11+
if (!NumbersHelper.isInteger(props.value)) {
1412
console.warn(
1513
'A non-integer value was passed to InputInteger. It has been converted to integer.',
1614
)
15+
}
16+
return ~~props.value
1717
}, [props.value])
1818

1919
const parseValue = ({ target: { value, matchedValue } }) => {

src/components/basic/Svg/Svg.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect } from 'react'
1+
import React from 'react'
22

33
const Svg = ({
44
children,
@@ -8,13 +8,8 @@ const Svg = ({
88
width = '100px',
99
height = '100px',
1010
}) => {
11-
const [viewboxWidth, setViewBoxWidth] = useState(size)
12-
const [viewboxHeight, setViewBoxHeight] = useState(size)
13-
14-
useEffect(() => {
15-
sizeH ? setViewBoxHeight(sizeH) : setViewBoxHeight(size)
16-
sizeW ? setViewBoxWidth(sizeW) : setViewBoxWidth(size)
17-
}, [sizeH, sizeW, size])
11+
const viewboxWidth = sizeW || size
12+
const viewboxHeight = sizeH || size
1813

1914
return (
2015
<svg

src/components/composed/Charts/LineChart/LineChart.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect } from 'react'
1+
import React, { useMemo } from 'react'
22

33
import { Svg, Line } from '@BasicComponents'
44

@@ -37,19 +37,18 @@ const LineChart = ({
3737
height,
3838
width = '100px',
3939
}) => {
40-
const [size, setSize] = useState({ w: 0, h: 0 })
41-
const [proportionalHeight, setProportionalHeight] = useState()
42-
43-
useEffect(() => {
44-
setSize({
40+
const size = useMemo(
41+
() => ({
4542
w: maxWidthPoint(points) + EXTRABOUNDARIES,
4643
h: parseInt(height) + EXTRABOUNDARIES,
47-
})
48-
}, [points, height])
44+
}),
45+
[points, height],
46+
)
4947

50-
useEffect(() => {
51-
setProportionalHeight(height || getProportionalHeight(size, width))
52-
}, [width, height, size])
48+
const proportionalHeight = useMemo(
49+
() => height || getProportionalHeight(size, width),
50+
[width, height, size],
51+
)
5352

5453
return (
5554
<Svg

0 commit comments

Comments
 (0)