c++ - RC6 实施给出了不希望的结果
问题描述
我正在尝试从论文中获得 RC6 实现。我已经仔细检查了论文中的算法,虽然我怀疑是密钥调度,但不确定我哪里出错了。
我目前的输出是这样的:
平原:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
密钥:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
加密:30 48 87 4e 00 69 ff 12 da 49 ad 9c 50 8a 0c 96
解密:80 53 4a d9 78 b9 37 54 64 8f d4 1d e0 10 56 5d
试图从论文中获得第一个测试向量:
明文 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
用户密钥 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
密文 8f c3 a5 36 56 b1 f7 78 c1 29 df 4e 98 48 a4 1e
#pragma once
#include <cmath>
#include <cstdio>
#include <vector>
#include <limits>
#include "types.h"
using std::max;
using std::ceil;
using std::pow;
using std::vector;
using std::numeric_limits;
// Binary expansion of e - 2
template<class T> static const T P =
T(ceil((M_E - 2) * pow(2, numeric_limits<T>::digits)));
// Binary expansion of ϕ - 1 where ϕ is the golden ratio
template<class T> static const T Q =
T(((1.618033988749895 - 1) * pow(2, numeric_limits<T>::digits)));
class rc6 {
private:
// Used for indices on blocks to match paper
enum {
A = 0,
B = 1,
C = 2,
D = 3
};
static const unsigned MAX_KEY_LEN = 2040;
/**
* Rotate a N-bit value left
* @param word: value to rotate
* @param shift: bits to roll
*/
template<class T> static inline T rol(T word, unsigned shift)
{
return (word << shift) | (word >> (numeric_limits<T>::digits - shift));
}
/**
* Rotate a N-bit value right
* @param word: value to rotate
* @param shift: bits to roll
*/
template<class T> static inline T ror(T word, unsigned shift)
{
return (word >> shift) | (word << (numeric_limits<T>::digits - shift));
}
/**
* Create key schedule @S from input @key
* @param key: key bytes
* @param S: destination for key schedule
* @param r: number of rounds
*/
template<class T> static void key_schedule(vector<u8>& key, vector<T>& S, unsigned r = 20) {
// The user supplies a key of b bytes
unsigned b = key.size() * sizeof(T);
unsigned b_bits = b * 8;
if (b > MAX_KEY_LEN)
fprintf(stderr, "ERROR: Key can't be greater than 2040 bits, got %u.\n", b_bits);
// Sufficient zero bytes are appended to give a key length equal to a non-zero
// integral number of words
for ( ; key.size() % sizeof(T) != 0; b++)
key.push_back(0x00);
// key bytes are then loaded in little-endian fashion into an array of c w-bit
// words L[0], ..., L[c - 1]
const unsigned c = key.size();
vector<T> L(key.data(), static_cast<u8*>(key.data()) + b);
const unsigned v = 3 * max(c, 2 * r + 4);
unsigned i = 0, j = 0;
S[0] = P<T>;
for (i = 1; i < 2 * r + 3; i++)
S[i] = S[i - 1] + Q<T>;
i = 0;
unsigned A = 0, B = 0;
for (unsigned s = 1; s <= v; s++) {
A = S[i] = rol(S[i] + A + B, 3);
B = L[j] = rol(L[j] + A + B, A + B);
i = (i + 1) % (2 * r + 4);
j = (j + 1) % c;
}
}
public:
/**
* Encrypt @plaintext using @key for @r rounds
* @param plaintext: plain text to encrypt
* @param key: key bytes
* @param r: number of rounds
*/
template<class T> static void encrypt(vector<T>& plaintext, vector<u8>& key, unsigned r = 20)
{
vector<T> S(2 * r + 4);
key_schedule(key, S, r);
unsigned w = numeric_limits<T>::digits;
for (auto block = plaintext.begin(); block != plaintext.end(); block += 4) {
block[B] += S[0];
block[D] += S[1];
for (unsigned i = 1; i <= r; i++) {
T t = rol(block[B] * (2 * block[B] + 1), log2(w));
T u = rol(block[D] * (2 * block[D] + 1), log2(w));
block[A] = rol((block[A] ^ t), u) + S[2 * i];
block[C] = rol((block[C] ^ u), t) + S[2 * i + 1];
T a = block[A];
block[A] = block[B];
block[B] = block[C];
block[C] = block[D];
block[D] = a;
}
block[A] += S[2 * r + 2];
block[C] += S[2 * r + 3];
}
}
/**
* Decrypt @ciphertext using @key for @r rounds
* @param plaintext: plain text to encrypt
* @param key: key bytes
* @param r: number of rounds
*/
template<class T> static void decrypt(vector<T>& ciphertext, vector<u8>& key, unsigned r = 20)
{
vector<T> S(2 * r + 4);
key_schedule(key, S, r);
unsigned w = std::numeric_limits<T>::digits;
for (auto block = ciphertext.begin(); block != ciphertext.end(); block += 4) {
for (unsigned i = r; i > 0; i--) {
T d = block[D];
block[D] = block[C];
block[C] = block[B];
block[B] = block[A];
block[A] = d;
T u = rol(block[D] * (2 * block[D] + 1), log2(w));
T t = rol(block[B] * (2 * block[B] + 1), log2(w));
block[C] = ror(block[C] - S[2 * i + 1], t) ^ u;
block[A] = ror(block[A] - S[2 * i], u) ^ t;
}
block[D] -= S[1];
block[B] -= S[0];
}
}
};
解决方案
推荐阅读
- bison - 如何在 BISON 中访问,在 FLEX 中使用 REJECT 拒绝的令牌?
- javascript - 未捕获的类型错误:无法读取 jQuery 中未定义的属性“拆分”
- javascript - 一种无需传递 `.this` 作为参数即可检索上下文的方法
- r - group_by() 和 n() 的不同结果(paste0)
- .net - 替换 XML 文件中的值
- swift - Swift Realm - 一对多过滤器查询
- windows - 允许编辑但阻止删除文件
- spring - 招摇 2.6.1 /swagger-resources/configuration/ui 404
- javascript - React Native CheckBox 和 FlatList:无法切换,并且每个项目只能选择一次
- php - 用于 php 的 ffmpeg 命令无法在实时服务器上运行