Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java解密和加密是否与SJCL兼容?_Java_Javascript_Android_Cryptography - Fatal编程技术网

Java解密和加密是否与SJCL兼容?

Java解密和加密是否与SJCL兼容?,java,javascript,android,cryptography,Java,Javascript,Android,Cryptography,我需要用Java(在Android上)和(我可能会切换到另一个JS加密库,但我熟悉SJCL,所以如果可能的话,我更愿意使用它)对数据进行加密和解密 我的SJCL端工作正常,但在Java端,我不确定需要使用哪些参数来设置密钥生成器和密码。到目前为止,我用于解密的代码是: SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(pass

我需要用Java(在Android上)和(我可能会切换到另一个JS加密库,但我熟悉SJCL,所以如果可能的话,我更愿意使用它)对数据进行加密和解密

我的SJCL端工作正常,但在Java端,我不确定需要使用哪些参数来设置密钥生成器和密码。到目前为止,我用于解密的代码是:

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
String plaintext = new String(cipher.doFinal(ciphertext), "UTF-8");
return plaintext;
其中salt、iv和密文作为字符串从SJCL生成的JSON对象中提取,然后使用Base64解码器对字节数组进行解码

不幸的是,我在这方面有一些问题,上面的代码不起作用

我遇到的第一个问题是,带有HMACSHA256的PBKDF2似乎不是公认的密钥生成算法。我不完全确定这是否是我想要的,但从阅读SJCL文档来看,这似乎是正确的?Java确实使用HMACSHA1识别PBKDF2,但这似乎与SJCL实现的算法不同

其次,如果我尝试使用SHA1密钥算法,我会得到一个关于无效密钥大小的错误。我需要安装一些东西来启用256位密钥的AES吗?告诉密钥工厂生成128位密钥可以正常工作(尽管显然与使用256位密钥的SJCL不兼容)

第三,我应该使用什么密码模式?我很确定CBC是不对的。。。SJCL的文档中提到了CCM和OCB,但Java似乎都不支持这两个现成的工具——再说一遍,我需要安装一些东西来实现这一点吗?SJCL默认为哪一个


最后,即使我选择的参数使Java不会抱怨丢失的算法,它也会抱怨解码SJCL输出所提供的IV的长度是错误的,这显然是错误的:结果输出中有17个字节,而不是AES所要求的16个字节。我是否忽略最后一个字节?

您可能必须使用BouncyCastle来获取SJCL中使用的所有加密功能。确保您的base64解码正确,并且SJCL没有添加长度指示器或类似内容。

我没有尝试过它(最后我放弃使用Javascript加密,转而使用带有bouncycastle的嵌入式java小程序来处理通信),但GnuCrypto(bouncycastle分叉)支持PBKDFWithHmacSHA256。SJCL中的固定字符编码处理可能修复了IV(?)的意外长度,因此这将只保留密码模式。从这一点来看,最简单的方法似乎是实现一个相对简单的密码模式(例如CTR)作为SJCL的附加组件,即使对于不熟悉代码的人来说,这也应该只需要几个小时的工作时间,之后只需对SJCL使用的JSON编码数据包进行编码和解码(这应该是微不足道的)

另一种选择是,尽管该算法是专有的,但肯定可以为Java实现OCB模式,因为在GPL下分发的软件有公共专利授权(http://www.cs.ucdavis.edu/~rogaway/ocb/grant.htm)


有趣的是,我想知道GnuCrypto是否会接受OCB模式支持的补丁?GnuCrypto是在GPL下发行的,并且有库豁免,这似乎符合“自由软件基金会发布的任何版本的GNU通用公共许可证”的条件因此,至少从理论上讲,这是可能的。

java中的SJCL AES

import org.bouncycastle.jce.provider.BouncyCastleProvider;
导入org.json.JSONObject;
导入javax.crypto.Cipher;
导入javax.crypto.SecretKey;
导入javax.crypto.SecretKeyFactory;
导入javax.crypto.spec.IvParameterSpec;
导入javax.crypto.spec.PBEKeySpec;
导入javax.crypto.spec.SecretKeySpec;
导入java.security.SecureRandom;
导入java.security.spec.KeySpec;
导入java.util.array;
导入java.util.Base64;
导入java.util.Base64.*;
导入java.util.HashMap;
导入java.util.Map;
导入静态java.nio.charset.StandardCharsets.UTF_8;
/**
*
*SJCL 1.0.8
*
*依赖项:
*编译组:“org.bouncycastle”,名称:“bcprov-jdk15on”,版本:“1.64”
*编译组:“org.json”,名称:“json”,版本:“20190722”
*
*参考:https://blog.degering.name/posts/java-sjcl
*/
公共类AesSJCL{
//只需打印出解码的字符串。
公共静态void main(字符串[]args)引发异常{
字符串password=“password”;
String plainText=“我是谁?”;
//加密
映射结果=new AesSJCL().encrypt(密码,明文);
String json=新的JSONObject(result).toString();
System.out.printf(“加密输出:\n%s\n”,json);
System.out.printf(“\njavascript测试代码:\nsjcl.decrypt(\“%s\”,“%s”)\n”,密码,json);
//解密
String decryptedText=new AesSJCL().decrypt(密码,json);
System.out.printf(“\n加密输出:\n%s\n”,解密文本);
}
/**
*
*@param password-密码
*@param encryptedText-{“cipher”:“aes”,“mode”:“ccm”,“ct”:“r7U/Gp2r8LVNQR7kl5qLNd8=”,“salt”:“vwsoss3jcn6m=”,“v”:1,“ks”:128,“iter”:10000,“iv”:“5oewqpth2ej1mhwvof57a=”,“adata”:“ts”:64}
*@返回
*@抛出异常
*/
公共字符串解密(字符串密码、字符串加密文本)引发异常{
解码器d=Base64.getDecoder();
//解码编码的JSON并从中创建JSON对象
JSONObject j=新JSONObject(新字符串(encryptedText));
//我们需要盐,IV和密文;
//所有这些都需要进行Base64解码
字节[]salt=d.decode(j.getString(“salt”);
字节[]iv=d.decode(j.getString(“iv”);
字节[]密文=d.decode(j.getString(“ct”);
//此外,我们还需要密钥大小和迭代计数
int keySize=j.getInt(“ks”),迭代次数=j.getInt(“iter”);
// https://gith