2021-01-11 12:13:41 -05:00
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
2020-09-05 20:34:02 -04:00
2021-06-06 06:57:10 -04:00
use deno_core ::error ::null_opbuf ;
2020-09-14 12:48:57 -04:00
use deno_core ::error ::AnyError ;
2021-04-28 12:41:50 -04:00
use deno_core ::include_js_files ;
2021-06-06 06:57:10 -04:00
use deno_core ::op_async ;
2021-04-28 12:41:50 -04:00
use deno_core ::op_sync ;
use deno_core ::Extension ;
2020-09-10 09:57:45 -04:00
use deno_core ::OpState ;
2020-04-23 05:51:07 -04:00
use deno_core ::ZeroCopyBuf ;
2020-09-18 14:39:47 -04:00
use rand ::rngs ::StdRng ;
2019-08-14 11:03:02 -04:00
use rand ::thread_rng ;
use rand ::Rng ;
2021-04-28 12:41:50 -04:00
use rand ::SeedableRng ;
2021-06-06 06:57:10 -04:00
use ring ::digest ;
use std ::cell ::RefCell ;
2021-02-26 12:06:26 -05:00
use std ::path ::PathBuf ;
2021-06-06 06:57:10 -04:00
use std ::rc ::Rc ;
2019-08-14 11:03:02 -04:00
2020-11-13 16:01:57 -05:00
pub use rand ; // Re-export rand
2021-04-28 12:41:50 -04:00
pub fn init ( maybe_seed : Option < u64 > ) -> Extension {
2021-04-28 18:16:45 -04:00
Extension ::builder ( )
. js ( include_js_files! (
2021-04-30 15:51:48 -04:00
prefix " deno:extensions/crypto " ,
2021-06-06 06:57:10 -04:00
" 00_webidl.js " ,
2021-04-28 12:41:50 -04:00
" 01_crypto.js " ,
2021-04-28 18:16:45 -04:00
) )
2021-06-05 08:46:24 -04:00
. ops ( vec! [
(
" op_crypto_get_random_values " ,
op_sync ( op_crypto_get_random_values ) ,
) ,
2021-06-06 06:57:10 -04:00
( " op_crypto_subtle_digest " , op_async ( op_crypto_subtle_digest ) ) ,
2021-06-05 08:46:24 -04:00
( " op_crypto_random_uuid " , op_sync ( op_crypto_random_uuid ) ) ,
] )
2021-04-28 18:16:45 -04:00
. state ( move | state | {
2021-04-28 12:41:50 -04:00
if let Some ( seed ) = maybe_seed {
state . put ( StdRng ::seed_from_u64 ( seed ) ) ;
}
Ok ( ( ) )
2021-04-28 18:16:45 -04:00
} )
. build ( )
2019-10-11 14:41:54 -04:00
}
2021-01-14 19:24:38 -05:00
pub fn op_crypto_get_random_values (
2020-09-10 09:57:45 -04:00
state : & mut OpState ,
2021-06-05 13:30:20 -04:00
mut zero_copy : ZeroCopyBuf ,
_ : ( ) ,
2021-04-05 12:40:24 -04:00
) -> Result < ( ) , AnyError > {
2021-06-05 13:30:20 -04:00
if zero_copy . len ( ) > 65536 {
return Err (
deno_web ::DomExceptionQuotaExceededError ::new ( & format! ( " The ArrayBufferView's byte length ( {} ) exceeds the number of bytes of entropy available via this API (65536) " , zero_copy . len ( ) ) )
. into ( ) ,
) ;
}
2020-09-18 14:39:47 -04:00
let maybe_seeded_rng = state . try_borrow_mut ::< StdRng > ( ) ;
if let Some ( seeded_rng ) = maybe_seeded_rng {
2021-04-02 09:47:57 -04:00
seeded_rng . fill ( & mut * zero_copy ) ;
2019-08-14 11:03:02 -04:00
} else {
let mut rng = thread_rng ( ) ;
2021-04-02 09:47:57 -04:00
rng . fill ( & mut * zero_copy ) ;
2019-08-14 11:03:02 -04:00
}
2021-04-05 12:40:24 -04:00
Ok ( ( ) )
2019-08-14 11:03:02 -04:00
}
2021-02-26 12:06:26 -05:00
2021-06-05 08:46:24 -04:00
pub fn op_crypto_random_uuid (
state : & mut OpState ,
2021-06-05 13:30:20 -04:00
_ : ( ) ,
_ : ( ) ,
2021-06-05 08:46:24 -04:00
) -> Result < String , AnyError > {
let maybe_seeded_rng = state . try_borrow_mut ::< StdRng > ( ) ;
let uuid = if let Some ( seeded_rng ) = maybe_seeded_rng {
let mut bytes = [ 0 u8 ; 16 ] ;
seeded_rng . fill ( & mut bytes ) ;
uuid ::Builder ::from_bytes ( bytes )
. set_version ( uuid ::Version ::Random )
. build ( )
} else {
uuid ::Uuid ::new_v4 ( )
} ;
Ok ( uuid . to_string ( ) )
}
2021-06-06 06:57:10 -04:00
pub async fn op_crypto_subtle_digest (
_state : Rc < RefCell < OpState > > ,
algorithm_id : i8 ,
data : Option < ZeroCopyBuf > ,
) -> Result < ZeroCopyBuf , AnyError > {
let algorithm = match algorithm_id {
0 = > & digest ::SHA1_FOR_LEGACY_USE_ONLY ,
1 = > & digest ::SHA256 ,
2 = > & digest ::SHA384 ,
3 = > & digest ::SHA512 ,
_ = > panic! ( " Invalid algorithm id " ) ,
} ;
let input = data . ok_or_else ( null_opbuf ) ? ;
let output = tokio ::task ::spawn_blocking ( move | | {
digest ::digest ( algorithm , & input ) . as_ref ( ) . to_vec ( ) . into ( )
} )
. await ? ;
Ok ( output )
}
2021-02-26 12:06:26 -05:00
pub fn get_declaration ( ) -> PathBuf {
PathBuf ::from ( env! ( " CARGO_MANIFEST_DIR " ) ) . join ( " lib.deno_crypto.d.ts " )
}