- 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/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!