Skip to content

Commit 48c8e2c

Browse files
committed
update util functions and more tests
1 parent de620cc commit 48c8e2c

File tree

4 files changed

+58
-23
lines changed

4 files changed

+58
-23
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change Log
22

3+
## Release 0.2.11
4+
+ can import/export private key from openssl standard encrypted base64 format
5+
+ At the moment PEM PKCS8 format not supported
6+
+ utils function 'hexToByteArray', 'isHexString', 'wordArrayToByteArray' and 'byteArrayToWordArray' to support the new crypto library
7+
38
## Release 0.2.10
49
+ removed cypto, pem-file packages and replaced with @noble/ed25519 and crypto-key-composer
510

src/KeyPair.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ export class KeyPair {
3939
return new KeyPair(publicKey, privateKey)
4040
}
4141
/**
42-
* Imports a keypair from a PKCS8 fromated text string. You need to pass the correct password, to decrypt
42+
* Imports a keypair from a encrypted base64 text string. You need to pass the correct password, to decrypt
4343
* the private key stored in the text string.
4444
*
45-
* @param text PKCS8 fromated text with the private key encrypted.
45+
* @param text Encrpted base64 fromated text with the private key encrypted.
4646
* @param password Password to decrypt the private key.
4747
* @param publicKeyText Optional public key encoded in PEM format, if non provided, the public key
4848
* can be obtained from the private key.
@@ -57,7 +57,7 @@ export class KeyPair {
5757
}
5858

5959
/**
60-
* Imports a private key file. The key file is in the format as PKCS8 text. The private key is encrypted.
60+
* Imports a private key file. The key file is in the format as a encrpted base64 text. The private key is encrypted.
6161
*
6262
* @param filename Filename containing the encrypted private key.
6363
* @param password Password to decrypt the private key.
@@ -75,11 +75,11 @@ export class KeyPair {
7575
}
7676

7777
/**
78-
* Export the keypair to a PKCS8 fromatted text string. The private key is encrypted using the provided password.
78+
* Export the keypair to a encrypt base64 fromatted text string. The private key is encrypted using the provided password.
7979
*
8080
* @param password Password to encrypt the private key.
8181
*
82-
* @returns The encrpted private key as a PKCS8 formatted string.
82+
* @returns The encrpted private key as a encrypted base64 formatted string.
8383
*
8484
*/
8585
public exportToString(password: string): string {
@@ -88,7 +88,7 @@ export class KeyPair {
8888
}
8989

9090
/**
91-
* Same as `exportToText` this writes the exported tex to a file.
91+
* Same as `exportToText` this writes the exported text to a file.
9292
*
9393
* @param password Password to encrypt the private key.
9494
*

src/Utils.ts

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,7 @@ interface IWordArray {
1212
words: Uint32Array
1313
sigBytes: number
1414
}
15-
export function hexToBytes(hex: string): Uint8Array {
16-
if (typeof hex !== 'string') {
17-
throw new TypeError('hexToBytes: expected string, got ' + typeof hex)
18-
}
19-
if (hex.length % 2) throw new Error('hexToBytes: received invalid unpadded hex')
20-
const array = new Uint8Array(hex.length / 2)
21-
for (let i = 0; i < array.length; i++) {
22-
const j = i * 2
23-
const hexByte = hex.slice(j, j + 2)
24-
const byte = Number.parseInt(hexByte, 16)
25-
if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence')
26-
array[i] = byte
27-
}
28-
return array
29-
}
15+
3016

3117
/**
3218
* Return true if the number or string is an address value. This does not check the network for a valid
@@ -125,7 +111,7 @@ export function remove0xPrefix(value: string): string {
125111
export function toPublicKeyChecksum(publicKey: string): string {
126112
const publicKeyClean = remove0xPrefix(publicKey).toLowerCase()
127113
let result = '0x'
128-
const hashData = sha3_256(hexToBytes(publicKeyClean))
114+
const hashData = sha3_256(hexToByteArray(publicKeyClean))
129115
for (let index = 0; index < hashData.length && index < publicKeyClean.length; index++) {
130116
if (parseInt(hashData.charAt(index), 16) > 7) {
131117
result = result.concat(publicKeyClean.charAt(index).toUpperCase())
@@ -163,8 +149,33 @@ export function isPublicKeyChecksum(publicKey: string): boolean {
163149
return remove0xPrefix(publicKey) && remove0xPrefix(publicKey) == remove0xPrefix(toPublicKeyChecksum(publicKey))
164150
}
165151

152+
/**
153+
* Returns true if the string is a hex string
154+
*
155+
*/
156+
export function isHexSring(hex: string): boolean {
157+
return hex !== null && hex.match(/^[0-9a-f]+$/gi) !== null
158+
}
159+
160+
/**
161+
* Returns a Uint8Array of a hex string. The hex string must only contain
162+
* characters from 0 - 9 and a-f
163+
*/
164+
export function hexToByteArray(hex: string): Uint8Array {
165+
if ( !isHexSring(hex)) {
166+
throw TypeError(`the hex string ${hex} contains non hex characters`)
167+
}
168+
const pairs = hex.match(/[0-9a-f]{2}/ig)
169+
const values = pairs.map((p) => {
170+
return parseInt(p, 16)
171+
})
172+
return new Uint8Array(values)
173+
}
174+
175+
166176
/*
167177
* Code originally copied from crypto-js for conversion Latin1 to and from WordArray
178+
* but changed to return/input Uint8Array
168179
*
169180
*/
170181
export function wordArrayToByteArray(wordArray: IWordArray): Uint8Array {

test/unit/Utils.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
*/
66

7-
import { assert } from 'chai'
7+
import { assert, expect } from 'chai'
88
import { randomInt, randomBytes } from 'crypto'
99

1010
import { Account } from '../../src/Account'
@@ -13,6 +13,7 @@ import {
1313
isAddress,
1414
isPublicKey,
1515
isPublicKeyChecksum,
16+
hexToByteArray,
1617
prefix0x,
1718
remove0xPrefix,
1819
toAddress,
@@ -22,6 +23,12 @@ import {
2223
} from '../../src/Utils'
2324

2425
const PUBLIC_ADDRESS = '0x5288fec4153b702430771dfac8aed0b21cafca4344dae0d47b97f0bf532b3306'
26+
const PUBLIC_ADDRESS_BYTES = [
27+
0x52, 0x88, 0xFE, 0xC4, 0x15, 0x3B, 0x70, 0x24,
28+
0x30, 0x77, 0x1D, 0xFA, 0xC8, 0xAE, 0xD0, 0xB2,
29+
0x1C, 0xAF, 0xCA, 0x43, 0x44, 0xDA, 0xE0, 0xD4,
30+
0x7B, 0x97, 0xF0, 0xBF, 0x53, 0x2B, 0x33, 0x06
31+
]
2532
const PUBLIC_ADDRESS_CHECHKSUM = '0x5288Fec4153b702430771DFAC8AeD0B21CAFca4344daE0d47B97F0bf532b3306'
2633

2734

@@ -128,6 +135,18 @@ describe('Utils module', () => {
128135
})
129136
})
130137

138+
describe('hexToBytes', () => {
139+
it('should convert a hex string to Uint8Array', () => {
140+
expect(() => hexToByteArray(PUBLIC_ADDRESS)).to.throw(TypeError, /contains non hex characters/)
141+
142+
let result = hexToByteArray(remove0xPrefix(PUBLIC_ADDRESS))
143+
assert.equal(Uint8Array.from(PUBLIC_ADDRESS_BYTES).toString(), result.toString())
144+
145+
result = hexToByteArray(remove0xPrefix(PUBLIC_ADDRESS_CHECHKSUM))
146+
assert.equal(Uint8Array.from(PUBLIC_ADDRESS_BYTES).toString(), result.toString())
147+
148+
})
149+
})
131150
describe('Convert Uint8Array to and from WordArray for crypto-js', () => {
132151
it('should convert to word array', () => {
133152
const testLength = 64

0 commit comments

Comments
 (0)