@@ -5,16 +5,18 @@ import Worker from 'worker-loader!./worker';
55
66/* eslint-disable no-use-before-define */
77
8- export async function socketConnect ( channelId , sessionId , pluginPublicKey , callbacks ) {
8+ export async function socketConnect ( protocolVersion , channelId , sessionId , pluginPublicKey , callbacks ) {
9+ const cryptoHelper = new CryptoHelper ( protocolVersion ) ;
10+
911 // generate public/private keypair for the editor
10- const keys = await loadKeys ( ) || await generateKeys ( ) ;
12+ const keys = await cryptoHelper . loadKeys ( ) || await cryptoHelper . generateKeys ( ) ;
1113
1214 // decode and import the plugin public key
13- const pluginKey = await importKey ( 'spki' , pluginPublicKey , [ 'verify' ] ) ;
15+ const pluginKey = await cryptoHelper . importKey ( 'spki' , pluginPublicKey , [ 'verify' ] ) ;
1416
1517 const { userAgent } = window . navigator ;
1618 const socket = wrap ( new Worker ( ) ) ;
17- await socket . socketConnect ( channelId , sessionId , keys , pluginKey , userAgent , proxy ( {
19+ await socket . socketConnect ( channelId , sessionId , cryptoHelper . signVerifyAlgorithm , keys , pluginKey , userAgent , proxy ( {
1820 connect : proxy ( ( ) => {
1921 callbacks . connect ( { socket } ) ;
2022 } ) ,
@@ -34,53 +36,85 @@ export async function socketConnect(channelId, sessionId, pluginPublicKey, callb
3436 return socket ;
3537}
3638
37- async function loadKeys ( ) {
38- const encodedPublicKey = localStorage . getItem ( 'editor-public-key' ) ;
39- const encodedPrivateKey = localStorage . getItem ( 'editor-private-key' ) ;
39+ class CryptoHelper {
40+ constructor ( protocolVersion ) {
41+ if ( protocolVersion === 1 ) {
42+ this . publicKeyVariable = 'editor-public-key'
43+ this . privateKeyVariable = 'editor-private-key'
44+ this . importAlgorithm = {
45+ name : 'RSASSA-PKCS1-v1_5' ,
46+ hash : 'SHA-256' ,
47+ }
48+ this . generateAlgorithm = {
49+ name : 'RSASSA-PKCS1-v1_5' ,
50+ hash : 'SHA-256' ,
51+ modulusLength : 4096 ,
52+ publicExponent : new Uint8Array ( [ 1 , 0 , 1 ] ) ,
53+ }
54+ this . signVerifyAlgorithm = {
55+ name : 'RSASSA-PKCS1-v1_5' ,
56+ }
57+
58+ } else if ( protocolVersion === 2 ) {
59+ this . publicKeyVariable = 'editor-public-key-v2'
60+ this . privateKeyVariable = 'editor-private-key-v2'
61+ this . importAlgorithm = {
62+ name : 'ECDSA' ,
63+ namedCurve : 'P-256' ,
64+ }
65+ this . generateAlgorithm = {
66+ name : 'ECDSA' ,
67+ namedCurve : 'P-256' ,
68+ }
69+ this . signVerifyAlgorithm = {
70+ name : 'ECDSA' ,
71+ hash : 'SHA-256' ,
72+ }
73+ } else {
74+ throw new Error ( `Unsupported protocol version: ${ protocolVersion } ` ) ;
75+ }
76+ }
77+
78+ async loadKeys ( ) {
79+ const encodedPublicKey = localStorage . getItem ( this . publicKeyVariable ) ;
80+ const encodedPrivateKey = localStorage . getItem ( this . privateKeyVariable ) ;
81+
82+ if ( encodedPublicKey && encodedPrivateKey ) {
83+ const publicKey = await this . importKey ( 'spki' , encodedPublicKey , [ ] ) ;
84+ const privateKey = await this . importKey ( 'pkcs8' , encodedPrivateKey , [ 'sign' ] ) ;
85+ return {
86+ publicKey,
87+ privateKey,
88+ encodedPublicKey,
89+ encodedPrivateKey,
90+ } ;
91+ }
92+
93+ return null ;
94+ }
95+
96+ importKey ( format , encoded , keyUsages ) {
97+ return crypto . subtle . importKey ( format , decode ( encoded ) , this . importAlgorithm , false , keyUsages ) ;
98+ }
99+
100+ async exportKey ( format , key , storageKey ) {
101+ const exported = await crypto . subtle . exportKey ( format , key ) ;
102+ const encoded = encode ( exported ) ;
103+ localStorage . setItem ( storageKey , encoded ) ;
104+ return encoded ;
105+ }
106+
107+ async generateKeys ( ) {
108+ const { publicKey, privateKey } = await crypto . subtle . generateKey ( this . generateAlgorithm , true , [ 'sign' ] ) ;
109+
110+ const encodedPublicKey = await this . exportKey ( 'spki' , publicKey , this . publicKeyVariable ) ;
111+ const encodedPrivateKey = await this . exportKey ( 'pkcs8' , privateKey , this . privateKeyVariable ) ;
40112
41- if ( encodedPublicKey && encodedPrivateKey ) {
42- const publicKey = await importKey ( 'spki' , encodedPublicKey , [ ] ) ;
43- const privateKey = await importKey ( 'pkcs8' , encodedPrivateKey , [ 'sign' ] ) ;
44113 return {
45114 publicKey,
46115 privateKey,
47116 encodedPublicKey,
48117 encodedPrivateKey,
49118 } ;
50119 }
51-
52- return null ;
53- }
54-
55- function importKey ( format , encoded , keyUsages ) {
56- return crypto . subtle . importKey ( format , decode ( encoded ) , {
57- name : 'RSASSA-PKCS1-v1_5' ,
58- hash : 'SHA-256' ,
59- } , false , keyUsages ) ;
60- }
61-
62- async function exportKey ( format , key , storageKey ) {
63- const exported = await crypto . subtle . exportKey ( format , key ) ;
64- const encoded = encode ( exported ) ;
65- localStorage . setItem ( storageKey , encoded ) ;
66- return encoded ;
67- }
68-
69- async function generateKeys ( ) {
70- const { publicKey, privateKey } = await crypto . subtle . generateKey ( {
71- name : 'RSASSA-PKCS1-v1_5' ,
72- modulusLength : 4096 ,
73- publicExponent : new Uint8Array ( [ 1 , 0 , 1 ] ) ,
74- hash : 'SHA-256' ,
75- } , true , [ 'sign' ] ) ;
76-
77- const encodedPublicKey = await exportKey ( 'spki' , publicKey , 'editor-public-key' ) ;
78- const encodedPrivateKey = await exportKey ( 'pkcs8' , privateKey , 'editor-private-key' ) ;
79-
80- return {
81- publicKey,
82- privateKey,
83- encodedPublicKey,
84- encodedPrivateKey,
85- } ;
86120}
0 commit comments