LRW算法的相关信息是通过分析LibTomCrypt的LRW得到。LRW也是一种磁盘加密模式。IEEE P1619在2006前使用的还是LRW-AES模式,但在2006年后,由于某些安全原因,LRW-AES被XTS-AES代替。具体情况可以在IEEE的官方网站上查询。LRW是可调密码(tweakable block cipher)。
LRW也用到了有限域GF(2^128),生成多项式和GCM一样是
f(x) = x^128+x^7+x^2+x^1+x^0
输入
[输入] Key 密钥
[输入] P 明文
[输入] IV 输出化向量
[输入] tweak 调整值
[输出] C 密文
步骤:
1. P = P0 || P1 || P2 || …… || Pn Pn已将最后一个分组填充为128bit(填充方式未知)
2. for ( int i = 0; i <= n; i++ ){
}
注意
- +是普通的加法;
- 是GF(2^128)上的加法,即异或;
- 是GF(2^128)上的乘法
解密和加密类似,只是将Ek改为Dk。
为加速运算,实现中对
;
调整为
;
前面一项在预计算阶段就可以计算出来并赋给pad。的做法是每次++pad后再与tweak乘。且此乘法可以采用查表的方式加速。查表方式与XTS一样。
- TomLibCrypt与LRW
LRW的结构体是
typedef struct { // 记录LRW的信息的结构体
int cipher; // 密码算法索引值,128bit分组密码
unsigned char IV[16], // iv 值
tweak[16], // tweak 值
pad[16]; // pad = ( iv + i ) tweak
symmetric_key key; // 扩展密码
#ifdef LRW_TABLES// 如果采用查表法加速运算
unsigned char PC[16][256][16]; // 乘法用的查表
#endif
} symmetric_LRW;
涉及函数包括:
int lrw_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *tweak, int num_rounds, symmetric_LRW *lrw);
int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);
int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);
int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);
int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw);
int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);
int lrw_done(symmetric_LRW *lrw);
int lrw_test(void);
──────────────────────────────────────
int lrw_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *tweak, int num_rounds, symmetric_LRW *lrw)
// [功能] 初始化LRW
- cipher // [输入] 密码算法
- IV // [输入] 初始值
- key // [输入] 密钥
- keylen // [输入] 密钥长度
- tweak // [输入] 调整值
- num_rounds // [输入] 密码算法工作轮数(建议设置为0以使用默认的AES轮数)
- lrw // [输入/输出]LRW状态
//备注:主要做以下几件事情
// 1. 密钥扩展
// 2. 生成tweak的表
// 3. 计算 iv * tweak
──────────────────────────────────────
──────────────────────────────────────
int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);
// [功能] 加密
- pt // [输入]明文
- ct // [输出]密文
- len // [输入]明密文长度
- lrw // [输入/输出] LRW状态
//备注:实际调用的是既可以做加密又可以做解密的lrw_process
──────────────────────────────────────
──────────────────────────────────────
int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);
// [功能] 解密
- ct // [输入] 密文
- pt // [输出] 明文
- len // [输入] 明密文长度
- lrw // [输入/输出]LRW的状态
//备注:实际调用的是既可以做加密又可以做解密的lrw_process
──────────────────────────────────────
──────────────────────────────────────
int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);
// [功能] 加密/解密
- pt // [输入/输出]明文(加密时为输入,解密时为输出)
- ct // [输入/输出]密文(加密时为输出,解密时为输入)
- len // [输入]明密文长度
- mode // [输入] LRW_ENCRYPT表示加密, LRW_DECRYPT表示解密
- lrw // [输入/输出] LRW状态
//备注:实际调用的是既可以做加密又可以做解密的lrw_process
──────────────────────────────────────
──────────────────────────────────────
int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw);
// [功能] 获取IV
- IV // [输出] 初始化向量
- len // [输出] IV长度
- lrw // [输入/输出]LRW的状态
//备注:获取的IV值就是在lrw_start 或者lrw_setiv中设置的IV值
──────────────────────────────────────
──────────────────────────────────────
int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);
// [功能] 设置IV值
- IV // [输入] 初始化向量
- len // [输入] IV长度
- lrw // [输入/输出]LRW的状态
//备注:主要用在仅改变IV值,而key不变的情况下
──────────────────────────────────────
──────────────────────────────────────
int lrw_done(symmetric_LRW *lrw);
// [功能] 完成LRW
- xts // [输入/输出]XTS的状态
//备注:调用算法的done(), 但AES中done()未作任何事情
//建议最好是销毁密钥相关敏感信息
──────────────────────────────────────
──────────────────────────────────────
int lrw_test(void);
// [功能] 测试函数
──────────────────────────────────────