我需要的是加密将显示在二维条码中的字符串(PDF-417),这样当有人想要扫描它时就不会有任何可读性。
其他要求:
它必须足够简单,以摆脱窥探的人,并易于解密其他有兴趣获取数据的公司。他们打电话给我们,我们告诉他们标准或给他们一些简单的密钥,然后可以用于解密。
可能这些公司可以使用不同的技术,因此坚持一些与某些特殊平台或技术无关的标准会很好。
你有什么建议?是否有一些Java类正在进行encrypt()
& decrypt()
在实现高安全标准方面没有太大的复杂性?
答案 0 :(得分:110)
我建议使用广泛使用的标准对称密码,如DES,3DES或AES。虽然这不是最安全的算法,但是有很多实现,您只需要将密钥交给任何应该解密条形码中信息的人。 javax.crypto.Cipher是你想要在这里工作的。
我们假设要加密的字节在
中byte[] input;
接下来,您需要密钥和initialization vector字节
byte[] keyBytes;
byte[] ivBytes;
现在您可以为您选择的算法初始化密码:
// wrap key data in Key/IV specs to pass to cipher
SecretKeySpec key = new SecretKeySpec(keyBytes, "DES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
// create the cipher with the algorithm you choose
// see javadoc for Cipher class for more info, e.g.
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
加密将如下所示:
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted= new byte[cipher.getOutputSize(input.length)];
int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);
并解密如下:
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0);
dec_len += cipher.doFinal(decrypted, dec_len);
答案 1 :(得分:98)
这是通过Google和安全性显示的第一页 所有实现中的漏洞让我感到畏缩,所以我很沮丧 发布此信息以添加有关其他人的加密信息 原帖子已经 7年。我拥有硕士学位 计算机工程并花了很多时间学习和学习 密码学所以我把两分钱投入互联网 更安全的地方。
另外,请注意,对于给定的实施,许多实现可能是安全的 情况,但为什么要使用这些,并可能意外地制作一个 错误?使用你可用的最强大的工具,除非你有 具体原因没有。总的来说,我强烈建议使用图书馆和 如果可以的话,远离细节的细节。
更新4/5/18:我重写了一些部分,使其更易于理解,并将推荐的库从Jasypt更改为Google's new library Tink,我建议完全删除来自现有设置的Jasypt。
<强>前言强>
我将在下面概述安全对称加密的基础知识,并指出当人们使用标准Java库自己实现加密时我在网上看到的常见错误。如果您只想跳过转到Google's new library Tink的所有详细信息,请将其导入项目,并使用AES-GCM模式进行所有加密,您应该是安全的。
现在,如果您想了解有关如何在java中加密的详细信息,请阅读:)
分组密码
首先,您需要选择对称密钥块密码。分组密码是用于创建伪随机性的计算机功能/程序。伪随机性是伪随机性,除了量子计算机之外,任何计算机都无法区分它与真实随机性之间的区别。分组密码就像加密的构建块一样,当与不同的模式或方案一起使用时,我们可以创建加密。
现在关于今日可用的分组密码算法,请确保从不,我重复从不使用DES,我甚至会说永远不会使用{{3} }。即使斯诺登的NSA版本能够验证真正尽可能接近伪随机的唯一分组密码是3DES。还存在AES 128,区别在于AES 256在256位块中工作,而AES 128在128块中工作。总而言之,AES 128被认为是安全的,虽然已经发现了一些弱点,但256就像它一样坚固。
有趣的事实AES 256在最初成立时被国家安全局打破,并且实际上保密了几年,尽管有些人仍然认为DES是安全的,但仍有不少研究已发现并分析3DES中的弱点的论文。
加密模式
当您使用分组密码并使用特定方案时,会创建加密,以便随机性与密钥组合,以便只要您知道密钥就可以创建可逆的内容。这被称为加密模式。
以下是加密模式和称为ECB的最简单模式的示例,以便您可以直观地了解正在发生的事情:
您最常在网上看到的加密模式如下:
ECB CTR,CBC,GCM
除了列出的模式之外还存在其他模式,研究人员总是致力于新模式以改善现有问题。
现在让我们继续实施,什么是安全的。 从不使用ECB这对隐藏重复数据很不好,如着名所示。Linux penguin
在Java中实现时,请注意,如果使用以下代码,则默认设置ECB模式:
Cipher cipher = Cipher.getInstance("AES");
...危险这是一个脆弱性!,不幸的是,这在整个StackOverflow和在线教程和示例中都可以看到。
Nonces和IVs
针对ECB模式发现的问题,已经创建了nounces,也称为IVs。我们的想法是生成一个新的随机变量并将其附加到每个加密,这样当你加密两个相同的消息时,它们会变得不同。这背后的美丽是IV或nonce是公共知识。这意味着攻击者可以访问此权限,但只要他们没有密钥,他们就无法利用这些知识做任何事情。
我将看到的常见问题是人们会将IV设置为静态值,就像在代码中使用相同的固定值一样。当你重复一次实际上危及加密的整个安全性时,这就是IV的陷阱。
生成随机IV
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
注意: SHA1已损坏,但我无法找到如何正确地将SHA256应用到此用例中,因此如果有人想对此进行破解并更新它将会很棒!此外,SHA1攻击仍然是非传统的,因为它可能需要几年时间才能破解庞大的群集。
点击率实施
点击模式无需填充。
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
CBC实施
如果您选择使用PKCS7Padding实现CBC模式,请执行以下操作:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
CBC和点击率漏洞以及您应该使用GCM的原因
虽然其他一些模式(如CBC和CTR)是安全的,但它们遇到的问题是攻击者可以翻转加密数据,在解密时更改其值。所以,让我们假设您加密了一个想象中的银行消息&#34;卖出100&#34;,您的加密消息就像这样&#34; eu23ng&#34;攻击者将一位改为&#34; eu53ng&#34;当你解密你的消息时,它会突然显示为&#34;卖出900&#34;。
为避免这种情况,大部分互联网都使用GCM,每次看到HTTPS时,他们都可能使用GCM。 GCM使用散列对加密消息进行签名,并检查以使用此签名验证消息是否未更改。
由于其复杂性,我会避免实施GCM。你最好使用Check out details here.,因为如果你不小心重复IV,你会在GCM的情况下妥协你的密钥,这是最终的安全漏洞。新的研究人员正致力于IV重复抗性加密模式,即使你重复IV,密钥也没有危险,但这尚未成为主流。
现在,如果你想要实施GCM,这里是Googles new library Tink。但是,我无法确保安全性,或者它是否已正确实施,但它会降低基础。另请注意,GCM没有填充。
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
密码与密码
另一个非常重要的注意事项是,当涉及到加密时,密钥和密码不是一回事。密码学中的密钥需要具有一定量的熵和随机性才能被认为是安全的。这就是为什么您需要确保使用适当的加密库为您生成密钥。
所以你真的可以在这里做两个实现,第一个是使用link to a nice GCM implementation上的代码。此解决方案使用安全的随机数生成器从头开始创建一个可以使用的密钥。
另一个不太安全的选项是使用用户输入,例如密码。我们讨论的问题是密码没有足够的熵,所以我们必须使用this StackOverflow thread for Random Key Generation,这是一种获取密码并加强密码的算法。这是一个PBKDF2。但是Google Tink库内置了所有这些内容,你应该利用它。
Android开发者
需要指出的一点是要知道你的android代码是反向可操作的,大多数情况下大多数java代码也是如此。这意味着如果您在代码中以纯文本格式存储密码。黑客可以轻松检索它。通常,对于这些类型的加密,您需要使用非对称加密等。这超出了这篇文章的范围,所以我将避免潜入它。
StackOverflow implementation I liked:指出Android中88%的Crypto实施都是不正确的。
最后的想法
我再次建议避免直接为crypto实现java库并使用interesting reading from 2013,它会让你头疼,因为它们确实很好地正确地实现了所有算法。即使这样,也要确保检查Tink github上出现的问题,这里和那里都会出现漏洞。
如果您有任何问题或反馈,请随时发表评论! 安全性总是在变化,你需要尽力跟上它:)
答案 2 :(得分:20)
警告强>
请勿将其用作某种安全措施。
这篇文章中的加密机制是一次性填充,这意味着攻击者可以使用2个加密消息轻松恢复密钥。 XOR 2加密消息,你得到了密钥。那很简单!
Moussa指出
我正在使用Sun的Base64Encoder / Decoder,它可以在Sun的JRE中找到,以避免在lib中使用另一个JAR。从使用OpenJDK或其他一些JRE开始,这很危险。除此之外,还有另一个原因我应该考虑使用带有编码器/解码器的Apache commons lib吗?
public class EncryptUtils {
public static final String DEFAULT_ENCODING = "UTF-8";
static BASE64Encoder enc = new BASE64Encoder();
static BASE64Decoder dec = new BASE64Decoder();
public static String base64encode(String text) {
try {
return enc.encode(text.getBytes(DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
return null;
}
}//base64encode
public static String base64decode(String text) {
try {
return new String(dec.decodeBuffer(text), DEFAULT_ENCODING);
} catch (IOException e) {
return null;
}
}//base64decode
public static void main(String[] args) {
String txt = "some text to be encrypted";
String key = "key phrase used for XOR-ing";
System.out.println(txt + " XOR-ed to: " + (txt = xorMessage(txt, key)));
String encoded = base64encode(txt);
System.out.println(" is encoded to: " + encoded + " and that is decoding to: " + (txt = base64decode(encoded)));
System.out.print("XOR-ing back to original: " + xorMessage(txt, key));
}
public static String xorMessage(String message, String key) {
try {
if (message == null || key == null) return null;
char[] keys = key.toCharArray();
char[] mesg = message.toCharArray();
int ml = mesg.length;
int kl = keys.length;
char[] newmsg = new char[ml];
for (int i = 0; i < ml; i++) {
newmsg[i] = (char)(mesg[i] ^ keys[i % kl]);
}//for i
return new String(newmsg);
} catch (Exception e) {
return null;
}
}//xorMessage
}//class
答案 3 :(得分:10)
谢谢我用你的代码创建了这个类,也许有人发现它是userfull
对象crypter
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class ObjectCrypter {
private Cipher deCipher;
private Cipher enCipher;
private SecretKeySpec key;
private IvParameterSpec ivSpec;
public ObjectCrypter(byte[] keyBytes, byte[] ivBytes) {
// wrap key data in Key/IV specs to pass to cipher
ivSpec = new IvParameterSpec(ivBytes);
// create the cipher with the algorithm you choose
// see javadoc for Cipher class for more info, e.g.
try {
DESKeySpec dkey = new DESKeySpec(keyBytes);
key = new SecretKeySpec(dkey.getKey(), "DES");
deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] encrypt(Object obj) throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, IllegalBlockSizeException, ShortBufferException, BadPaddingException {
byte[] input = convertToByteArray(obj);
enCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
return enCipher.doFinal(input);
// cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
// byte[] encypted = new byte[cipher.getOutputSize(input.length)];
// int enc_len = cipher.update(input, 0, input.length, encypted, 0);
// enc_len += cipher.doFinal(encypted, enc_len);
// return encypted;
}
public Object decrypt( byte[] encrypted) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException {
deCipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
return convertFromByteArray(deCipher.doFinal(encrypted));
}
private Object convertFromByteArray(byte[] byteObject) throws IOException,
ClassNotFoundException {
ByteArrayInputStream bais;
ObjectInputStream in;
bais = new ByteArrayInputStream(byteObject);
in = new ObjectInputStream(bais);
Object o = in.readObject();
in.close();
return o;
}
private byte[] convertToByteArray(Object complexObject) throws IOException {
ByteArrayOutputStream baos;
ObjectOutputStream out;
baos = new ByteArrayOutputStream();
out = new ObjectOutputStream(baos);
out.writeObject(complexObject);
out.close();
return baos.toByteArray();
}
}
答案 4 :(得分:5)
这个怎么样:
private static byte[] xor(final byte[] input, final byte[] secret) {
final byte[] output = new byte[input.length];
if (secret.length == 0) {
throw new IllegalArgumentException("empty security key");
}
int spos = 0;
for (int pos = 0; pos < input.length; ++pos) {
output[pos] = (byte) (input[pos] ^ secret[spos]);
++spos;
if (spos >= secret.length) {
spos = 0;
}
}
return output;
}
对我来说很好,而且相当紧凑。
答案 5 :(得分:5)
您可以使用Jasypt
使用Jasypt,加密和检查密码可以像......一样简单。
StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
textEncryptor.setPassword(myEncryptionPassword);
<强>加密强>
String myEncryptedText = textEncryptor.encrypt(myText);
<强>解密:强>
String plainText = textEncryptor.decrypt(myEncryptedText);
<强>摇篮:强>
compile group: 'org.jasypt', name: 'jasypt', version: '1.9.2'
功能强>
Jasypt为您提供简单的单向(摘要)和双向加密技术。
Open API,用于任何JCE提供程序,而不仅仅是默认的Java VM提供程序。 Jasypt可以很容易地与像Bouncy Castle这样的知名提供商一起使用。了解更多。
为您的用户提供更高的安全性&#39;密码。了解更多。
二进制加密支持。 Jasypt允许二进制文件(字节数组)的摘要和加密。在需要时加密您的对象或文件(例如,通过网络发送)。
号码加密支持。除了文本和二进制文件之外,它还允许数值的摘要和加密(BigInteger和BigDecimal,在加密Hibernate持久性时支持其他数字类型)。了解更多。
完全线程安全。
支持加密/消化池,以实现多处理器/多核系统的高性能。
包含一个轻量级(&#34; lite&#34;)版本的库,以便在移动平台等大小限制环境中实现更好的可管理性。
为新加密用户提供简单,无配置的加密工具,并为高级用户提供高度可配置的标准加密工具。
Hibernate 3和4可选集成,用于以加密方式保留映射实体的字段。字段加密在Hibernate映射文件中定义,并且对于应用程序的其余部分保持透明(对于敏感的个人数据,具有许多启用读取的用户的数据库...)。加密文本,二进制文件,数字,布尔值,日期......了解更多信息。
无缝集成到Spring应用程序中,具有Spring 2,Spring 3.0和Spring 3.1的特定集成功能。 jasypt中的所有消化器和加密器都设计为可以从Spring轻松使用(实例化,依赖注入...)。并且,由于它们是线程安全的,因此可以在像Spring这样的面向单一的环境中使用它们而不会出现同步问题。了解更多:Spring 2,Spring 3.0,Spring 3.1。
Spring Security(以前称为Acegi Security)可选集成,用于为安全框架执行密码加密和匹配任务,提高用户的安全性。密码使用更安全的密码加密机制,为您提供更高程度的配置和控制。了解更多。
提供加密全部或部分应用程序配置文件的高级功能,包括数据库密码等敏感信息。将加密配置无缝集成到基于Spring,和/或Hibernate的普通应用程序中。了解更多。
提供易于使用的CLI(命令行界面)工具,允许开发人员初始化其加密数据,并在维护任务或脚本中包含加密/解密/摘要操作。了解更多。
集成到Apache Wicket中,以便在安全应用程序中对URL进行更强大的加密。
全面的指南和javadoc文档,使开发人员能够更好地了解他们对数据的真实作用。
强大的字符集支持,旨在充分加密和消化原始字符集中的文本。完全支持日语,韩语,阿拉伯语......没有编码或平台问题。
非常高级别的配置功能:开发人员可以实现一些技巧,例如指示&#34;加密器&#34;例如,向远程HTTPS服务器询问用于加密的密码。它可以满足您的安全需求。
答案 6 :(得分:4)
这是我从meta64.com作为Spring Singleton实现的。如果您想为每个也可以使用的呼叫创建一个ciper实例,那么您可以删除同步的&#39;电话,但要注意密码&#39;不是线程安全的。
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("singleton")
public class Encryptor {
@Value("${aeskey}")
private String keyStr;
private Key aesKey = null;
private Cipher cipher = null;
synchronized private void init() throws Exception {
if (keyStr == null || keyStr.length() != 16) {
throw new Exception("bad aes key configured");
}
if (aesKey == null) {
aesKey = new SecretKeySpec(keyStr.getBytes(), "AES");
cipher = Cipher.getInstance("AES");
}
}
synchronized public String encrypt(String text) throws Exception {
init();
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
return toHexString(cipher.doFinal(text.getBytes()));
}
synchronized public String decrypt(String text) throws Exception {
init();
cipher.init(Cipher.DECRYPT_MODE, aesKey);
return new String(cipher.doFinal(toByteArray(text)));
}
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}
/*
* DO NOT DELETE
*
* Use this commented code if you don't like using DatatypeConverter dependency
*/
// public static String toHexStringOld(byte[] bytes) {
// StringBuilder sb = new StringBuilder();
// for (byte b : bytes) {
// sb.append(String.format("%02X", b));
// }
// return sb.toString();
// }
//
// public static byte[] toByteArrayOld(String s) {
// int len = s.length();
// byte[] data = new byte[len / 2];
// for (int i = 0; i < len; i += 2) {
// data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i +
// 1), 16));
// }
// return data;
// }
}
答案 7 :(得分:4)
这是我刚才在Java 8中编写的加密和解密代码,其中考虑了以下几点。希望有人会觉得有用:
加密算法:具有256位密钥的分组密码AES被认为足够安全。要加密完整的消息,需要选择一种模式。建议使用经过身份验证的加密(同时提供机密性和完整性)。 GCM,CCM和EAX是最常用的经过身份验证的加密模式。 GCM通常是首选,并且在提供GCM专用说明的英特尔体系结构中表现良好。所有这三种模式都是基于CTR(基于计数器)的模式,因此它们不需要填充。因此,它们不容易受到与填充相关的攻击
GCM需要初始化向量(IV)。 IV不是秘密。唯一的要求是它必须是随机的或不可预测的。在Java中,SecuredRandom
类用于生成密码学上强的伪随机数。伪随机数生成算法可以在getInstance()
方法中指定。但是,从Java 8开始,推荐的方法是使用getInstanceStrong()
方法,该方法将使用Provider
NIST建议GCM使用96位IV,以提高互操作性,效率和简化设计
为确保额外的安全性,在以下实现中,SecureRandom
在产生每2 ^ 16字节的伪随机字节生成后重新播种
收件人需要知道IV才能解密密文。因此,IV需要与密文一起传输。一些实现将IV作为AD(关联数据)发送,这意味着将在密文和IV上计算身份验证标签。但是,这不是必需的。可以在IV前面简单地加上密文,因为如果IV在传输过程中由于故意的攻击或网络/文件系统错误而被更改,则身份验证标签验证仍然会失败
字符串不应该用于保存明文消息或密钥,因为字符串是不可变的,因此使用后我们无法清除它们。这些未清除的字符串随后会在内存中徘徊,并可能显示在堆转储中。出于相同的原因,调用这些加密或解密方法的客户端应在不再需要它们时清除包含消息或密钥的所有变量或数组。
没有遵循常规建议的代码中的提供者被硬编码
最后要通过网络或存储进行传输,密钥或密文应使用Base64编码进行编码。可以在here中找到Base64的详细信息。应该遵循Java 8方法
可以使用以下方法清除字节数组:
Arrays.fill(clearTextMessageByteArray, Byte.MIN_VALUE);
但是,从Java 8开始,没有简单的方法可以清除SecretKeyspec
和SecretKey
,因为这两个接口的实现似乎尚未实现方法的destroy()
。接口Destroyable
。在下面的代码中,编写了一个单独的方法以使用反射清除SecretKeySpec
和SecretKey
。
密钥应使用以下两种方法之一生成。
请注意,密钥是像密码一样的秘密,但是与供人使用的密码不同,密钥是供加密算法使用的,因此只能使用上述方式生成。
package com.sapbasu.javastudy;
import java.lang.reflect.Field;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
private static final int AUTH_TAG_SIZE = 128; // bits
// NIST recommendation: "For IVs, it is recommended that implementations
// restrict support to the length of 96 bits, to
// promote interoperability, efficiency, and simplicity of design."
private static final int IV_LEN = 12; // bytes
// number of random number bytes generated before re-seeding
private static final double PRNG_RESEED_INTERVAL = Math.pow(2, 16);
private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
private static final List<Integer> ALLOWED_KEY_SIZES = Arrays
.asList(new Integer[] {128, 192, 256}); // bits
private static SecureRandom prng;
// Used to keep track of random number bytes generated by PRNG
// (for the purpose of re-seeding)
private static int bytesGenerated = 0;
public byte[] encrypt(byte[] input, SecretKeySpec key) throws Exception {
Objects.requireNonNull(input, "Input message cannot be null");
Objects.requireNonNull(key, "key cannot be null");
if (input.length == 0) {
throw new IllegalArgumentException("Length of message cannot be 0");
}
if (!ALLOWED_KEY_SIZES.contains(key.getEncoded().length * 8)) {
throw new IllegalArgumentException("Size of key must be 128, 192 or 256");
}
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
byte[] iv = getIV(IV_LEN);
GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, gcmParamSpec);
byte[] messageCipher = cipher.doFinal(input);
// Prepend the IV with the message cipher
byte[] cipherText = new byte[messageCipher.length + IV_LEN];
System.arraycopy(iv, 0, cipherText, 0, IV_LEN);
System.arraycopy(messageCipher, 0, cipherText, IV_LEN,
messageCipher.length);
return cipherText;
}
public byte[] decrypt(byte[] input, SecretKeySpec key) throws Exception {
Objects.requireNonNull(input, "Input message cannot be null");
Objects.requireNonNull(key, "key cannot be null");
if (input.length == 0) {
throw new IllegalArgumentException("Input array cannot be empty");
}
byte[] iv = new byte[IV_LEN];
System.arraycopy(input, 0, iv, 0, IV_LEN);
byte[] messageCipher = new byte[input.length - IV_LEN];
System.arraycopy(input, IV_LEN, messageCipher, 0, input.length - IV_LEN);
GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.DECRYPT_MODE, key, gcmParamSpec);
return cipher.doFinal(messageCipher);
}
public byte[] getIV(int bytesNum) {
if (bytesNum < 1) throw new IllegalArgumentException(
"Number of bytes must be greater than 0");
byte[] iv = new byte[bytesNum];
prng = Optional.ofNullable(prng).orElseGet(() -> {
try {
prng = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Wrong algorithm name", e);
}
return prng;
});
if (bytesGenerated > PRNG_RESEED_INTERVAL || bytesGenerated == 0) {
prng.setSeed(prng.generateSeed(bytesNum));
bytesGenerated = 0;
}
prng.nextBytes(iv);
bytesGenerated = bytesGenerated + bytesNum;
return iv;
}
private static void clearSecret(Destroyable key)
throws IllegalArgumentException, IllegalAccessException,
NoSuchFieldException, SecurityException {
Field keyField = key.getClass().getDeclaredField("key");
keyField.setAccessible(true);
byte[] encodedKey = (byte[]) keyField.get(key);
Arrays.fill(encodedKey, Byte.MIN_VALUE);
}
}
主要可以通过两种方式生成加密密钥:
没有任何密码
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(KEY_LEN, SecureRandom.getInstanceStrong());
SecretKey secretKey = keyGen.generateKey();
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
"AES");
Crypto.clearSecret(secretKey);
// After encryption or decryption with key
Crypto.clearSecret(secretKeySpec);
使用密码
SecureRandom random = SecureRandom.getInstanceStrong();
byte[] salt = new byte[32];
random.nextBytes(salt);
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations,
keyLength);
SecretKeyFactory keyFactory =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
"AES");
Crypto.clearSecret(secretKey);
// After encryption or decryption with key
Crypto.clearSecret(secretKeySpec);
正如@MaartenBodewes指出的那样,我的回答没有按照问题的要求处理任何String
。因此,我将尝试填补这一空白,以防万一有人偶然发现了这个答案而对处理String
感到疑惑。
如答案前面所述,在String
中处理敏感信息通常不是一个好主意,因为String
是不可变的,因此我们在使用后无法清除它。并且我们知道,即使String
没有强引用,垃圾回收器也不会立即急于将其从堆中删除。因此,String
会在内存中继续存在一个未知的时间窗口,即使程序无法访问它。问题在于,在该时间段内进行堆转储会泄露敏感信息。因此,总是最好处理字节数组或char数组中的所有敏感信息,然后在达到目的后将其填充为0。
但是,尽管有这么多知识,但是如果我们仍然遇到要加密的敏感信息位于String
中的情况,我们首先需要将其转换为字节数组并调用{{1上面介绍的}}和encrypt
函数。 (另一个输入键可以使用上面提供的代码段生成。)
可以通过以下方式将decrypt
转换为字节:
String
从Java 8开始,byte[] inputBytes = inputString.getBytes(StandardCharsets.UTF_8);
内部以String
编码存储在堆中。但是,我们这里使用UTF-16
是因为它通常比UTF-8
占用更少的空间,尤其是对于ASCII字符。
同样,加密的字节数组也可以转换为字符串,如下所示:
UTF-16
答案 8 :(得分:3)
我会考虑使用像https://www.bouncycastle.org/这样的东西它是一个预构建的库,允许你用许多不同的密码加密你喜欢的任何东西 我知道您只想保护免受窥探,但如果您真的想要保护信息,使用Base64实际上并不能保护您。
答案 9 :(得分:2)
以下是一些链接,您可以阅读Java支持的内容
Encrypting/decrypting a data stream.
此示例演示如何操作 加密(使用对称加密 算法,如AES,Blowfish,RC2, 3DES等)大量数据。该 数据以块的形式传递给其中一个 加密方法:EncryptBytes, EncryptString,EncryptBytesENC或 EncryptStringENC。 (方法名称 表示输入的类型(字符串或 字节数组)和返回类型 (编码的字符串或字节数组)。该 FirstChunk和LastChunk属性 用于表示是否有块 是第一个,中间的或最后一个 要加密的流。默认情况下, FirstChunk和LastChunk都相同 true - 表示数据已通过 是全部金额。
答案 10 :(得分:1)
这是一个只有java.*
和javax.crypto.*
依赖关系的简单解决方案,用于加密字节,提供机密性和完整性。对于千字节的短消息,它应该是indistinguishable under a choosen plaintext attack。
它在AES
模式下使用GCM
而没有填充,128位密钥由PBKDF2
派生,具有大量迭代和来自提供的密码的静态盐。这样可以确保暴力破解密码很难,并将熵分配到整个密钥上。
生成随机初始化向量(IV)并将其添加到密文之前。此外,静态字节0x01
作为第一个字节被添加为&#39;版本&#39;。
整个邮件进入AES/GCM
生成的邮件验证码(MAC)。
此外,零外部依赖关系加密类提供机密性和完整性:
package ch.n1b.tcrypt.utils;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
/**
* This class implements AES-GCM symmetric key encryption with a PBKDF2 derived password.
* It provides confidentiality and integrity of the plaintext.
*
* @author Thomas Richner
* @created 2018-12-07
*/
public class AesGcmCryptor {
// https://crypto.stackexchange.com/questions/26783/ciphertext-and-tag-size-and-iv-transmission-with-aes-in-gcm-mode
private static final byte VERSION_BYTE = 0x01;
private static final int VERSION_BYTE_LENGTH = 1;
private static final int AES_KEY_BITS_LENGTH = 128;
// fixed AES-GCM constants
private static final String GCM_CRYPTO_NAME = "AES/GCM/NoPadding";
private static final int GCM_IV_BYTES_LENGTH = 12;
private static final int GCM_TAG_BYTES_LENGTH = 16;
// can be tweaked, more iterations = more compute intensive to brute-force password
private static final int PBKDF2_ITERATIONS = 1024;
// protects against rainbow tables
private static final byte[] PBKDF2_SALT = hexStringToByteArray("4d3fe0d71d2abd2828e7a3196ea450d4");
public String encryptString(char[] password, String plaintext) throws CryptoException {
byte[] encrypted = null;
try {
encrypted = encrypt(password, plaintext.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException //
| InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException //
| InvalidKeySpecException e) {
throw new CryptoException(e);
}
return byteArrayToHexString(encrypted);
}
public String decryptString(char[] password, String ciphertext)
throws CryptoException {
byte[] ct = hexStringToByteArray(ciphertext);
byte[] plaintext = null;
try {
plaintext = decrypt(password, ct);
} catch (AEADBadTagException e) {
throw new CryptoException(e);
} catch ( //
NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException //
| InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException //
| BadPaddingException e) {
throw new CryptoException(e);
}
return new String(plaintext, StandardCharsets.UTF_8);
}
/**
* Decrypts an AES-GCM encrypted ciphertext and is
* the reverse operation of {@link AesGcmCryptor#encrypt(char[], byte[])}
*
* @param password passphrase for decryption
* @param ciphertext encrypted bytes
* @return plaintext bytes
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
* @throws InvalidKeySpecException
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws IllegalArgumentException if the length or format of the ciphertext is bad
* @throws CryptoException
*/
public byte[] decrypt(char[] password, byte[] ciphertext)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException,
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
// input validation
if (ciphertext == null) {
throw new IllegalArgumentException("ciphertext cannot be null");
}
if (ciphertext.length <= VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH + GCM_TAG_BYTES_LENGTH) {
throw new IllegalArgumentException("ciphertext too short");
}
// the version must match, we don't decrypt other versions
if (ciphertext[0] != VERSION_BYTE) {
throw new IllegalArgumentException("wrong version: " + ciphertext[0]);
}
// input seems legit, lets decrypt and check integrity
// derive key from password
SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH);
// init cipher
Cipher cipher = Cipher.getInstance(GCM_CRYPTO_NAME);
GCMParameterSpec params = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8,
ciphertext,
VERSION_BYTE_LENGTH,
GCM_IV_BYTES_LENGTH
);
cipher.init(Cipher.DECRYPT_MODE, key, params);
final int ciphertextOffset = VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH;
// add version and IV to MAC
cipher.updateAAD(ciphertext, 0, ciphertextOffset);
// decipher and check MAC
return cipher.doFinal(ciphertext, ciphertextOffset, ciphertext.length - ciphertextOffset);
}
/**
* Encrypts a plaintext with a password.
* <p>
* The encryption provides the following security properties:
* Confidentiality + Integrity
* <p>
* This is achieved my using the AES-GCM AEAD blockmode with a randomized IV.
* <p>
* The tag is calculated over the version byte, the IV as well as the ciphertext.
* <p>
* Finally the encrypted bytes have the following structure:
* <pre>
* +-------------------------------------------------------------------+
* | | | | |
* | version | IV bytes | ciphertext bytes | tag |
* | | | | |
* +-------------------------------------------------------------------+
* Length: 1B 12B len(plaintext) bytes 16B
* </pre>
* Note: There is no padding required for AES-GCM, but this also implies that
* the exact plaintext length is revealed.
*
* @param password password to use for encryption
* @param plaintext plaintext to encrypt
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
* @throws NoSuchPaddingException
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws InvalidKeySpecException
*/
public byte[] encrypt(char[] password, byte[] plaintext)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException,
InvalidKeySpecException {
// initialise random and generate IV (initialisation vector)
SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH);
final byte[] iv = new byte[GCM_IV_BYTES_LENGTH];
SecureRandom random = SecureRandom.getInstanceStrong();
random.nextBytes(iv);
// encrypt
Cipher cipher = Cipher.getInstance(GCM_CRYPTO_NAME);
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
// add IV to MAC
final byte[] versionBytes = new byte[]{VERSION_BYTE};
cipher.updateAAD(versionBytes);
cipher.updateAAD(iv);
// encrypt and MAC plaintext
byte[] ciphertext = cipher.doFinal(plaintext);
// prepend VERSION and IV to ciphertext
byte[] encrypted = new byte[1 + GCM_IV_BYTES_LENGTH + ciphertext.length];
int pos = 0;
System.arraycopy(versionBytes, 0, encrypted, 0, VERSION_BYTE_LENGTH);
pos += VERSION_BYTE_LENGTH;
System.arraycopy(iv, 0, encrypted, pos, iv.length);
pos += iv.length;
System.arraycopy(ciphertext, 0, encrypted, pos, ciphertext.length);
return encrypted;
}
/**
* We derive a fixed length AES key with uniform entropy from a provided
* passphrase. This is done with PBKDF2/HMAC256 with a fixed count
* of iterations and a provided salt.
*
* @param password passphrase to derive key from
* @param salt salt for PBKDF2 if possible use a per-key salt, alternatively
* a random constant salt is better than no salt.
* @param keyLen number of key bits to output
* @return a SecretKey for AES derived from a passphrase
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
private SecretKey deriveAesKey(char[] password, byte[] salt, int keyLen)
throws NoSuchAlgorithmException, InvalidKeySpecException {
if (password == null || salt == null || keyLen <= 0) {
throw new IllegalArgumentException();
}
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password, salt, PBKDF2_ITERATIONS, keyLen);
SecretKey pbeKey = factory.generateSecret(spec);
return new SecretKeySpec(pbeKey.getEncoded(), "AES");
}
/**
* Helper to convert hex strings to bytes.
* <p>
* May be used to read bytes from constants.
*/
private static byte[] hexStringToByteArray(String s) {
if (s == null) {
throw new IllegalArgumentException("Provided `null` string.");
}
int len = s.length();
if (len % 2 != 0) {
throw new IllegalArgumentException("Invalid length: " + len);
}
byte[] data = new byte[len / 2];
for (int i = 0; i < len - 1; i += 2) {
byte b = (byte) toHexDigit(s, i);
b <<= 4;
b |= toHexDigit(s, i + 1);
data[i / 2] = b;
}
return data;
}
private static int toHexDigit(String s, int pos) {
int d = Character.digit(s.charAt(pos), 16);
if (d < 0) {
throw new IllegalArgumentException("Cannot parse hex digit: " + s + " at " + pos);
}
return d;
}
private static String byteArrayToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
public class CryptoException extends Exception {
public CryptoException(Throwable cause) {
super(cause);
}
}
}
这里有一个很好的CLI整个项目:https://github.com/trichner/tcrypt
现在使用适当的encryptString
和decryptString
修改
答案 11 :(得分:0)
这是复制/粘贴解决方案。我也建议阅读@Konstantino's answer并为其投票,即使它没有提供任何代码。初始化向量(IV)就像盐-不必保密。我是GCM的新手,显然AAD是可选的,仅在某些情况下使用。在环境变量<p id="resMessage"></p>
<div id="generalSettings" class="main-menu-content">
<% if (showData.prefix) { %>
<%
function savePrefix() {
try {
configData({
'prefix': document.getElementById('resMessage') <=== this is not defined
});
%>
<script type="text/javascript">
var resMessage = document.getElementById("resMessage")
resMessage.style.backgroundColor = 'green';
resMessage.innerHTML = "Success!"
</script>
<%
} catch (err) {
if (err) {
%>
<script type="text/javascript">
var resMessage = document.getElementById("resMessage")
resMessage.style.backgroundColor = 'red';
resMessage.innerHTML = `Error: ${err.toString()}`
</script>
<%
console.log(err)
};
};
};
%>
<input type="text" id="prefix" value=<%= showData.prefix %> maxlength="6"><input type="submit" onclick=<%= savePrefix() %>>
<% } %>
</div>
中设置密钥。使用类似KeePass之类的密码来生成32个字符的密码。此解决方案是根据我的Ruby解决方案建模的。
SECRET_KEY_BASE
这里是一个例子:
public static String encrypt(String s) {
try {
byte[] input = s.getBytes("UTF-8");
String keyString = System.getProperty("SECRET_KEY_BASE", System.getenv("SECRET_KEY_BASE"));
if (keyString == null || keyString.length() == 0) {
Logger.error(Utils.class, "encrypt()", "$SECRET_KEY_BASE is not set.");
return null;
}
byte[] keyBytes = keyString.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
// generate IV
SecureRandom secureRandom = SecureRandom.getInstanceStrong();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] ivBytes = new byte[cipher.getBlockSize()];
secureRandom.nextBytes(ivBytes);
GCMParameterSpec gcmSpec = new GCMParameterSpec(96, ivBytes); // 96 bit tag length
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
// generate AAD
// byte[] aadBytes = new byte[cipher.getBlockSize()];
// secureRandom.nextBytes(aadBytes);
// cipher.updateAAD(aadBytes);
// encrypt
byte[] encrypted = cipher.doFinal(input);
byte[] returnBytes = new byte[ivBytes.length + encrypted.length];
// byte[] returnBytes = new byte[ivBytes.length + aadBytes.length + encrypted.length];
System.arraycopy(ivBytes, 0, returnBytes, 0, ivBytes.length);
// System.arraycopy(aadBytes, 0, returnBytes, ivBytes.length, aadBytes.length);
System.arraycopy(encrypted, 0, returnBytes, ivBytes.length, encrypted.length);
// System.arraycopy(encrypted, 0, returnBytes, ivBytes.length+aadBytes.length, encrypted.length);
String encryptedString = Base64.getEncoder().encodeToString(returnBytes);
return encryptedString;
} catch (UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
Logger.error(Utils.class, "encrypt()", "Could not encrypt string: " + e.getMessage());
return null;
}
}
public static String decrypt(String s) {
if (s == null || s.length() == 0) return "";
try {
byte[] encrypted = Base64.getDecoder().decode(s);
String keyString = System.getProperty("SECRET_KEY_BASE", System.getenv("SECRET_KEY_BASE"));
if (keyString == null || keyString.length() == 0) {
Logger.error(Utils.class, "encrypt()", "$SECRET_KEY_BASE is not set.");
return null;
}
byte[] keyBytes = keyString.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] ivBytes = new byte[cipher.getBlockSize()];
System.arraycopy(encrypted, 0, ivBytes, 0, ivBytes.length);
GCMParameterSpec gcmSpec = new GCMParameterSpec(96, ivBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
// cipher.updateAAD(encrypted, ivBytes.length, cipher.getBlockSize());
byte[] decrypted = cipher.doFinal(encrypted, cipher.getBlockSize(), encrypted.length - cipher.getBlockSize());
// byte[] decrypted = cipher.doFinal(encrypted, cipher.getBlockSize()*2, encrypted.length - cipher.getBlockSize()*2);
String decryptedString = new String(decrypted, "UTF-8");
return decryptedString;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedEncodingException | InvalidKeyException |
InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
Logger.error(Utils.class, "decrypt()", "Could not decrypt string: " + e.getMessage());
return null;
}
}
答案 12 :(得分:-1)
就像许多人已经告诉过的那样,您应该使用过度使用的标准密码,例如DES或AES。
一个简单的示例,说明如何使用 AES 在Java中加密和解密字符串。
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptorDemo {
public static String encrypt(String key, String randomVector, String value) {
try {
IvParameterSpec iv = new IvParameterSpec(randomVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted text: " + Base64.encodeBase64String(encrypted));
return Base64.encodeBase64String(encrypted);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt(String key, String randomVector, String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(randomVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] originalText = cipher.doFinal(Base64.decodeBase64(encrypted));
System.out.println("decrypted text: " + new String(originalText));
return new String(originalText);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String key = "JavasEncryptDemo"; // 128 bit key
String randomVector = "RandomJavaVector"; // 16 bytes IV
decrypt(key, randomVector, encrypt(key, randomVector, "Anything you want to encrypt!"));
}
}
答案 13 :(得分:-4)
您可能需要考虑一些自动化工具来执行加密/解密代码生成,例如。 https://www.stringencrypt.com/java-encryption/
每次为字符串或文件加密生成不同的加密和解密代码。
在不使用RSA,AES等快速字符串加密方面非常方便。
示例结果:
// encrypted with https://www.stringencrypt.com (v1.1.0) [Java]
// szTest = "Encryption in Java!"
String szTest = "\u9E3F\uA60F\uAE07\uB61B\uBE1F\uC62B\uCE2D\uD611" +
"\uDE03\uE5FF\uEEED\uF699\uFE3D\u071C\u0ED2\u1692" +
"\u1E06\u26AE\u2EDC";
for (int iatwS = 0, qUJQG = 0; iatwS < 19; iatwS++)
{
qUJQG = szTest.charAt(iatwS);
qUJQG ++;
qUJQG = ((qUJQG << 5) | ( (qUJQG & 0xFFFF) >> 11)) & 0xFFFF;
qUJQG -= iatwS;
qUJQG = (((qUJQG & 0xFFFF) >> 6) | (qUJQG << 10)) & 0xFFFF;
qUJQG ^= iatwS;
qUJQG -= iatwS;
qUJQG = (((qUJQG & 0xFFFF) >> 3) | (qUJQG << 13)) & 0xFFFF;
qUJQG ^= 0xFFFF;
qUJQG ^= 0xB6EC;
qUJQG = ((qUJQG << 8) | ( (qUJQG & 0xFFFF) >> 8)) & 0xFFFF;
qUJQG --;
qUJQG = (((qUJQG & 0xFFFF) >> 5) | (qUJQG << 11)) & 0xFFFF;
qUJQG ++;
qUJQG ^= 0xFFFF;
qUJQG += iatwS;
szTest = szTest.substring(0, iatwS) + (char)(qUJQG & 0xFFFF) + szTest.substring(iatwS + 1);
}
System.out.println(szTest);
我们一直在公司使用它。
答案 14 :(得分:-4)
String s1="arshad";
char[] s2=s1.toCharArray();
int s3= s2.length;
System.out.println(s3);
int i=0;
// for(int j=0;j<s3;j++)
// System.out.println(s2[j]);
for(i=0;i<((s3)/2);i++) {
char z,f=10;
z=(char) (s2[i] * f);
s2[i]=s2[(s3-1)-i];
s2[(s3-1)-i]=z;
String b=new String(s2);
print(b); }
答案 15 :(得分:-5)
public static String encryptParams(String myTextInput) {
String myKey = "40674244454045cb9a70040a30e1c007";
String myVector = "@1B2c3D4e5F6g7H8";
String encData = "";
try{
JavaEncryprtionUtil encUtil = new JavaEncryprtionUtil();
encData = Base64.encodeToString(encUtil.encrypt(myTextInput.getBytes("UTF-8"), myKey.getBytes("UTF-8"), myVector.getBytes("UTF-8")),Base64.DEFAULT);
System.out.println(encData);
}catch(NoSuchAlgorithmException ex){
ex.printStackTrace();
}catch(NoSuchPaddingException ex){
ex.printStackTrace();
}catch(InvalidKeyException ex){
ex.printStackTrace();
}catch(InvalidAlgorithmParameterException ex){
ex.printStackTrace();
}catch(IllegalBlockSizeException ex){
ex.printStackTrace();
}catch(BadPaddingException ex){
ex.printStackTrace();
}catch(UnsupportedEncodingException ex){
ex.printStackTrace();
}
return encData;
}