- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个电子阅读器应用程序(使用 skyepub ),它基本上将加密的书籍下载到文件系统中(并将解密 key 保存在数据库中),当用户尝试阅读它时,它会加载将书存入内存并解密。
问题是有些书的第一章被截断(epub 书实际上是 zip 文件,每一章都是一个单独的文件)..这会导致这个可怕的错误:
this XML file does not appear to have any style information associated with it. The document tree is shown below
我已经验证加密的书是否已正确下载,b/c如果我将文件复制到我的桌面(从我的root android)并在其上运行以下命令:
openssl aes-192-cbc -d -K *** -iv *** -in test.epub.encrypted -out test.epub
它工作得很好。但是,如果我几乎尝试对以下 android 代码执行相同的操作
public ContentData getContentData(String baseDirectory, String contentPath) {
if( contentPath.startsWith("/fonts/")) {
... // handle font suff
}
int secondSlash = contentPath.indexOf('/', 1);
if( secondSlash == -1) return null;
String bookEditionID = contentPath.substring(1,secondSlash);
String zipEntryName = contentPath.substring(secondSlash+1);
final ContentData data = new ContentData();
try {
InputStream stream = dbUtil.getBookStream(bookEditionID);
if( stream == null) return null;
final ZipInputStream zip = new ZipInputStream(stream);
ZipEntry entry;
do {
entry = zip.getNextEntry();
Log.e("Abjjad","looping through entry: "+entry);
if( entry == null) {
zip.close();
return null;
}
} while( !entry.getName().equals(zipEntryName));
Log.e("debug","going through data with entry: " +entry+", contentLength: "+entry.getSize());
查看方法dbUtil.getBookStream
:
public InputStream getBookStream( String bookEditionId) {
BookInfo book = getBookInfo(bookEditionId);
InputStream origStream = null;
try {
// Open the downloaded ePub
origStream = openFileInput(bookEditionId + ".epub");
// De-obfuscate the key
SecretKeySpec sks = getObfuscationKeySpec(bookEditionId);
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
c.init(Cipher.DECRYPT_MODE, sks);
byte[] decodedBytes = c.doFinal(Base64.decode(book.decryptionKey, Base64.DEFAULT));
String keyPair = new String(decodedBytes);
// Split the key and parse into binary
int separator = keyPair.indexOf(':');
byte[] key = DatatypeConverter.parseHexBinary(keyPair.substring(0, separator));
byte[] iv = DatatypeConverter.parseHexBinary(keyPair.substring(separator + 1));
c = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key,"AES"), new IvParameterSpec(iv));
return new CipherInputStream(origStream, c);
} catch( Exception e) {
try {
if (origStream != null) origStream.close();
} catch( Exception x) {}
return null;
}
}
然后entry.getSize()的日志在第一个代码块中返回-1
。
我们在 iOS 中编写了相同的代码,并且它运行完美(在同一本书上):
+ (NSData *)encryptKey:(NSString *)key ivParam:(NSString *)iv bookId:(NSString *)bookId
{
NSString *keyPair = [NSString stringWithFormat:@"%@:%@", key, iv];
NSString *secret = [self getObfuscationSecretWithValue:bookId];
NSData *data = [keyPair dataUsingEncoding:NSASCIIStringEncoding];
char keyPtr[kCCKeySizeAES128];
bzero(keyPtr, sizeof(keyPtr));
[[NSData dataWithHexString:secret] getBytes:keyPtr length:sizeof(keyPtr)];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted;
CCCryptorStatus status = CCCrypt(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCKeySizeAES128,
NULL,
[data bytes], [data length],
buffer, bufferSize, &numBytesEncrypted);
if (status == kCCSuccess) {
return [NSData dataWithBytes:buffer length:numBytesEncrypted];
}
else {
free(buffer);
return nil;
}
}
我注意到这种截断仅在阅读目录后才会发生(这似乎是上面的最后一章?)..来自日志:
:::::::::::::::::::::::::::::::
getInputStream: /24748681/OEBPS/toc.ncx
:::::::::::::::::::::::::::::::
looping through entry: mimetype
looping through entry: OEBPS/hayat-ghayr.html
looping through entry: OEBPS/content.opf
looping through entry: OEBPS/images/978-614-425-313-7-hayat-ghayr-cover.png
looping through entry: OEBPS/images/978-614-425-313-7-hayat_fmt.png
looping through entry: OEBPS/template.css
looping through entry: OEBPS/hayat-ghayr-2.html
looping through entry: OEBPS/hayat-ghayr-1.html
looping through entry: OEBPS/hayat-ghayr-3.html
looping through entry: OEBPS/hayat-ghayr-4.html
looping through entry: OEBPS/hayat-ghayr-5.html
looping through entry: OEBPS/hayat-ghayr-6.html
looping through entry: OEBPS/hayat-ghayr-7.html
looping through entry: OEBPS/hayat-ghayr-8.html
looping through entry: OEBPS/hayat-ghayr-9.html
looping through entry: OEBPS/hayat-ghayr-10.html
looping through entry: OEBPS/hayat-ghayr-11.html
looping through entry: OEBPS/hayat-ghayr-12.html
looping through entry: OEBPS/hayat-ghayr-13.html
looping through entry: OEBPS/hayat-ghayr-14.html
looping through entry: OEBPS/hayat-ghayr-15.html
looping through entry: OEBPS/hayat-ghayr-16.html
looping through entry: OEBPS/hayat-ghayr-17.html
looping through entry: OEBPS/hayat-ghayr-18.html
looping through entry: OEBPS/hayat-ghayr-19.html
looping through entry: OEBPS/hayat-ghayr-20.html
looping through entry: OEBPS/hayat-ghayr-21.html
looping through entry: OEBPS/hayat-ghayr-22.html
looping through entry: META-INF/container.xml
looping through entry: OEBPS/images/277.png
looping through entry: OEBPS/toc.ncx
going through data with entry: OEBPS/toc.ncx, contentLength: 5549
returning data
:::::::::::::::::::::::::::::::
getInputStream: /24748681/OEBPS/hayat-ghayr.html
:::::::::::::::::::::::::::::::
looping through entry: mimetype
looping through entry: OEBPS/hayat-ghayr.html
going through data with entry: OEBPS/hayat-ghayr.html, contentLength: -1
returning data
最佳答案
根据the docs ,如果大小未知,getSize() 可能返回 -1。这肯定会发生在某些 zip 文件中。在这些情况下,您需要阅读整个条目才能确定其未压缩的大小。
首先,整个加密解密的事情是一个转移注意力的事情。只需复制相同 epub/zip 文件并使用相同的代码读取它就会得到相同的页面。所以这是一个zip 文件本身有问题,而不是它的解密问题
正如 java 文档中提到的,如果内容未知(这正是这里发生的情况),读取 zip 文件实际上可以返回 -1。事实上,我们得到了相同的结果 em> zip 文件,解压缩它(在命令行上),然后使用增加的压缩级别重新压缩它,如下所示:
zip -9 -r filename.epub *
然后我们将相同的 zip 文件提供给现有代码,它运行得很好!
这是最终有效的代码:
try {
InputStream stream = abjjadDb.getBookStream(bookEditionID);
if( stream == null) return null;
final ZipInputStream zip = new ZipInputStream(stream);
ZipEntry entry;
do {
entry = zip.getNextEntry();
if( entry == null) {
zip.close();
return null;
}
} while( !entry.getName().equals(zipEntryName));
data.contentLength = entry.getSize();
data.lastModified = entry.getTime();
data.contentPath = contentPath;
InputStream s = zip;
if( data.contentLength == -1) {
Log.e("demo",new Object(){}.getClass().getEnclosingMethod().getName()+":: entry \""+entry+"\" has contentLength -1, so we will work around");
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
// use buf to store data from the zip file entry in fixed size
byte[] buf = new byte[4096];
while ((nRead = zip.read(buf)) != -1) {
// dump that data into buffer, which is a growing buffer
buffer.write(buf, 0, nRead);
}
buffer.flush();
byte[] finalBuffer = buffer.toByteArray();
Log.e("demo",new Object(){}.getClass().getEnclosingMethod().getName()+":: entry \""+entry+"\" final data length: "+finalBuffer.length);
data.contentLength = finalBuffer.length;
s = new ByteArrayInputStream(finalBuffer);
}
final InputStream finalStream = s;
日志给了我们这个
getContentData:: entry "OEBPS/hayat-ghayr.html" has contentLength -1, so we will work around
getContentData:: entry "OEBPS/hayat-ghayr.html" final data length: 2378
getContentData:: entry "OEBPS/hayat-ghayr.html" has contentLength -1, so we will work around
getContentData:: entry "OEBPS/hayat-ghayr.html" final data length: 2378
有趣的是..如果我们在命令行上运行它,该大小与该文件hayat-ghyr
的实际内容长度完全匹配:
$ unzip -l b17c024e-89f1-42f7-a546-91d46610cedb.epub
Archive: b17c024e-89f1-42f7-a546-91d46610cedb.epub
Length Date Time Name
-------- ---- ---- ----
20 01-27-12 11:17 mimetype
2378 04-20-12 10:12 OEBPS/hayat-ghayr.html
6436 02-06-12 11:06 OEBPS/content.opf
112579 01-27-12 11:25 OEBPS/images/978-614-425-313-7-hayat-ghayr-cover.png
182575 01-27-12 11:25 OEBPS/images/978-614-425-313-7-hayat_fmt.png
7757 01-27-12 11:21 OEBPS/template.css
5643 01-27-12 11:18 OEBPS/hayat-ghayr-2.html
20144 01-27-12 11:17 OEBPS/hayat-ghayr-1.html
65543 01-27-12 11:17 OEBPS/hayat-ghayr-3.html
59434 01-27-12 11:17 OEBPS/hayat-ghayr-4.html
66768 01-27-12 11:17 OEBPS/hayat-ghayr-5.html
49117 01-27-12 11:17 OEBPS/hayat-ghayr-6.html
65346 01-27-12 11:17 OEBPS/hayat-ghayr-7.html
74196 01-27-12 11:17 OEBPS/hayat-ghayr-8.html
73998 01-27-12 11:17 OEBPS/hayat-ghayr-9.html
61031 01-27-12 11:17 OEBPS/hayat-ghayr-10.html
68297 01-27-12 11:17 OEBPS/hayat-ghayr-11.html
72084 01-27-12 11:17 OEBPS/hayat-ghayr-12.html
2386 01-27-12 11:17 OEBPS/hayat-ghayr-13.html
61132 01-27-12 11:17 OEBPS/hayat-ghayr-14.html
46320 01-27-12 11:17 OEBPS/hayat-ghayr-15.html
32673 01-27-12 11:17 OEBPS/hayat-ghayr-16.html
88584 01-27-12 11:17 OEBPS/hayat-ghayr-17.html
56474 01-27-12 11:17 OEBPS/hayat-ghayr-18.html
52840 01-27-12 11:17 OEBPS/hayat-ghayr-19.html
80022 01-27-12 11:17 OEBPS/hayat-ghayr-20.html
50781 01-27-12 11:17 OEBPS/hayat-ghayr-21.html
2765 01-27-12 11:17 OEBPS/hayat-ghayr-22.html
265 01-27-12 11:17 META-INF/container.xml
54942 01-27-12 11:17 OEBPS/images/277.png
5549 01-27-12 11:17 OEBPS/toc.ncx
1072 03-23-12 13:28 iTunesMetadata.plist
-------- -------
1529151 32 files
关于java - 将解密的文件读入 ZipInputStream 有时会截断第一个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36768080/
尝试使用集成到 QTCreator 的表单编辑器,但即使我将插件放入 QtCreator.app/Contents/MacOS/designer 也不会显示。不过,相同的 dylib 文件确实适用于独
在此代码示例中。 “this.method2();”之后会读到什么?在返回returnedValue之前会跳转到method2()吗? public int method1(int returnedV
我的项目有通过gradle配置的依赖项。我想添加以下依赖项: compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', v
我将把我们基于 Windows 的客户管理软件移植到基于 Web 的软件。我发现 polymer 可能是一种选择。 但是,对于我们的使用,我们找不到 polymer 组件具有表格 View 、下拉菜单
我的项目文件夹 Project 中有一个文件夹,比如 ED 文件夹,当我在 Eclipse 中指定在哪里查找我写入的文件时 File file = new File("ED/text.txt"); e
这是奇怪的事情,这个有效: $('#box').css({"backgroundPosition": "0px 250px"}); 但这不起作用,它只是不改变位置: $('#box').animate
这个问题在这里已经有了答案: Why does OR 0 round numbers in Javascript? (3 个答案) 关闭 5 年前。 Mozilla JavaScript Guide
这个问题在这里已经有了答案: Is the function strcmpi in the C standard libary of ISO? (3 个答案) 关闭 8 年前。 我有一个问题,为什么
我目前使用的是共享主机方案,我不确定它使用的是哪个版本的 MySQL,但它似乎不支持 DATETIMEOFFSET 类型。 是否存在支持 DATETIMEOFFSET 的 MySQL 版本?或者有计划
研究 Seam 3,我发现 Seam Solder 允许将 @Named 注释应用于包 - 在这种情况下,该包中的所有 bean 都将自动命名,就好像它们符合条件一样@Named 他们自己。我没有看到
我知道 .append 偶尔会增加数组的容量并形成数组的新副本,但 .removeLast 会逆转这种情况并减少容量通过复制到一个新的更小的数组来改变数组? 最佳答案 否(或者至少如果是,则它是一个错
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
noexcept 函数说明符是否旨在 boost 性能,因为生成的对象中可能没有记录异常的代码,因此应尽可能将其添加到函数声明和定义中?我首先想到了可调用对象的包装器,其中 noexcept 可能会产
我正在使用 Angularjs 1.3.7,刚刚发现 Promise.all 在成功响应后不会更新 angularjs View ,而 $q.all 会。由于 Promises 包含在 native
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我正在编写一个玩具(物理)矢量库,并且遇到了 GHC 坚持认为函数应该具有 Integer 的问题。是他们的类型。我希望向量乘以向量以及标量(仅使用 * ),虽然这可以通过仅使用 Vector 来实现
PHP 的 mail() 函数发送邮件正常,但 Swiftmailer 的 Swift_MailTransport 不起作用! 这有效: mail('user@example.com', 'test
我尝试通过 php 脚本转储我的数据,但没有命令行。所以我用 this script 创建了我的 .sql 文件然后我尝试使用我的脚本: $link = mysql_connect($host, $u
使用 python 2.6.4 中的 sqlite3 标准库,以下查询在 sqlite3 命令行上运行良好: select segmentid, node_t, start, number,title
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我是一名优秀的程序员,十分优秀!