java - 我应该如何直接使用 UTF8 或 UTF16 随机生成一个固定长度的字符串变量?
问题描述
所以这是我的代码,它基本上会生成一个用于加密的盐。为了生成随机字符,我只是使用了一个预先声明的字符串变量来保存所有字符,因此代码会根据预先声明的变量生成字符串输出
但是,我认为如果我使用一组更大的密钥(例如 UTF8 或 16)来生成盐,结果可能不会那么随机。
static final String keychain = "0123456789qwertyuioasdfghjklzxcvbnm,.+_=-][}{;:></?'|!@#$%^&*()坢坣坥坧坨坩坪坫坬坭坮" ;
static SecureRandom randomValue = new SecureRandom();
public static String GetRandomSalt(){
StringBuilder constructsalt = new StringBuilder(16);
for (int i = 0; i < 16; i ++){
constructsalt.append(keychain.charAt(randomValue.nextInt(keychain.length())));
}
System.out.println(constructsalt.toString());
return constructsalt.toString();
}
那么是否可以参考上面的代码使用 UTF8/16 密钥集直接生成一个随机固定长度的字符串?
解决方案
但是,我认为如果我使用一组更大的密钥(例如 UTF8 或 16)来生成盐,结果可能不会那么随机。
你似乎很困惑。
加密完全在字节上完成。不是字符。字节是数字,从 0 到 255。仅此而已。
但是,如果需要,您可以将字符转换为字节。没有一种固定的方法可以做到这一点。US-ASCII 是一种方式(仅定义 96 个字符,映射到范围 32-127)。UTF-8 是另一种。大多数编码具有不能产生每个可以想象的可能字节序列的特性。只是其中的一个子集。这对加密来说是个坏消息,因此请避免使用字符串。时期。(对于几乎所有的编码,有些字节序列永远不会是将字符串转换为字节的结果)。
getRandomSalt
返回字符串的事实?
你搞砸了。那是错误的。它应该返回byte[]
。
许多加密工具、API 和教程似乎确实使用了字符串。这有两个独立的、同样愚蠢的起源:
对字符集的误解
一大堆编程语言随便模糊了字符串和一袋字节之间的区别,并且无法区分 和 之间的"Hello"
区别[0,72, 101, 108, 108, 111]
。这是一个非常愚蠢的想法——除了英语倾向于使用的字符之外,还有更多的字符,并且整个 unicode 符号集不适合 0-255 范围;毕竟,有超过 256 个独特的字符。
幸运的是,Java 并不是一种愚蠢的语言。byte[] 和 String 不可互换,因此,使该方法返回一个byte[]
.
更容易转移到人的眼球
读 Hello 比读 0、72、101、108、108、111 容易得多。但是,最好的情况、令人困惑的情况和最坏的情况,将事物保留为字符串会严重降低您的键和盐的能力表达随机性。这很糟糕。
因此,这替换了您粘贴在问题中的所有代码,并且非常优越:
public byte[] getRandomSalt() {
byte[] salt = new byte[16];
random.nextBytes(salt);
return salt;
}
推荐阅读
- r - gtsummary 中是否有一个函数可以将 R2、N 和 F 统计量添加到包含多个模型的输出表中?
- flutter - 如何使用流构建器从我的消息集合中的最后一个消息字段返回消息
- c++ - 编译器错误:“非静态成员引用必须相对于特定对象”
- c++ - 让 OpenCV 在 MacOS 上的 CLion 中运行很难
- sql - search line break in several tables and get the rowid
- audio - 如何流式传输桌面声音而不是与 obs 的传入语音聊天
- python - Venv 未包装导致找不到模块的第三方库
- python - 填充通过检查不同数据框的列之间添加的新列
- php - Laravel 8 不会从数据库中删除数据
- c# - C# ASP.NET Core 替代扩展方法来注册服务