Delphi / 算法 · 2024年1月12日

国密算法SM2签名验证中的压缩公钥还原

在项目中,经常会遇到接口要求进行验签的动作;SM2签名算法属于非对称密钥算法;需要使用公钥进行验签;JAVA平台生成的公钥很多是压缩公钥(03开头的16进制字符串),需要在平台数据回应时使用公钥进行验签,以保证数据的安全性;

采用CnPack组织开发的Cnvcl包中的密钥算法单元 CnSM2.Pas

uses
  CnSM2;
  
  
function VerifySign(AID, APublicKey, ASrc, ASign : string):Boolean;
var
  _SM2Ecc : TCnSM2;
  _SM2PublicKey : TCnSM2PublicKey;
  _SM2Signature : TCnSM2Signature;
  _Bytes : TBytes;
  _sStr : string;
begin
  Result := False;
  _SM2PublicKey := TCnSM2PublicKey.Create;
  _SM2Signature := TCnSM2Signature.Create;
  _SM2Ecc := TCnSM2.Create;
  try
    try
      //将签名原文赋值给数组_Bytes
      setlength(_Bytes, Length(ASrc));
      Move(ASrc[1], _Bytes[0], Length(ASrc));
      //将SM2的签名赋值给_SM2Signature
      _SM2Signature.SetAsn1Hex(ASign);
      //加载压缩公钥(03开头),需要额外传入椭圆曲线TCnSM2;如果是普通公钥(04开头),则不需要传入椭圆曲线TCnSM2
      _SM2PublicKey.SetHex(trim('036392c9db2dc1c1e24ab1aac7591a0b680de18e50a2e8bace829278c97b12100d'), _SM2Ecc);
      //验证签名
      if CnSM2.CnSM2VerifyData(AID,           //'1111111111111111',
                               _Bytes,
                               _SM2Signature,
                               _SM2PublicKey,
                               nil) then
      begin
        Result := True;
      end
      else
      begin
        //记录日志
        AddLog(Format('VerifySign 签名验证 - %s',['FAIL']) ,llMessage);
      end;
    except
      on E:Exception do
      begin
        //记录日志
        AddLog(Format('VerifySign Err - %s',[E.Message]) ,llAlert);
      end;
    end;
  finally
    if Assigned(_SM2PublicKey) then FreeAndNil(_SM2PublicKey);
    if Assigned(_SM2Signature) then FreeAndNil(_SM2Signature);
    if Assigned(_SM2Ecc) then FreeAndNil(_SM2Ecc);
    
  end;
end;
Pascal