@@ -28,6 +28,13 @@ func WithLogger(log func(msg string)) DecryptOption {
28
28
}
29
29
}
30
30
31
+ type EncryptionAlgorithm string
32
+
33
+ const (
34
+ EncryptionAlgorithmAES256CBC EncryptionAlgorithm = "http://www.w3.org/2001/04/xmlenc#aes256-cbc"
35
+ EncryptionAlgorithmFontObfuscation EncryptionAlgorithm = "http://www.idpf.org/2008/embedding"
36
+ )
37
+
31
38
// Decrypt reads an EPUB file encrypted with the Readium LCP DRM from in and
32
39
// outputs a regular EPUB file to out.
33
40
//
@@ -113,7 +120,7 @@ func Decrypt(out io.Writer, in io.ReaderAt, inSize int64, userKeyHex string, opt
113
120
}
114
121
115
122
if fileEntry , ok := encryptedFilesSet [f .Name ]; ok {
116
- err = decryptFile (dstFile , srcFile , contentKey , fileEntry .IsCompressed )
123
+ err = decryptFile (dstFile , srcFile , contentKey , fileEntry .EncryptionAlgorithm , fileEntry . IsCompressed )
117
124
} else {
118
125
_ , err = io .Copy (dstFile , srcFile )
119
126
}
@@ -137,8 +144,9 @@ func Decrypt(out io.Writer, in io.ReaderAt, inSize int64, userKeyHex string, opt
137
144
}
138
145
139
146
type FileEntry struct {
140
- Path string
141
- IsCompressed bool
147
+ Path string
148
+ IsCompressed bool
149
+ EncryptionAlgorithm EncryptionAlgorithm
142
150
}
143
151
144
152
func listEncryptedFiles (epubRoot fs.FS ) ([]FileEntry , error ) {
@@ -178,8 +186,12 @@ func listEncryptedFiles(epubRoot fs.FS) ([]FileEntry, error) {
178
186
for _ , d := range encryption .EncryptedData {
179
187
path := d .CipherData .CipherReference .URI
180
188
isCompressed := false
189
+ var encryptionAlgorithm EncryptionAlgorithm
181
190
182
- if d .EncryptionMethod .Algorithm != "http://www.w3.org/2001/04/xmlenc#aes256-cbc" {
191
+ switch d .EncryptionMethod .Algorithm {
192
+ case string (EncryptionAlgorithmAES256CBC ), string (EncryptionAlgorithmFontObfuscation ):
193
+ encryptionAlgorithm = EncryptionAlgorithm (d .EncryptionMethod .Algorithm )
194
+ default :
183
195
return nil , fmt .Errorf ("unsupported encryption algorithm for file %s: %s" , path , d .EncryptionMethod .Algorithm )
184
196
}
185
197
@@ -193,7 +205,11 @@ func listEncryptedFiles(epubRoot fs.FS) ([]FileEntry, error) {
193
205
}
194
206
}
195
207
196
- res = append (res , FileEntry {Path : path , IsCompressed : isCompressed })
208
+ res = append (res , FileEntry {
209
+ Path : path ,
210
+ IsCompressed : isCompressed ,
211
+ EncryptionAlgorithm : encryptionAlgorithm ,
212
+ })
197
213
}
198
214
199
215
return res , nil
@@ -236,7 +252,7 @@ func getContentKey(epubRoot fs.FS, userKey []byte) ([]byte, error) {
236
252
return nil , fmt .Errorf ("error decoding key check: %w" , err )
237
253
}
238
254
239
- keyCheck , err := decipher (encryptedKeyCheck , userKey )
255
+ keyCheck , err := decipherAES256CBC (encryptedKeyCheck , userKey )
240
256
if err != nil {
241
257
return nil , fmt .Errorf ("error decrypting key check: %w" , err )
242
258
}
@@ -250,15 +266,15 @@ func getContentKey(epubRoot fs.FS, userKey []byte) ([]byte, error) {
250
266
return nil , fmt .Errorf ("error decoding content key: %w" , err )
251
267
}
252
268
253
- contentKey , err := decipher (encryptedContentKey , userKey )
269
+ contentKey , err := decipherAES256CBC (encryptedContentKey , userKey )
254
270
if err != nil {
255
271
return nil , fmt .Errorf ("error decrypting content key: %w" , err )
256
272
}
257
273
258
274
return contentKey , nil
259
275
}
260
276
261
- func decipher (data , key []byte ) ([]byte , error ) {
277
+ func decipherAES256CBC (data , key []byte ) ([]byte , error ) {
262
278
block , err := aes .NewCipher (key )
263
279
if err != nil {
264
280
return nil , fmt .Errorf ("error creating cipher: %w" , err )
@@ -283,13 +299,30 @@ func decipher(data, key []byte) ([]byte, error) {
283
299
return res , nil
284
300
}
285
301
286
- func decryptFile (dst io.Writer , src io.Reader , contentKey []byte , isCompressed bool ) error {
302
+ func decipherFontObfuscation (data , key []byte ) ([]byte , error ) {
303
+ // Let's assume readers know how to deal with this algorithm... Worst case,
304
+ // let's hope they fallback to any font.
305
+ return data , nil
306
+ }
307
+
308
+ func decryptFile (dst io.Writer , src io.Reader , contentKey []byte , encryptionAlgorithm EncryptionAlgorithm , isCompressed bool ) error {
287
309
encryptedData , err := io .ReadAll (src )
288
310
if err != nil {
289
311
return fmt .Errorf ("error reading data: %w" , err )
290
312
}
291
313
292
- data , err := decipher (encryptedData , contentKey )
314
+ var decipherFunc func (data []byte , key []byte ) (res []byte , err error )
315
+
316
+ switch encryptionAlgorithm {
317
+ case EncryptionAlgorithmAES256CBC :
318
+ decipherFunc = decipherAES256CBC
319
+ case EncryptionAlgorithmFontObfuscation :
320
+ decipherFunc = decipherFontObfuscation
321
+ default :
322
+ return fmt .Errorf ("invalid encryption algorithm: %s" , encryptionAlgorithm )
323
+ }
324
+
325
+ data , err := decipherFunc (encryptedData , contentKey )
293
326
if err != nil {
294
327
return fmt .Errorf ("error decrypting data: %w" , err )
295
328
}
0 commit comments