RISC Zero的Babybear域 及其 扩域

1. 引言

前序博客见:

代码实现见:

Babybear域 F p \mathbb{F}_p Fp,其中 p = 2 31 − 2 17 + 1 = 15 ∗ 2 17 + 1 p=2^{31}-2^{17}+1=15*2^{17}+1 p=231217+1=15217+1,取其4-th 扩域 F p 4 \mathbb{F}_{p^4} Fp4的不可约多项式为 x 4 − 11 x^4-11 x411。对应的sagemath验证脚本为:

sage: p=2**31-2**27+1 
....: R.<x> = GF(p)[] 
....: (x^4 - 11).is_irreducible()                                               
True

对应的域定义为:

/// The BabyBear class is an element of the finite field F_p, where P is the
/// prime number 15*2^27 + 1. Put another way, Fp is basically integer
/// arithmetic modulo P.
///
/// The `Fp` datatype is the core type of all of the operations done within the
/// zero knowledge proofs, and is the smallest 'addressable' datatype, and the
/// base type of which all composite types are built. In many ways, one can
/// imagine it as the word size of a very strange architecture.
///
/// This specific prime P was chosen to:
/// - Be less than 2^31 so that it fits within a 32 bit word and doesn't
///   overflow on addition.
/// - Otherwise have as large a power of 2 in the factors of P-1 as possible.
///
/// This last property is useful for number theoretical transforms (the fast
/// fourier transform equivelant on finite fields). See NTT.h for details.
///
/// The Fp class wraps all the standard arithmetic operations to make the finite
/// field elements look basically like ordinary numbers (which they mostly are).
#[derive(Eq, Clone, Copy, Pod, Zeroable)]
#[repr(transparent)]
pub struct Elem(u32); //F_p
/// Alias for the Baby Bear [Elem]
pub type BabyBearElem = Elem;

/// The size of the extension field in elements, 4 in this case.
const EXT_SIZE: usize = 4;

/// Instances of `ExtElem` are elements of a finite field `F_p^4`. They are
/// represented as elements of `F_p[X] / (X^4 - 11)`. This large
/// finite field (about `2^128` elements) is used when the security of
/// operations depends on the size of the field. The field extension `ExtElem`
/// has `Elem` as a subfield, so operations on elements of each are compatible.
/// The irreducible polynomial `x^4 - 11` was chosen because `11` is
/// the smallest choice of `B` for `x^4 - B` that makes this polynomial
/// irreducible.
#[derive(Eq, Clone, Copy, Pod, Zeroable)]
#[repr(transparent)]
pub struct ExtElem([Elem; EXT_SIZE]); //F_{p^4}扩域

/* struct Fp4 {
  /// The elements of Fp4, elems[0] + elems[1]*X + elems[2]*X^2 + elems[3]*x^4
  Fp elems[4];
  ....
  } */

之前将有限域元素表示为:
x ∈ [ 0 , N − 1 ] x\in [0,N-1] x[0,N1]

而Montgomery Form表示定义为:
[ x ] = ( x R ) m o d    N [x]=(xR)\mod N [x]=(xR)modN

Montgomery Reduction算法计算的是:
R E D C ( u ) = ( u R − 1 ) m o d    N REDC(u)=(uR^{-1})\mod N REDC(u)=(uR1)modN
而不是之前Barrett Reduction计算的 u m o d    N u\mod N umodN

R E D C REDC REDC是一个非常多功能的公式:

  • 1)将经典转换为Montgomery: [ x ] = R E D C ( ( x R 2 ) m o d    N ) [x]=REDC((xR^2)\mod N) [x]=REDC((xR2)modN)
  • 2)将Montgomery转换为经典: R E D C ( [ x ] ) = x REDC([x])=x REDC([x])=x
  • 3)对Montgomery Form表示的乘法运算: ( ( x R m o d    N ) ∗ ( y R m o d    N ) ∗ R − 1 m o d    N ) = ( x y R ) m o d    N ((xR\mod N)*(yR\mod N)*R^{-1}\mod N)=(xyR)\mod N ((xRmodN)(yRmodN)R1modN)=(xyR)modN

根据 有限域的Fast Multiplication和Modular Reduction算法实现,BabyBear域运算采用Montgomery形式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
鉴于单个Babybear域元素可 以32位整数表示,2个Babybear域元素 0 ≤ u , v < p 0\leq u,v <p 0u,v<p 乘积可 以64位整数表示,且无需考虑进位情况。对应为:

  • b = 2 32 b=2^{32} b=232
  • n = 1 n=1 n=1
  • R = b n = 2 32 R=b^n=2^{32} R=bn=232
  • 实际代码实现时,由于 n = 1 n=1 n=1,可预计算出相应的R2值为mod(r^2, p),相应的M值为mod(1/p,r)
sage: p=2**31-2**27+1 
sage: r=2**32                                                                   
sage: mod(r^2, p)                                                               
1172168163
sage: mod(1/p,r)                                                                
2281701377
sage: hex(2281701377)                                                           
'0x88000001'
/// Wrapping multiplication of [Elem]  using Baby Bear field modulus
// Copied from the C++ implementation (fp.h)
const fn mul(lhs: u32, rhs: u32) -> u32 {
    
    
    // uint64_t o64 = uint64_t(a) * uint64_t(b);
    let mut o64: u64 = (lhs as u64).wrapping_mul(rhs as u64);
    // uint32_t low = -uint32_t(o64);
    let low: u32 = 0u32.wrapping_sub(o64 as u32);
    // uint32_t red = M * low;
    let red = M.wrapping_mul(low);
    // o64 += uint64_t(red) * uint64_t(P);
    o64 += (red as u64).wrapping_mul(P_U64);
    // uint32_t ret = o64 >> 32;
    let ret = (o64 >> 32) as u32;
    // return (ret >= P ? ret - P : ret);
    if ret >= P {
    
    
        ret - P
    } else {
    
    
        ret
    }
}

/// Encode to Montgomery form from direct form.
const fn encode(a: u32) -> u32 {
    
    
    mul(R2, a)
}

/// Decode from Montgomery form from direct form.
const fn decode(a: u32) -> u32 {
    
    
    mul(1, a)
}

RISC Zero系列博客

猜你喜欢

转载自blog.csdn.net/mutourend/article/details/135342571