随笔-168  评论-223  文章-30  trackbacks-0
  置顶随笔
模板
    1. 空基类优化
    2. 元编程技术
        2.1. 选择API
        2.2. 计算最值
        2.3. 类型选择
    3. 封装GCC原子操作
    4. 定制类对象的内存管理

算法
    1. 排序
        1.1. 改进的快速排序
        1.2. 原位统计排序     
    2. 多叉树
        2.1. 深度优先存储
        2.2. 迭代器的设计
        2.3. 前序遍历
        2.4. 后序遍历
        2.5. 兄弟遍历
        2.6. 叶子遍历
        2.7. 深度遍历 
    3. 优先级队列
        3.1. 原理
        3.2. 内幕
        3.3. 外观
    4. RSA加解密的证明
    5. DSA数字签名的推导
    6. 基于中国剩余定理优化RSA解密推论的证明
    7. 总结AES加密涉及的数学定理
    8. 为什么素检测存在概率多项式时间算法
    9. Blum数的基本定理及应用
    10. 论证有限域上平方根的求解

GUI 
    1. MFC中的WM_COMMAND传递
    2. ATL和WTL中的消息反射
    3. 工作线程与消息循环
    4. 多窗口的组合与分离
        4.1. 接口
        4.2. 实现

跨平台
    1. 用户态自旋锁
    2. 互斥锁
    3. 信号量
    4. socket管道
    5. 锁框架的设计与实现

网络
    1. 运用状态机异步接收变长包
    2. 基于OpenSSL实现的安全连接
    3. TCP/IP FAQ
        3.1. 链路层、网络层和传输层
        3.2. 插口层和应用层
    4. Linux套接字与虚拟文件系统
        4.1. 初始化和创建
        4.2. 操作和销毁
    5. Linux ICMP消息的产生与转换
    6. nginx iocp
        6.1. tcp异步连接
        6.2. udp异步接收
        6.3. scm服务控制
    7. TCP分组丢失时的状态变迁
    8. 基于ENet实现可靠UDP通信的同步模型

Shell应用
    1. 自动生成并安装服务脚本
    2. nginx升级与恢复
    3. 使用awk定位反汇编输出
    4. 自动化批量编译
posted @ 2014-04-10 16:04 春秋十二月 阅读(1894) | 评论 (0)编辑 收藏
  2026年4月8日
 本文解释SM4算法解密时轮密钥为什么要反序,给出S盒的复现构造、安全性分析,以及相关sage代码(SageMath版本为10.7),
安全性分析包括基本代数性质、差分分析表、线性逼近表关于SM4算法的标准,具体参考文献[1]

解密验证
 依文献[1] 解密变换与加密变换使用相同的结构,仅是轮密钥顺序不同,解密时使用轮密钥序(rk31rk30,…,rk0)。先从数学上证明如下
 
 
 再看GMSSL对SM4的实现,验证解密时是否作了反序处理。下面代码从https://github.com/guanzhi/GmSSL/blob/master/src/sm4.c 处拷贝
void sm4_set_encrypt_key(SM4_KEY *key, const uint8_t user_key[16])
{
    uint32_t X0, X1, X2, X3, X4;
    int i;

    X0 = GETU32(user_key     ) ^ FK[0];
    X1 = GETU32(user_key  + 4) ^ FK[1];
    X2 = GETU32(user_key  + 8) ^ FK[2];
    X3 = GETU32(user_key + 12) ^ FK[3];

    for (i = 0; i < 32; i++) {

        X4 = X1 ^ X2 ^ X3 ^ CK[i];
        X4 = S32(X4);
        X4 = X0 ^ L32_(X4);

        key->rk[i] = X4;

        X0 = X1;
        X1 = X2;
        X2 = X3;
        X3 = X4;
    }
}

void sm4_set_decrypt_key(SM4_KEY *key, const uint8_t user_key[16])
{
    uint32_t X0, X1, X2, X3, X4;
    int i;

    X0 = GETU32(user_key     ) ^ FK[0];
    X1 = GETU32(user_key  + 4) ^ FK[1];
    X2 = GETU32(user_key  + 8) ^ FK[2];
    X3 = GETU32(user_key + 12) ^ FK[3];

    for (i = 0; i < 32; i++) {

        X4 = X1 ^ X2 ^ X3 ^ CK[i];
        X4 = S32(X4);
        X4 = X0 ^ L32_(X4);

        key->rk[31 - i] = X4;

        X0 = X1;
        X1 = X2;
        X2 = X3;
        X3 = X4;
    }
}
 可以看到对比加密,在sm4_set_decrypt_key函数内做了反序处理。进一步可以发现sm4_set_decrypt_key被ECB和CBC操作模式调用了,
 比如在https://github.com/guanzhi/GmSSL/blob/master/src/sm4_cbc.c 中的sm4_cbc_decrypt_init函数内
