@@ -19,11 +19,13 @@ package rsa
19
19
import (
20
20
"crypto/rand"
21
21
"crypto/rsa"
22
+ "crypto/sha1"
23
+ "crypto/sha256"
24
+ "crypto/sha512"
22
25
"crypto/x509"
23
26
"encoding/base64"
24
- "errors"
25
27
"fmt"
26
- "io "
28
+ "hash "
27
29
"math/big"
28
30
29
31
"github.com/armortal/webcrypto-go"
@@ -123,7 +125,7 @@ func (c *CryptoKeyPair) PrivateKey() webcrypto.CryptoKey {
123
125
124
126
type CryptoKey struct {
125
127
isPrivate bool
126
- pub rsa.PublicKey
128
+ pub * rsa.PublicKey
127
129
priv * rsa.PrivateKey
128
130
alg * KeyAlgorithm
129
131
ext bool
@@ -149,8 +151,39 @@ func (c *CryptoKey) Usages() []webcrypto.KeyUsage {
149
151
return c .usages
150
152
}
151
153
152
- func (a * SubtleCrypto ) Decrypt (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , data io.Reader ) (any , error ) {
153
- return nil , errors .New ("unimplemented" )
154
+ func (a * SubtleCrypto ) Decrypt (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , data []byte ) ([]byte , error ) {
155
+ alg , err := getAlgorithm (algorithm )
156
+ if err != nil {
157
+ return nil , err
158
+ }
159
+ if alg .Name != rsaOaep {
160
+ return nil , webcrypto .NewError (webcrypto .ErrNotSupportedError , "encrypt not supported" )
161
+ }
162
+
163
+ k , ok := key .(* CryptoKey )
164
+ if ! ok {
165
+ return nil , webcrypto .NewError (webcrypto .ErrDataError , "key must be *rsa.CryptoKey" )
166
+ }
167
+
168
+ if ! k .isPrivate {
169
+ return nil , webcrypto .NewError (webcrypto .ErrInvalidAccessError , "key must be private" )
170
+ }
171
+
172
+ hash , err := getHash (k .alg .Hash )
173
+ if err != nil {
174
+ return nil , err
175
+ }
176
+ label := make ([]byte , 0 )
177
+ if alg .OaepParams != nil {
178
+ label = alg .OaepParams .Label
179
+ }
180
+
181
+ msg , err := rsa .DecryptOAEP (hash , rand .Reader , k .priv , data , label )
182
+ if err != nil {
183
+ return nil , webcrypto .NewError (webcrypto .ErrOperationError , err .Error ())
184
+ }
185
+
186
+ return msg , nil
154
187
}
155
188
156
189
func (a * SubtleCrypto ) DeriveBits (algorithm webcrypto.Algorithm , baseKey webcrypto.CryptoKey , length uint64 ) ([]byte , error ) {
@@ -161,12 +194,44 @@ func (a *SubtleCrypto) DeriveKey(algorithm webcrypto.Algorithm, baseKey webcrypt
161
194
return nil , webcrypto .ErrMethodNotSupported ()
162
195
}
163
196
164
- func (a * SubtleCrypto ) Digest (algorithm webcrypto.Algorithm , data io. Reader ) ([]byte , error ) {
197
+ func (a * SubtleCrypto ) Digest (algorithm webcrypto.Algorithm , data [] byte ) ([]byte , error ) {
165
198
return nil , webcrypto .ErrMethodNotSupported ()
166
199
}
167
200
168
- func (a * SubtleCrypto ) Encrypt (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , data io.Reader ) (any , error ) {
169
- return nil , errors .New ("unimplemented" )
201
+ func (a * SubtleCrypto ) Encrypt (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , data []byte ) ([]byte , error ) {
202
+ alg , err := getAlgorithm (algorithm )
203
+ if err != nil {
204
+ return nil , err
205
+ }
206
+ if alg .Name != rsaOaep {
207
+ return nil , webcrypto .NewError (webcrypto .ErrNotSupportedError , "encrypt not supported" )
208
+ }
209
+
210
+ k , ok := key .(* CryptoKey )
211
+ if ! ok {
212
+ return nil , webcrypto .NewError (webcrypto .ErrDataError , "key must be *rsa.CryptoKey" )
213
+ }
214
+
215
+ if k .isPrivate {
216
+ return nil , webcrypto .NewError (webcrypto .ErrInvalidAccessError , "key must be public" )
217
+ }
218
+
219
+ hash , err := getHash (k .alg .Hash )
220
+ if err != nil {
221
+ return nil , err
222
+ }
223
+
224
+ label := make ([]byte , 0 )
225
+ if alg .OaepParams != nil {
226
+ label = alg .OaepParams .Label
227
+ }
228
+
229
+ b , err := rsa .EncryptOAEP (hash , rand .Reader , k .pub , data , label )
230
+ if err != nil {
231
+ return nil , webcrypto .NewError (webcrypto .ErrOperationError , err .Error ())
232
+ }
233
+
234
+ return b , nil
170
235
}
171
236
172
237
func (a * SubtleCrypto ) ExportKey (format webcrypto.KeyFormat , key webcrypto.CryptoKey ) (any , error ) {
@@ -292,7 +357,7 @@ func (a *SubtleCrypto) generateKeyOaep(algorithm *HashedKeyGenParams, extractabl
292
357
293
358
// Create the CryptoKey object for the public key
294
359
pub := & CryptoKey {
295
- pub : key .PublicKey ,
360
+ pub : & key .PublicKey ,
296
361
alg : alg ,
297
362
ext : true ,
298
363
usages : util .UsageIntersection ([]webcrypto.KeyUsage {webcrypto .Encrypt , webcrypto .WrapKey }, keyUsages ),
@@ -477,7 +542,7 @@ func (a *SubtleCrypto) importKeyJwk(keyData *webcrypto.JsonWebKey, algorithm *Al
477
542
pub .E = int (big .NewInt (0 ).SetBytes (e ).Int64 ())
478
543
ck .alg .ModulusLength = uint64 (pub .N .BitLen ())
479
544
ck .alg .PublicExponent = * big .NewInt (int64 (pub .E ))
480
- ck .pub = pub
545
+ ck .pub = & pub
481
546
482
547
// Extract private data if it exists
483
548
if keyData .D != "" {
@@ -536,7 +601,7 @@ func (a *SubtleCrypto) importKeyJwk(keyData *webcrypto.JsonWebKey, algorithm *Al
536
601
return ck , nil
537
602
}
538
603
539
- func (a * SubtleCrypto ) Sign (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , data io. Reader ) ([]byte , error ) {
604
+ func (a * SubtleCrypto ) Sign (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , data [] byte ) ([]byte , error ) {
540
605
return nil , webcrypto .ErrMethodNotSupported ()
541
606
}
542
607
@@ -550,10 +615,33 @@ func (a *SubtleCrypto) UnwrapKey(format webcrypto.KeyFormat,
550
615
return nil , webcrypto .ErrMethodNotSupported ()
551
616
}
552
617
553
- func (a * SubtleCrypto ) Verify (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , signature []byte , data io. Reader ) (bool , error ) {
618
+ func (a * SubtleCrypto ) Verify (algorithm webcrypto.Algorithm , key webcrypto.CryptoKey , signature []byte , data [] byte ) (bool , error ) {
554
619
return false , webcrypto .ErrMethodNotSupported ()
555
620
}
556
621
557
622
func (a * SubtleCrypto ) WrapKey (format webcrypto.KeyFormat , key webcrypto.CryptoKey , wrappingKey webcrypto.CryptoKey , wrapAlgorithm webcrypto.Algorithm ) (any , error ) {
558
623
return nil , webcrypto .ErrMethodNotSupported ()
559
624
}
625
+
626
+ func getAlgorithm (algorithm webcrypto.Algorithm ) (* Algorithm , error ) {
627
+ alg , ok := algorithm .(* Algorithm )
628
+ if ! ok {
629
+ return nil , webcrypto .NewError (webcrypto .ErrDataError , "algorithm must be *rsa.Algorithm" )
630
+ }
631
+ return alg , nil
632
+ }
633
+
634
+ func getHash (hash string ) (hash.Hash , error ) {
635
+ switch hash {
636
+ case "SHA-1" :
637
+ return sha1 .New (), nil
638
+ case "SHA-256" :
639
+ return sha256 .New (), nil
640
+ case "SHA-384" :
641
+ return sha512 .New384 (), nil
642
+ case "SHA-512" :
643
+ return sha512 .New (), nil
644
+ default :
645
+ return nil , webcrypto .NewError (webcrypto .ErrNotSupportedError , fmt .Sprintf ("hash %s not supported" , hash ))
646
+ }
647
+ }
0 commit comments