首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么JNCryptor/RNCryptor库抛出InvalidHMACException?

为什么JNCryptor/RNCryptor库抛出InvalidHMACException?
EN

Stack Overflow用户
提问于 2015-08-20 18:43:13
回答 2查看 1.2K关注 0票数 1

我想要使用AES256对称加密,我的iPhone应用程序和我的Java服务器套接字。我目前使用的是Rob Napier的RNCryptor/JNCryptor库。iPhone上的加密似乎工作得很好,因为我可以再次解密加密的字符串。但是,只要我尝试解密Java服务器套接字上的字符串,就会抛出以下异常:

代码语言:javascript
复制
com.acme.crypto.InvalidHMACException: Incorrect HMAC value.
    at com.acme.crypto.AES256JNCryptor.decryptV3Data(AES256JNCryptor.java:248)
    at com.acme.crypto.AES256JNCryptor.decryptV3Data(AES256JNCryptor.java:323)
    at com.acme.crypto.AES256JNCryptor.decryptData(AES256JNCryptor.java:280)

com.acme.crypto.CryptorException: Unrecognised version number: 61.
    at com.acme.crypto.AES256JNCryptor.decryptData(AES256JNCryptor.java:283)

以下是用于发送加密数据(iOS/Objective-C)的相关客户端代码片段:

代码语言:javascript
复制
// add line break and send message to server
 NSString* message = [NSString stringWithFormat:@"%@\n", output];
 NSData* data = [[NSData alloc] initWithData:[message dataUsingEncoding:NSUTF8StringEncoding 
                                                   allowLossyConversion:NO]];
 // encrypt outgoing data with AES-256
 NSError *error1;
 NSData *cypher = [RNEncryptor encryptData:data
                              withSettings:kRNCryptorAES256Settings
                                  password:@"mypassword"
                                     error:&error1];
 // write encrypted data to output stream
 if (error1==nil) {
     NSInteger result = [outputStream write:[cypher bytes] maxLength:[cypher length]];
 } else {
     NSLog(@"Encryption of outgoing data failed: %@", error1);
 }

下面是在套接字(Linux/Java)上接收加密数据的相应服务器代码:

代码语言:javascript
复制
// initializing cryptor object during object construction
JNCryptor cryptor = new AES256JNCryptor();

// setting up the input stream on the server socket
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));

// this is within the client thread ...

String line;
while((line=input.readLine())!=null) {
    try {
        // ... the exception is thrown at the following line  ...
        byte[] decrypted = cryptor.decryptData(line.getBytes(), password.toCharArray());
        line = new String(decrypted, StandardCharsets.UTF_8);
        // message handling ...
    } catch (Exception ex) {
        // print exception ...
    }
 }

有人知道我做错了什么吗?在发送数据之前,我必须使用Base64或类似的编码吗?任何帮助都非常感谢。

编辑:这是解决方案。我现在不使用基于字符的输入流,而是直接使用来自套接字的InputStream,以便读取原始字节来提供解密算法:

代码语言:javascript
复制
@Override
public void run() {
    try {
        int bytes;
        byte[] buffer = new byte[4096];
        while((bytes=input.read(buffer))!=-1) {
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                baos.write(buffer, 0, bytes);
                byte[] decrypted = cryptor.decryptData(baos.toByteArray(), password.toCharArray());
                String line = new String(decrypted, StandardCharsets.UTF_8);
                // handle input ...
            } catch (Exception ex) {
                // handle exception ...
            }
        }
    } catch (Exception ex) {
        // handle exception ...
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-21 21:54:16

表示您的密码不正确或数据已损坏。

(我的Java有点弱,但我相当确定我对这里的文档的理解是正确的。)

我怀疑你的问题是你在用

..。这是从字节流到字符流(在您的例子中是UTF-8流)的桥梁。密文是完全随机的字节,在大多数情况下是非法的UTF-8字符(不仅仅是“胡言乱语”,实际上是非法的,不可破译)。我当然希望在bytes->utf8->bytes的往返过程中发生损坏。

你不需要使用

在这里。把它处理掉。

票数 3
EN

Stack Overflow用户

发布于 2015-11-17 21:57:55

我也有同样的问题,我的版本是65,而JNCryptor预期是2或3。

尽量不要使用baos.toByteArray()。

代码语言:javascript
复制
byte[] decrypted = cryptor.decryptData(baos.toByteArray(), password.toCharArray());

请改用:

代码语言:javascript
复制
byte[] decrypted = cryptor.decryptData(Base64.decodeBase64(baos), password.toCharArray());

希望能有所帮助,迭戈

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32116108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档