int sm4_cbc_decrypt_init(SM4_CBC_CTX *ctx, const uint8_t key[SM4_BLOCK_SIZE], const uint8_t iv[SM4_BLOCK_SIZE])
{
    if (!ctx || !key || !iv) {
        error_print();
        return -1;
        }
        sm4_set_decrypt_key(&ctx->sm4_key, key);
        memcpy(ctx->iv, iv, SM4_BLOCK_SIZE);
        memset(ctx->block, 0, SM4_BLOCK_SIZE);
        ctx->block_nbytes = 0;
        return 1;
}

 S盒的复现构造
   基本思路是根据文献[2]给出的如下公式及矩阵、向量参数
 
 脚本代码如下
def sm4_sbox(byte):
    v = V([(byte >> i) & 1 for i in range(S_M-1, -1, -1)])

    v1 = A1 * v + C1
    r_byte = sum(int(v1[i]) << i for i in range(S_M-1, -1, -1))
    elem = byte_to_poly(r_byte)

    if elem != 0:
       inv_elem = elem^-1
       inv = poly_to_byte(inv_elem)
    else:
       inv = 0

    v2 = V([(inv >> i)  & 1 for i in range(S_M)])  
    r = A2 * v2 + C2
    return sum(int(r[i]) << (S_M-1-i) for i in range(S_M))

def sm4_sbox_create():
    table = [sm4_sbox(i) for i in range(S_SIZE)]
    return table

def sm4_sbox_print(S):
    print(f"const uint8_t sm4_sbox[{S_SIZE}] = {{")

    for i in range(0, S_SIZE, 16):
        row = "".join(f"0x{s:02X}" for s in S[i:i+16])
        print("    " + row + ",")

    print("};", end="\n\n")

  运行输出如下 
 
 以上输出表格与文献[1] 给出的完全一致

S盒的代数性质
  主要是平衡性、代数次数、非线性度、Walsh谱、差分均分度、SAC、扩散准则PC(k),具体计算根据它们的定义。代码如下
###########################################################
def sbox_balance(S):
    for j in range(S_N):
       cnt = sum((S[i]>>j)&1 for i in range(S_SIZE))
       print(f"Output bit {j}: {cnt} ones")

