国密SM2算法并不仅仅是提供了新的曲线参数,而是在算法上对ECC进行了修改。
SM2的曲线使用了Weierstrass模型:
y
2
=
x
3
+
a
x
+
b
m
o
d
P
y^2=x^3+ax+b \mod P
y2=x3+ax+bmodP
p=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
a=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC
b=28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93
n=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123
Gx=32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7
Gy=BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0
椭圆曲线是关于x轴对称的,点和字节数据转换时,y坐标只需要获取/提供正负即可。
PC(Padding Char) = 02或03;
int nLsbY = epoint_get(epointC1, bigX, bigX);
if (0 == nLsbY)
{
PC = 2;
}
else // 1 == nLsbY
{
PC = 3;
}
S = PC || bigX;
PC = 04
PC = 04;
S = PC || X1 || Y1;
PC = 06或07
int nLsbY = epoint_get(epointC1, bigX, bigY);
if (0 == nLsbY)
{
PC = 6;
}
else // 1 == nLsbY
{
PC = 7;
}
S = PC || bigX || bigY;
int KDF(const uint8_t* pData
, uint32_t nData
, uint32_t nKeyBytesLen
, PFnHash pfnHash
, uint32_t nHash
, uint8_t* pOut )
{
int nRet = 0;
uint32_t nLoop = 0;
uint32_t zt = 1;
uint32_t i = 0;
uint8_t *pBuf = NULL;
uint32_t nBuf = nData + 4/*sizeof(zt)*/;
if (!pData || !pOut)
{
return 0;
}
// alloc memory
pBuf = (uint8_t *)calloc(nBuf, 1);
if(!pBuf) return 0;
memcpy(pBuf, pData, nData);
nLoop = (nKeyBytesLen + nHash - 1) / nHash; // upper(nKeyBytesLen/nHash)
for (i = 0; i < nLoop; ++i)
{
u32to8_big(&(pBuf[nData]), zt);
if (ERR_OK != pfnHash(pBuf, nBuf
, pOut + i * nHash, nHash))
{
break;
}
++zt;
}
if (i == nLoop)
{
nRet = nKeyBytesLen;
}
return nRet;
}
官网加解密示例使用了未压缩的转换方式。
https://github.com/C0deStarr/CryptoImp/tree/main/pubkey/ecc
国家密码管理局关于发布《SM2椭圆曲线公钥密码算法》公告(国密局公告第21号)_国家密码管理局 (sca.gov.cn)