- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在用 Java 构建 Blowfish 密码算法。我使用 these 测试 vector 来查看它是否有效,我发现了最糟糕的情况 - 它适用于某些输入而不适用于其他输入。
我使用 Blowfish paper 作为创建实现的指南。下面是它的相关部分。
public class Blowfish {
// Binary Digits of Pi
// ...
private static final int N = 16;
private final long S[][] = new long[4][256];
private final long P[] = new long[N + 2];
布鲁斯说:
(1) 先初始化P-array,再初始化四个S-box,依次用固定的字符串。此字符串由 pi 的十六进制数字组成(减去开头的 3)
public void keyExpansion(String key) {
System.arraycopy(p, 0, P, 0, N + 2);
for (int i = 0; i < 4; i++) {
System.arraycopy(s[i], 0, S[i], 0, 256);
}
我意识到这不是真正可读的,但是小写的 p[]
和 s[][]
包含固定值(pi 的十六进制数字)和大写的 P[]
和 S[][]
是 Blowfish 对象的属性,它们会发生变化。
布鲁斯说:
(2) P1 与 key 的前 32 位异或,P2 与 key 的后 32 位异或,依此类推 key 的所有位(可能直到 P14)。重复循环键位,直到整个 P 数组都与键位进行了异或。
for (int i = 0; i < N + 2; i++) {
int begin = (i * 8) % key.length();
int end = ((i + 1) * 8) % key.length();
String keySubstring;
if (begin < end) {
keySubstring = key.substring(begin, end);
} else {
keySubstring = key.substring(begin) + key.substring(0, end);
}
long keyChunk = Long.parseLong(keySubstring, 16);
P[i] ^= keyChunk;
}
由于 key 长度可变(最多 56 个字节),我想出了最简单的方法来传递它是一个字符串。也许我应该使用 BigInteger?
布鲁斯说:
(3) 使用 Blowfish 算法加密全零字符串,使用 步骤 (1) 和 (2) 中描述的子项。
(4) 将 P1 和 P2 替换为步骤 (3) 的输出。
(5) 使用 Blowfish 算法加密步骤 (3) 的输出 修改子项。
(6) 将 P3 和 P4 替换为步骤 (5) 的输出。
(7) 继续这个过程,替换 P 数组的所有条目,并且 然后按顺序排列所有四个 S-box,输出为 连续变化的 Blowfish 算法。
long e = 0;
for (int i = 0; i < N + 2; i += 2) {
e = encrypt(e);
long eL = trim(e >>> 32);
long eR = trim(e);
P[i] = eL;
P[i + 1] = eR;
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 256; j += 2) {
e = encrypt(e);
long eL = trim(e >>> 32);
long eR = trim(e);
S[i][j] = eL;
S[i][j + 1] = eR;
}
}
现在是提及我的辅助函数 trim
的好时机,它删除了更高的 32 位。
private static long trim(long value) {
return value & 0xFFFFFFFFL;
}
布鲁斯说:
Blowfish 是一个由 16 轮组成的 Feistel 网络。输入是 64 位数据元素 x。
将 x 分成两个 32 位的一半:xL、xR
对于 i = 1 到 16:
xL = xL XOR Pi
xR = F(xL) XOR xR
交换 xL 和 xR
下一个
交换 xL 和 xR(撤消上次交换。)
xR = xR XOR P17
xL = xL XOR P18
重组 xL 和 xR
public long encrypt(long plaintext) {
long xL = trim(plaintext >>> 32);
long xR = trim(plaintext);
for (int i = 0; i < N; i++) {
xL = xL ^ P[i];
xR = F(xL) ^ xR;
//swap
xL = xL + xR;
xR = xL - xR;
xL = xL - xR;
}
//swap
xL = xL + xR;
xR = xL - xR;
xL = xL - xR;
//final step
xR = xR ^ P[N];
xL = xL ^ P[N + 1];
return (xL << 32) | xR;
}
}
我只是针对上述测试 vector 运行此代码,如下所示:
public void testBlowfish() {
long key[] = {
...
};
long clear[] = {
...
};
long cipher[] = {
...
};
Blowfish b = new Blowfish();
for (int i = 0; i < 34; i++) {
b.keyExpansion(Long.toHexString(key[i]));
long result = b.encrypt(clear[i]);
if (result == cipher[i]) {
System.out.println("Test " + i + " passed!");
} else {
System.out.println("Test " + i + " failed: ");
System.out.println("\tKey:\t" + Long.toHexString(key[i]));
System.out.println("\tClear:\t" + Long.toHexString(clear[i]));
System.out.println("\tCipher:\t" + Long.toHexString(cipher[i]));
System.out.println("\tResult:\t" + Long.toHexString(result));
}
}
}
测试结果如下:
Test 0 passed!
Test 1 passed!
Test 2 passed!
Test 3 passed!
Test 4 failed:
Key: 123456789abcdef
Clear: 1111111111111111
Cipher: 61f9c3802281b096
Result: 65a2dfe88702a6bf
Test 5 passed!
Test 6 passed!
Test 7 passed!
Test 8 passed!
Test 9 failed:
Key: 131d9619dc1376e
Clear: 5cd54ca83def57da
Cipher: b1b8cc0b250f09a0
Result: fbd7e706e563d21a
Test 10 failed:
Key: 7a1133e4a0b2686
Clear: 248d43806f67172
Cipher: 1730e5778bea1da4
Result: 7d11a2563bbf76f1
Test 11 passed!
Test 12 failed:
Key: 4b915ba43feb5b6
Clear: 42fd443059577fa2
Cipher: 353882b109ce8f1a
Result: d747d42ef2bc89c0
Test 13 failed:
Key: 113b970fd34f2ce
Clear: 59b5e0851cf143a
Cipher: 48f4d0884c379918
Result: c559acf605825008
Test 14 failed:
Key: 170f175468fb5e6
Clear: 756d8e0774761d2
Cipher: 432193b78951fc98
Result: 8761d08e81a796d
Test 15 passed!
Test 16 failed:
Key: 7a7137045da2a16
Clear: 3bdd119049372802
Cipher: 2eedda93ffd39c79
Result: db47a054a5a0d496
Test 17 failed:
Key: 4689104c2fd3b2f
Clear: 26955f6835af609a
Cipher: d887e0393c2da6e3
Result: 40f96e5f9f3affe1
Test 18 passed!
Test 19 passed!
Test 20 passed!
Test 21 failed:
Key: 25816164629b007
Clear: 480d39006ee762f2
Cipher: 7555ae39f59b87bd
Result: a6cb030922383650
Test 22 passed!
Test 23 passed!
Test 24 passed!
Test 25 failed:
Key: 18310dc409b26d6
Clear: 1d9d5c5018f728c2
Cipher: d1abb290658bc778
Result: d45634df2f8eb002
Test 26 passed!
Test 27 failed:
Key: 101010101010101
Clear: 123456789abcdef
Cipher: fa34ec4847b268b2
Result: 30ce63f436ff5475
Test 28 passed!
Test 29 passed!
Test 30 passed!
Test 31 passed!
Test 32 failed:
Key: 123456789abcdef
Clear: 0
Cipher: 245946885754369a
Result: 291c4bd096af70e5
Test 33 passed!
正如我所说,有些输入有效,有些无效。而且我不明白为什么,这对我来说似乎很武断,我拒绝生活在计算机可以做出武断决定的世界里。换句话说,错误在哪里?
最佳答案
正如建议的那样,我在转换中丢失了前导零。实现很好,但在测试行中
b.keyExpansion(Long.toHexString(key[i]));
导致错误。替换为
b.keyExpansion(String.format("%016x", key[i]));
成功了。
现在看起来很明显,因为每个失败的测试至少有一个前导零。
出于某种原因,我假设每个键都将超过 8 个字节。为了让 keyExpansion
为短键工作,我将 reading from key 改成了这样:
for (int i = 0; i < N + 2; i++) {
StringBuilder keySubstring = new StringBuilder();
for (int j = 0; j < 8; j++) {
int index = (i * 8 + j) % key.length();
keySubstring.append(key.charAt(index));
}
long keyChunk = Long.parseLong(keySubstring.toString(), 16);
P[i] ^= keyChunk;
}
关于java - Java 中的 Blowfish 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45520635/
我似乎找不到差异的来源。我在这个在线解密工具中发现了这种差异 http://www.tools4noobs.com/online_tools/decrypt/ 我有一些加密的 Blowfish 数据,
C++ blowfish 支持加密少于 C# NET BlowfishC++ Blowfish<-- 在 C++ 和 C# 应用程序中,我加密了以下数组 byte response[6] =
我必须实现java密码空间填充。我正在尝试编写支持 Blowfish/CBC/space 模式的 Perl 代码的实现。我在Java Cipher列表中找不到相关模式,仅支持PCK5Padding和N
我正在使用 Blowfish 实现一个简单的密码存储。一切都很好,直到我尝试了几种不同的密码/ key 组合,并遇到了许多解密值仍然是垃圾的情况。 下面是一个演示该问题的独立类。我得到以下输出: 'A
我正在做一个关于图像加密的项目。我们在图像上使用河豚加密。根据 Paul Kocher 的代码 http://www.schneier.com/blowfish-download.html 。主要功能
在将此标记为重复之前,请理解我在 stackoverflow 上找不到任何关于河豚的有用信息。我正在尝试使用 Android Studio 使用河豚加密和解密字符串。我的加密似乎有效。但是当我尝试解密
我正在尝试通过Blowfish解密十六进制编码的字符串。但结果与正确的不同。 String s="a1d0534e4baf9e670bde8670caee8b87" String decKey = "
我今天一整天都在尝试找出如何读取二进制文件并对其进行解密。 在我的文件中,前 4 个字节描述文件格式,后 32 个字节是 header ,使用 Blowfish 加密。 所以我写了这段代码来做到这一点
我用 Blowfish 编码做了一些测试,发现了一些东西。编码后的字符串并不总是与源字符串一样长。有时会更短。 如果我想解码编码字符串,我需要在 openssl 函数中解码的长度: BF_cfb64_
我正在将 C++ TCP 客户端翻译成 C#。该客户端用于使用河豚对数组的 4 个字节进行编码。 C++ Blowfish C# Blowfish(C# NET) C++ BYTE respo
我正在尝试让一个 bowfish 函数用于简单的字符缓冲区。当我尝试解密加密缓冲区并在 EVP_CipherFinal_ex() 调用上失败时,程序失败。 #include #include #i
我正在用 Blowfish 算法加密我的文件,但我似乎对此一无所知。每当我尝试 Encipher() 时,它都会抛出一个异常,提示“无效长度”。我认为当它用 8 进行模数时,长度必须为零,我认为这
许多脚本语言(Python/PHP/等...)包含允许您使用 Blowfish 作为密码单向散列的功能(有时通过扩展)。我正在尝试为 C++ 找到类似的实现,但我遇到的一切都是加密/解密解决方案。 有
我一直在研究在 php 应用程序中保护密码的更好程序。形式上我会使用类似的东西(只是一个例子,不要开枪!): $salt = md5(rand() . md5(rand() . '$%E$%SDRT'
无法解密使用 Blowfish 在 Go 语言中加密的 Java 密文。 加密 import ( "testing" "golang.org/x/crypto/blowfish"
考虑以下执行 Blowfish 加密的方法: import javax.crypto.Cipher; import javax.crypto.Mac; import javax.crypto.spec
我们有一个类,它包装 BouncyCaSTLe(实际上是 Android 的 SpongyCaSTLe)Blowfish,以加密要传输的数据: public class BlowfishOutputS
Blowfish 能够进行强加密,并且可以使用最大 56 字节的 key (448 位 key )。 key 必须是 8 字节的倍数(最多 56)。 我想编写一个示例,它将自动填充和取消填充键的大小。
这是加密和解密消息的基本代码: #include #include #include //gcc cryptage.c -o cryptage -lcrypto int main(){ BF_K
我很难弄清楚如何使用 C# bouncycaSTLe 库来解密河豚 CTR 密文。由于缺少关于如何使用它的 BC 文档,我不知道如何使用它 我广泛搜索但没有在堆栈溢出中找到类似的东西,如果您有一些关于
我是一名优秀的程序员,十分优秀!