###########################################################
def max_nonlinearity(n):
    if n % 2 == 0:
        return 2^(n-1) - 2^(n//2 - 1)
    else:
        return 2^(n-1) - 2^((n-1)//2)

def sbox_boolfun_property(S):
    min_nl = infinity

    for j in range(S_N):
        bf = BooleanFunction([(S[i]>>j)&1 for i in range(S_SIZE)])
        deg = bf.algebraic_degree()
        nl = bf.nonlinearity()
        min_nl = min(min_nl, nl)
        walsh_max = max(abs(w) for w in bf.walsh_hadamard_transform())
        print(f"Bit {j}: degree={deg}, nonlinearity={nl}, max|Walsh|={walsh_max}")

    print(f"the minimum nonlinearity is {min_nl}, theory max nonlinearity is {max_nonlinearity(S_N)}")

###########################################################
def sbox_fixed_points(S):
    fps = []
    for x in range(S_SIZE):
        if S[x] == x:
            fps.append(hex(x))
    return fps

###########################################################
def flip_bit(x, i):
    return x ^^ (1 << i)

def sbox_sac(S):
    sac_matrix = matrix(QQ, S_M, S_N, 0)
    for x in range(S_SIZE):
        for i in range(S_M):          
            xp = flip_bit(x, i)
            dx = S[xp] ^^ S[x]      
        
            for j in range(S_N):     
                if (dx >> j) & 1:
                    sac_matrix[i, j] += 1

    # Normalize to probability
    sac_matrix = sac_matrix / S_SIZE
    return sac_matrix

def sbox_check_pck(S, k):
    bool_funcs = []
    bf_satisfy_pcks = []

    for i in range(S_N):
        bf = BooleanFunction([(S[x] >> i) & 1 for x in range(S_SIZE)])
        bool_funcs.append(bf)
        bf_satisfy_pcks.append(True)

    for i, f in enumerate(bool_funcs):
        w = f.walsh_hadamard_transform()

        for a in range(1,  S_SIZE):
            if bin(a).count('1') <= k:
                if w[a] != 0:
                    # D = f.derivative(a)             
                    # if not D.is_balanced():
                    bf_satisfy_pcks[i] = False
                    break               
        r = bf_satisfy_pcks[i]
        print(f"bf[{i}] satify PC({k}):{r}")
 sbox_check_pck函数内注释部分为用布尔函数导数的方法,结果与使用Walsh谱的方法一致。当k=1时等价于SAC。运行脚本,输出如下
 
 可以看出S盒不严格满足PC(k),SAC则是接近满足。其它指标良好。

 S盒的差分分布表
  差分分布表用于计算差分均匀度,及找到最大概率的差分特征。代码如下
 def sbox_ddt_make(S):
     ddt = {}
     for dx in range(1, S_SIZE):
         for x in range(S_SIZE):
             dy = S[x] ^^ S[x^^dx]
             ddt[(dx, dy)] = ddt.get((dx, dy), 0) + 1
     return ddt

def sbox_differential_uniformity(DDT):
    delta = max(DDT.values())
    print("Differential Uniformity =", delta)

###########################################################
DDT = sbox_ddt_make(sbox_table)
sbox_dict_print(DDT); print()

sbox_differential_uniformity(DDT)
 由于表格比较大,就不展示运行输出了

 S盒的线性逼近表
 用于找到最佳逼近(偏差最大)的输入输出线性掩码。代码如下
load("sbox.sage")
from sage.crypto.sbox import SBox

# Note: this method is rather slow
def sbox_lat_make(S):
    lat = {}
    D = 2^(S_M-1)   

    for a in range(S_SIZE):
       v_a = V([(a >> i) & 0x1 for i in range(S_M-1, -1, -1)])
       for b in range(S_SIZE):
            v_b = V([(b >> i) & 0x1 for i in range(S_M-1, -1, -1)])
            for x in range(S_SIZE):
                v_x = V([(x >> i) & 0x1 for i in range(S_M-1, -1, -1)])
                y = S[x]
                v_y = V([(y >> i) & 0x1 for i in range(S_N-1, -1, -1)])
                if v_a.dot_product(v_x) == v_b.dot_product(v_y):
                    lat[(a, b)] = lat.get((a,b), 0) + 1
            lat[(a,b)] -= D
    
    return lat

# LAT = sbox_lat_make(sbox_table)
#
 sbox_dict_print(LAT)

###########################################################
def sbox_best_lat_item(LAT):
    max_val = 0
    best_a, best_b = None, None

    for a in range(1, 256):
        for b in range(1, 256):
            val = abs(LAT[a,b])
            if val > max_val:
               max_val = val
               best_a, best_b = a, b

    print(f"The best lat item is [0x{best_a:02x},0x{best_b:02x}], |bias| is {max_val/256}")

S = SBox(sbox_table)
LAT = S.linear_approximation_table()
print(LAT); print() 

sbox_best_lat_item(LAT)
 由于手写方法构造LAT比较慢,所以采用了内置的SBox实现,两种方法的输出数据是一致的

 完整代码下载:https://github.com/cq12yue/sm4_analysis


 参考文献
   [1] GB/T32907—2016 信息安全技术 SM4分组密码算法
   [2] Algebraic Cryptanalysis of SMS4: Gr¨obner Basis Attack and SAT Attack Compared
posted @ 2026-04-08 13:33 春秋十二月 阅读(112) | 评论 (0)编辑 收藏
  2026年3月17日
从数学上考虑,主要是如下几点
  1. 模数N的两个素因子p、q之间的距离(差的绝对值)要够大。这是为了防费马因子分解法,详见《浅淡密码学几点安全性分析》第一点
  2. p-1 和q-1 要有大的素因子,即它们的素因子分解中最小的素数都得够大。这是为了防Pollard p-1 因子分解法、重复加密攻击 
  3. 解密指数d要比较大。这是为了防连分数方法攻击求解d。详见《简单连分数攻击RSA的迭代次数分析
  4. N的选取应考虑它难以找到二次剩余即x2≡y2 mod N。这是为了防Dixon分解法、二次筛法

从工程上考虑,有以下几点
​  5. RSA系统生成N不要重复。这是为了防共模攻击恢复明文
  6. 不同的N用不同的加密指数e,或不要加密相同的消息,或被加密的多个消息避免有仿射线性关系
  7. 避免暴露N的欧拉函数值。不然解一元二次方程可得到p、q
  8. 随机填充。给明文按一定规则填充随机串后加密,一定程度上可抗击选择明文与选择密文攻击


进一步提升安全性的考虑
  密钥生成KeyGen(κ):
      (N, e, d) ← GenRSA(κ); 
       pk = (N, e), sk = (N, d)
 
  加密过程Epk (M)、解密过程Dsk (C1, C2):
       与抗攻击的安全性有关
 
  H:抗碰撞哈希函数
 
 为抗选择明文攻击,利用H来改造
      Epk(M):
            r ←R ZN*
           输出(re mod N,H(r)⊕M)
     
      Dsk (C1, C2):
            r = C1d mod N
           输出H(r)⊕C2
 
 为抗选择密文攻击(攻击利用RSA的乘法同态性),利用H与IND-CCA安全的私钥加密方案<PrivGen, Enc, Dec>来改造:
      Epk (M):
            r ←R ZN*
            h = H(r)
            输出(re mod N,Ench (M))
     
      Dsk (C1, C2):
            r = C1d mod N
            h = H(r)
            输出Dech(C2)

 以上改造后的两种RSA方案,是可证明安全的。但第一种不支持IND-CCA
posted @ 2026-03-17 23:03 春秋十二月 阅读(47) | 评论 (0)编辑 收藏
  2026年3月4日
先摘自文献[1]中Lattice-based Cryptography章节引用的结论

 
 
 
再对上文三个结论稍作证明如下 

  

   
  
参考文献
  [1]  Post-Quantum Cryptography
  [2]  算法数论                 裴定一 祝跃飞 
  [3]  高等代数                 丘维声
posted @ 2026-03-04 16:41 春秋十二月 阅读(192) | 评论 (0)编辑 收藏
  2026年1月27日
先摘取文献[1]的NTRU密码算法描述 

  
 
 矩阵T及T*的定义如下 

    
 
  

 再给出证明过程 

   



参考文献

   [1]  Post-Quantum Cryptography
posted @ 2026-01-27 18:00 春秋十二月 阅读(127) | 评论 (0)编辑 收藏
  2026年1月25日
符号定义

   

主要结论

   
 

在密码学中的应用

   

    上述McEliece公钥算法成立的关键之一是Gpub=SGP。由前面的定理1可得出Gpub与G等价,
 但隐藏了码结构,另由于矩阵分解Gpub得到S和P是困难的,因为P随机且LU分解变形不唯一,
 当n和t较大时,Goppa码的生成矩阵是天文数字。从而增加了密码分析的难度

   
 上述红色下划线处的结论,其根据是推论1

   
  这里的线性码下界定义本质跟定理7一样,从校验矩阵H的所有列向量中,选取0个向量(即向量0)生成的线性组合数 +
选取1个线性无关向量生成的线性组合数 + 选取2个无关向量生成的线性组合数 + … +
选取d0-1个无关向量生成的线性组合数,不超过r个无关向量生成的线性组合总数。下面解释了红色下划线处的结论
    


参考文献 
 [1] 高等代数                                 丘维声
 [2] Finite fields                            Rudolf Lidl  Harald Niederreiter
 [3] Post-Quantum Cryptography
posted @ 2026-01-25 20:30 春秋十二月 阅读(154) | 评论 (0)编辑 收藏
  2025年9月28日
先摘录文献[1]中的LLL算法描述流程,及LLL约化基的定义 
 
 

LLL约化基的定义如下(文献[1]定义13.12)
 

再证明上图红色方框三行伪代码的正确性(其它部分文献[1]已讲得比较具体)
 


参考文献
 
  [1] 算法数论        裴定一 祝跃飞
  [2] 高等代数        丘维声 
posted @ 2025-09-28 17:43 春秋十二月 阅读(397) | 评论 (0)编辑 收藏
  2025年7月28日




参考文献
  [1]代数与数论       李超     周悦
  [2]抽象代数II       徐明曜  赵春来
posted @ 2025-07-28 12:01 春秋十二月 阅读(468) | 评论 (0)编辑 收藏
  2025年6月20日




参考文献
  [1] 代数学基础与有限域       林东岱
  [2] 抽象代数                     赵春来 徐明曜
posted @ 2025-06-20 18:41 春秋十二月 阅读(590) | 评论 (0)编辑 收藏
  2025年6月5日
符号含义 
 

关于特征的结论 
  
  
  

关于指数和的结论 
  
参考文献
   [1] 代数学基础与有限域         林东岱
   [2] 代数与数论                    李超 周悦
   [3] 关于群的一些结论及应用   本人
posted @ 2025-06-05 09:30 春秋十二月 阅读(281) | 评论 (0)编辑 收藏
  2025年4月25日
   本文主要阐述用两种方法判断给定两个二元二次型是否相似,相似情况下的具体变换。
相似变换如果确定了,也利于判断正定性,因为相似二次型的正定性相同。最后讲到了正交分解,
给出怎么求相似的整数对角矩阵

基本定义
  下述定义来自文献[1] 12.1节,有所扩展 
  

变换求解
  先来看运用解方程的方法 
  

 
 再来看用矩阵的观点方法,求解变换。这种方法更适合求解到对角型的变换
 
 
 

正交分解 
  

  

参考文献
 
   [1] 华罗庚文集数论卷2
   [2] 高等代数                 丘维声
posted @ 2025-04-25 19:05 春秋十二月 阅读(416) | 评论 (0)编辑 收藏
仅列出标题  下一页