-
-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
$mol_crypto_key - new async crypto api, more sync
- Loading branch information
jin
committed
Nov 19, 2023
1 parent
daa39c1
commit af8de22
Showing
2 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
namespace $ { | ||
|
||
const algorithm = { | ||
name: 'ECDSA', | ||
hash: 'SHA-256', | ||
namedCurve: "P-256", | ||
} | ||
|
||
export class $mol_crypto_key extends $mol_buffer { | ||
|
||
static from< This extends typeof $mol_crypto_key >( this: This, serial: string | Uint8Array ) { | ||
|
||
if( typeof serial === 'string' ) { | ||
serial = new Uint8Array([ | ||
... $mol_base64_decode_safe( serial.slice( 0, 43 ) ), | ||
... $mol_base64_decode_safe( serial.slice( 43, 86 ) ), | ||
... $mol_base64_decode_safe( serial.slice( 86, 129 ) ), | ||
]) | ||
} | ||
|
||
return new this( serial.buffer, serial.byteOffset, serial.byteLength ) as InstanceType< This > | ||
} | ||
|
||
asArray() { | ||
return new Uint8Array( this.buffer, this.byteOffset, this.byteLength ) | ||
} | ||
|
||
@ $mol_memo.method | ||
toString() { | ||
const arr = this.asArray() | ||
return $mol_base64_encode_safe( arr.subarray( 0, 32 ) ) | ||
+ $mol_base64_encode_safe( arr.subarray( 32, 64 ) ) | ||
+ $mol_base64_encode_safe( arr.subarray( 64 ) ) | ||
} | ||
|
||
} | ||
|
||
export class $mol_crypto_key_public extends $mol_crypto_key { | ||
|
||
static size_str = 86 | ||
static size_bin = 64 | ||
|
||
@ $mol_memo.method | ||
async native() { | ||
const str = this.toString() | ||
return $mol_crypto_native.subtle.importKey( | ||
'jwk', | ||
{ | ||
crv: "P-256", | ||
ext: true, | ||
key_ops: [ 'verify' ], | ||
kty: "EC", | ||
x: str.slice( 0, 43 ), | ||
y: str.slice( 43, 86 ), | ||
}, | ||
algorithm, | ||
true, | ||
[ 'verify' ], | ||
) | ||
} | ||
|
||
async verify( data: BufferSource, sign: BufferSource ) { | ||
return await $mol_crypto_native.subtle.verify( | ||
algorithm, | ||
await this.native(), | ||
sign, | ||
data, | ||
) | ||
} | ||
|
||
} | ||
|
||
export class $mol_crypto_key_private extends $mol_crypto_key { | ||
|
||
static size_str = 129 | ||
static size_bin = 96 | ||
static size_sign = 64 | ||
|
||
static async generate() { | ||
|
||
const pair = await $mol_crypto_native.subtle.generateKey( | ||
algorithm, | ||
true, | ||
[ 'sign', 'verify' ] | ||
) | ||
|
||
const { x, y, d } = await $mol_crypto_native.subtle.exportKey( 'jwk', pair.privateKey ) | ||
return $mol_crypto_key_private.from( x + y! + d! ) | ||
|
||
} | ||
|
||
@ $mol_memo.method | ||
async native() { | ||
const str = this.toString() | ||
return await $mol_crypto_native.subtle.importKey( | ||
'jwk', | ||
{ | ||
crv: "P-256", | ||
ext: true, | ||
key_ops: [ 'sign' ], | ||
kty: "EC", | ||
x: str.slice( 0, 43 ), | ||
y: str.slice( 43, 86 ), | ||
d: str.slice( 86, 129 ), | ||
}, | ||
algorithm, | ||
true, | ||
[ 'sign' ], | ||
) | ||
} | ||
|
||
@ $mol_memo.method | ||
public() { | ||
return new $mol_crypto_key_public( this.buffer, this.byteOffset, this.byteOffset + 64 ) | ||
} | ||
|
||
async sign( data: BufferSource ) { | ||
return await $mol_crypto_native.subtle.sign( | ||
algorithm, | ||
await this.native(), | ||
data | ||
) | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
namespace $ { | ||
$mol_test({ | ||
|
||
async 'str sizes'() { | ||
|
||
const key_private = await $$.$mol_crypto_key_private.generate() | ||
const key_public = key_private.public() | ||
|
||
$mol_assert_equal( key_private.toString().length, $mol_crypto_key_private.size_str ) | ||
$mol_assert_equal( key_public.toString().length, $mol_crypto_key_public.size_str ) | ||
|
||
$mol_assert_equal( key_private.asArray().length, $mol_crypto_key_private.size_bin ) | ||
$mol_assert_equal( key_public.asArray().length, $mol_crypto_key_public.size_bin ) | ||
|
||
const data = new Uint8Array([ 1, 2, 3 ]) | ||
const sign = await key_private.sign( data ) | ||
$mol_assert_equal( sign.byteLength, $mol_crypto_key_private.size_sign ) | ||
|
||
}, | ||
|
||
async 'verify self signed with auto generated key'() { | ||
|
||
const Alice = await $$.$mol_crypto_key_private.generate() | ||
const data = new Uint8Array([ 1, 2, 3 ]) | ||
const sign = await Alice.sign( data ) | ||
|
||
$mol_assert_ok( await Alice.public().verify( data, sign ) ) | ||
|
||
}, | ||
|
||
async 'verify signed with str exported auto generated key'() { | ||
|
||
const Alice = await $$.$mol_crypto_key_private.generate() | ||
const data = new Uint8Array([ 1, 2, 3 ]) | ||
|
||
const Bella = $mol_crypto_key_private.from( Alice.toString() ) | ||
const sign = await Bella.sign( data ) | ||
|
||
const Catie = $mol_crypto_key_public.from( Alice.public().toString() ) | ||
$mol_assert_ok( await Catie.verify( data, sign ) ) | ||
|
||
const Diana = $mol_crypto_key_public.from( Alice.toString() ) | ||
$mol_assert_ok( await Diana.verify( data, sign ) ) | ||
|
||
}, | ||
|
||
async 'verify signed with bin exported auto generated key'() { | ||
|
||
const Alice = await $$.$mol_crypto_key_private.generate() | ||
const data = new Uint8Array([ 1, 2, 3 ]) | ||
|
||
const Bella = $mol_crypto_key_private.from( Alice.asArray() ) | ||
const sign = await Bella.sign( data ) | ||
|
||
const Catie = $mol_crypto_key_public.from( Alice.public().asArray() ) | ||
$mol_assert_ok( await Catie.verify( data, sign ) ) | ||
|
||
const Diana = $mol_crypto_key_public.from( Alice.asArray() ) | ||
$mol_assert_ok( await Diana.verify( data, sign ) ) | ||
|
||
}, | ||
|
||
}) | ||
} |