实验一-密码引擎-加密API实现与测试

任务详情

1 下载并查找GMT 0018-2012密码设备应用接口规范原始文档进行学习 (5分)
2 实现GMT 0018-2012密码设备应用接口规范的接口函数,至少实现:
1)设备管理中的打开设备,关闭设备,获取设备信息,产生随机数(4分)
2)密钥管理导出 ECC 签名公钥;SDF _ ExportSignPublicKey _ ECC I.导出 ECC加密公钥∶SDF_ExportEncPublicKey_ECC J. 产生 ECC非对称密钥对并输出∶SDF_ GenerateKeyPair_ ECC
K. (6分)
3)非对称算法(至少支持SM2):外部密钥 ECC验证∶SDF_ ExternalVerify_ECC ,内部密钥 ECC签名;SDF_ InternalSign_ECC ,内部密钥 ECC验证∶SDF_ InternalVerify_ ECC 外部密钥 ECC加密∶SDF_ ExternalEncrypt _ ECC(8分)
4)对称算法(至少支持SM4)∶SDF _ Encrypt 对称解密∶SDF _ Dccrypt 计算 MAC∶SDF _ CalculateMAC(6分)
5)杂凑算法(至少支持SM3):· 杂凑运算初始化∶SDF _ HashInit· 多包杂凑运算∶SDF_ HashUpdate· 杂凑运算结束∶SDF _ HashFinal(6分)

密钥管理要求(10分)
基于本标准设计、开发的密码设备在密钥管理方面,应满足以下要求; 1)设备密钥的使用不对应用系统开放; 2) 密钥必须用安全的方法产生并存储;
3) 在任何时间、任何情况下,除公钥外的密钥均不能以明文形式出现在密码设备外; 4) 密码设备内部存储的密钥应具备有效的密钥保护机制,防止解剖、探测和非法读取; 5) 密码设备内部存储的密钥应具备权限控制机制,防止非法使用和导出。

设备状态要求(5分)
基于本标准设计、开发的密码设备在设备状态方面,应满足以下要求; 1) 密码设备应具有初始和就绪两个状态;
2) 未安装设备密钥的密码设备应处干初始状态,已安装设备密钥的密码设备应处于就绪状态; 3) 在初始状态下,除可读取设备信息、设备密钥的生成或恢复操作外,不能执行任何操作,生成或恢复设备密钥后,密码设备处于就绪状态;
4) 在就绪状态下,除设备密钥的生成或恢复操作外,应能执行任何操作; 5) 在就绪状态下进行的密钥操作,设备操作员应经过密码设备的认证。

1 下载并查找GMT 0018-2012密码设备应用接口规范原始文档进行学习

本标准的目标是为公钥密码基础设施应用体系框架下的服务类密码设备制定统一的应用接口标准,通过该接口调用密码设备,向上层提供基础密码服务。为该类密码设备的开发、使用及检测提供标准依据和指导,有利于提高该类密码设备的产品化、标准化和系列化水平。
在公钥密码基础设施应用技术体系框架中,密码设备服务层由密码机、密码卡、智能密码终端等设备组成,通过该标准规定的密码设备应用接口向通用密码服务层提供基础密码服务,如下图所示:

  • 基础密码服务包括密钥生成、单一的密码运算、文件管理等服务。

  • 本标准采用C语言描述接口函数,无特别说明时,函数中参数的长度单位均为字节数。

设备管理类函数

  • 打开设备:SDF_OpenDevice

  • 关闭设备:SDF_CloseDevice

  • 创建会话:SDF_OpenSession

  • 关闭会话:SDF_CloseSession

  • 获取设备信息:SDF_GetDeviceInfo

  • 产生随机数:SDF_GenerateRandom

  • 获取私钥使用权限:SDF_GetPrivateKeyAccessRight

  • 释放私钥使用权限:SDF_ReleasePrivateKeyAccessRight

密钥管理类函数

  • 导出 RSA 签名公钥:SDF_ExportSignPublicKey_RSA

  • 导出 RSA 加密公钥:SDF_ExportEncPublicKey_RSA

  • 产生RSA非对称密钥对并输出:SDF_GenerateKeyPair_RSA

  • 生成会话密钥并用内部RSA公钥加密输出:SDF_GenerateKeyWithIPK_RSA

  • 生成会话密钥并用外部RSA公钥加密输出:SDF_GenerateKeyWithEPK_RSA - 导人会话密钥并用内部RSA私钥解密:SDF_ImportKeyWithISK_RSA

  • 基于 RSA 算法的数宇倍封转换:SDF_ExchangeDigitEnvelopeBaseOnRSA

  • 导出 ECC 签名公钥:SDF_ExportSignPublicKey_ECC

  • 导出 ECC 加密公钥:SDF_ExportEncPublicKey_ECC

  • 产生ECC非对称密钥对并输出:SDF_GenerateKeyPair_ECC

  • 生成会话密钥并用内部ECC公钥加密输岀:SDF_GenerateKeyWithIPK_ECC - 生成会话密钥并用外部ECC公钥加密输出:SDF_GenerateKeyWithEPK_ECC

  • 导入会话密钥并用内部ECC私钥解密:SDFJmportKeyWithlSKJECC

  • 生成密钥协商参数并输出:SDF_GenerateAgreementDataWithECC

  • 计算会话密钥:SDF_GenerateKey WithECC

  • 产生协商数据并计算会话密钥:SDF—GenerateAgreementDataAndKeyWithECC

  • 基于 ECC算法的数字信封转换:SDF_ExchangeDigitEnvelopeBaseOnECC

  • 生成会话密钥并用密钥加密密钥加密输出: SDF_GenerateKeyWithKEK

  • 导入会话密钥并用密钥加密密钥解密:SDF_ImportKeyWithKEK

  • 销毁会话密钥:SDF_DestroyKey

非对称算法运算类函数

  • 外部公钥 RSA 运算:SDF_ExternalPublicKeyOperation_RSA

  • 内部公钥 RSA 运算:SDF_InternalPublicKeyOperation_RSA

  • 内部私钥 RSA 运算:SDF_InternalPrivateKeyOperation_RSA

  • 外部密钥 ECC 验证:SDF_ExternalVerify_ECC

  • 内部密钥 ECC 签名:SDF_InternalSign_ECC

  • 内部密钥 ECC 验证:SDF_InternalVerify_ECC

  • 外部密钥 ECC 加密:SDF_ExternalEncrypt_ECC

对称算法运算类函数

  • 对称加密:SDF_Encrypt

  • 对称解密:SDF_Decrypt

  • 计算MAC:SDF_CalculateMAC

杂凑运算类函数

  • 杂凑运算初始化:SDF_HashInit

  • 多包杂凑运算:SDF_HashUpdate

  • 杂凑运算结束:SDF_HashFinal

安全要求

(1)基于本标准设计、开发的密码设备在密钥管理方面,应满足以下要求:
设备密钥的使用不对应用系统开放;
密钥必须用安全的方法产生并存储;
在任何时间、任何情况下,除公钥外的密钥均不能以明文形式出现在密码设备外;
密码设备内部存储的密钥应具备有效的密钥保护机制,防止解剖、探测和非法读取;
密码设备内部存储的密钥应具备权限控制机制,防止非法使用和导出。
(2)密码服务要求:
使用的密码算法应得到国家密码主管部门的批准;
使用国家密码主管部门认可的密码算法芯片;
本标准所列的所有接口函数均应能被应用系统任意调用。
(3)设备状态要求:
密码设备应具有初始和就绪两个状态;
未安装设备密钥的密码设备应处于初始状态,已安装设备密钥的密码设备应处于就绪状态;
在初始状态下,除可读取设备信息、设备密钥的生成或恢复操作外,不能执行任何操作,生成或恢复设备密钥后,密码设备处于就绪状态;
在就绪状态下,除设备密钥的生成或恢复操作外,应能执行任何操作;
在就绪状态下进行的密钥操作,设备操作员应经过密码设备的认证。
(4)其他要求:
密码设备应有安全机制和措施,保证密钥在生成、安装、导入、存储、备份、恢复及销毁整个生存期间的安全,此安全机制可由设备厂商自行设计实现

2 实现GMT 0018-2012密码设备应用接口规范的接口函数

2.1 创建文件过程

2.2 生成的sdfproject树

2.3 代码

include/sdf.h

#ifndef _SDF_H

#define _SDF_H



typedef struct DeviceInfo_st{

unsigned char IssuerName[40];

unsigned char DeviceName[16];

unsigned char DeviceSerial[16];

unsigned int DeviceVersion;

unsigned int StandardVersion;

unsigned int AsymAlgAbility[2];

unsigned int SymAlgAbility;

unsigned int HashAlgAbility;

unsigned int BufferSize;

} DEVICEINFO;

# define ECCref_MAX_BITS 512

# define ECCref_MAX_LEN ((ECCref_MAX_BITS+3)/4)

# define SGD_SM2_1 0x00020200

# define SGD_SM2_3 0x00020800

# define SGD_PUBLIC_KEY_SIGN 0x00000103

# define SGD_PUBLIC_KEY_ENCRYPT 0x00000104

# define SGD_PRIVATE_KEY_SIGN 0x00000105

# define SGD_PRIVATE_KEY_ENCRYPT 0x00000106

#define FILE_PATH "demo.txt"

#define INVALID_NULL_VALUE_INPUT    0x1000

#define INVALID_INPUT_LENGTH        0x1001

#define CREATE_SM2_KEY_PAIR_FAIL    0x1002

#define COMPUTE_SM3_DIGEST_FAIL     0x1003

#define ALLOCATION_MEMORY_FAIL      0x1004

#define COMPUTE_SM2_SIGNATURE_FAIL  0x1005

#define INVALID_SM2_SIGNATURE       0x1006

#define VERIFY_SM2_SIGNATURE_FAIL   0x1007

typedef struct ECCrefPublicKey_st{

   unsigned int bits;

   unsigned char x[ECCref_MAX_LEN];

   unsigned char y[ECCref_MAX_LEN];

}ECCrefPublicKey;



typedef struct ECCrefPrivateKey_st{

   unsigned int bits;

   unsigned char K[ECCref_MAX_LEN];

}ECCrefPrivateKey;



//定义密钥对

typedef struct sm2_key_pair_structure {

   ECCrefPrivateKey pri_key;

   ECCrefPublicKey pub_key;

}SM2_KEY_PAIR;





//定义密钥容器:盛放两对密钥,签名验签公私钥、加密解密公私钥

typedef struct keybox{

    unsigned length;//默认length=2

    SM2_KEY_PAIR mysm2_key_pair[2];//盛放两对密钥,签名验签公私钥、加密解密公私钥,默认第一对加解密公私钥,第二对签名验签公私钥

}KEYBOX;



#define SDR_OK 0x0

/*打开密码设备*/

int SDF_OpenDevice( void * * phDeviceHandle);



/*关闭设备*/



int SDF_CloseDevice( void * hDeviceHandle);





/*获取设备信息*/

int SDF_GetDeviceInfo(void * hSessionHandle,DEVICEINFO * pstDeviceInfo) ;



/*产生随机数*/

int SDF_GenerateRandom (void * hSessionHandle,unsigned int uiLength,unsigned char * pucRandom);



/*导出ECC签名公钥*/

int SDF_ExportSignPublicKey_ECC(void * hSessionHandle,unsigned int uiKeyIndex,ECCrefPublicKey * pucPublicKey);

/*导出ECC加密公钥*/

int SDF_ExportEncPublicKey_ECC(void * hSessionHandle,unsigned int uiKeyIndex,ECCrefPublicKey * pucPublicKey);

/*产生ECC密钥对并输出*/

int SDF_GenerateKeyPair_ECC(void * hSessionHandle,unsigned int uiAlgID,unsigned int uiKeyBits,ECCrefPublicKey * pucPublicKey,ECCrefPrivateKey * pucPrivateKey);





#endif

test/main.c

#include<stdio.h>

#include<stdlib.h>

#include "sdf.h"

#include <time.h>

#include <stdio.h>





int main(){

   void **pdh;

   pdh=(void **)malloc(20);

   int ret;

   ret = SDF_OpenDevice(pdh);

   if(ret != SDR_OK)

   {

	   printf("打开设备失败\n");

   }

   else

   {

	   printf("打开设备成功!\n");

	 }

   printf("查看设备信息\n");

   DEVICEINFO a;

   ret = SDF_GetDeviceInfo(*pdh,&a);

   if(ret !=SDR_OK)

           printf("查看设备信息失败!\n");

   else

           printf("查看设备信息成功!\n");

   printf("设备名字叫做%s\n",a.DeviceName);

   printf("设备版本号为%d\n",a.DeviceVersion);

   printf("想要获取的随机数长度为:\n");

   int n;

   scanf("%d",&n);

   char string[100];

   ret = SDF_GenerateRandom(*pdh,n,string);

   if(ret !=SDR_OK)

	   printf("生成随机数失败!");

    else

	    printf("生成的随机数为%s\n",string);

   

   //对密钥容器生成两对密钥

   KEYBOX Keybox;

   Keybox.length=2;

  

   /*生成加解密密钥对*/

  

   printf("*************************生成加解密密钥对***********************************\n");

   ret =  SDF_GenerateKeyPair_ECC(*pdh,SGD_SM2_3,256,&(Keybox.mysm2_key_pair[0].pub_key),&(Keybox.mysm2_key_pair[0].pri_key));//我设的生成密钥算法默认长度32字节,256bit;

   if(ret ==SDR_OK)

   {

	   printf("生成加解密密钥对成功!\n");

           /*

	   printf("加密公钥的位数:%d\n",(Keybox.mysm2_key_pair[0].pub_key).bits);

	   printf("加密公钥的x坐标:%s\n",(Keybox.mysm2_key_pair[0].pub_key).x);

	   printf("加密公钥的y坐标:%s\n",(Keybox.mysm2_key_pair[0].pub_key).y);

	   printf("加密私钥的位数:%d\n",(Keybox.mysm2_key_pair[0].pri_key).bits);

	   printf("加密私钥为:%s\n",(Keybox.mysm2_key_pair[0].pri_key).K);

           */

           

   }

   else

   {

	   printf("生成加解密密钥失败!");

   }

   /*生成签名验签密钥对*/

   printf("*************************生成签名验签密钥对***********************************\n");

   ret =  SDF_GenerateKeyPair_ECC(*pdh,SGD_SM2_1,256,&(Keybox.mysm2_key_pair[1].pub_key),&(Keybox.mysm2_key_pair[1].pri_key));

    if(ret ==SDR_OK)

   {

           printf("生成签名验签密钥对成功!\n");

           /*

           printf("签名公钥的位数:%d\n",(Keybox.spub_key).bits);

           printf("签名公钥的x坐标:%s\n",(Keybox.spub_key).x);

           printf("签名公钥的y坐标:%s\n",(Keybox.spub_key).y);

           printf("签名私钥的位数:%d\n",(Keybox.spri_key).bits);

           printf("签名私钥为:%s\n",(Keybox.spri_key).K);

           */

   }

   else

   {

           printf("生成签名验签密钥失败!");

   }



    FILE *fp;  // 文件指针

    unsigned int uiKeyIndex;

    unsigned int bits;

    unsigned char x[ECCref_MAX_LEN];

    unsigned char y[ECCref_MAX_LEN];

    //unsigned int uiKeyIndex1 = SGD_PUBLIC_KEY_ENCRYPT;

    //unsigned int bits1=201;

    //unsigned char x1[ECCref_MAX_LEN]="ABCD12345";

    //unsigned char y1[ECCref_MAX_LEN]="YUIO87651";

    // 判断文件是否能够正确创建/打开

    if( (fp=fopen(FILE_PATH,"wt+")) == NULL ){

        perror(FILE_PATH);

        exit(1);

    }

   

  

    printf("*************************将两对密钥放进密钥容器***************************\n");



    fprintf(fp,"%d\t%d\t%s\t%s\n", SGD_PUBLIC_KEY_ENCRYPT, (Keybox.mysm2_key_pair[0].pub_key).bits, (Keybox.mysm2_key_pair[0].pub_key).x, (Keybox.mysm2_key_pair[0].pub_key).y);//将加密公钥写入文件

    fprintf(fp,"%d\t%d\t%s\t%s\n", SGD_PRIVATE_KEY_ENCRYPT, (Keybox.mysm2_key_pair[0].pri_key).bits, (Keybox.mysm2_key_pair[0].pri_key).K, "空");//将加密私钥入文件

    fprintf(fp,"%d\t%d\t%s\t%s\n", SGD_PUBLIC_KEY_SIGN, (Keybox.mysm2_key_pair[1].pub_key).bits, (Keybox.mysm2_key_pair[1].pub_key).x, (Keybox.mysm2_key_pair[1].pub_key).y);//将签名公钥写入文件

    fprintf(fp,"%d\t%d\t%s\t%s\n", SGD_PRIVATE_KEY_SIGN, (Keybox.mysm2_key_pair[1].pri_key).bits, (Keybox.mysm2_key_pair[1].pri_key).K, "空");//将签名私钥写入文件

    

    // 刷新缓冲区,将缓冲区的内容写入文件

    fflush(fp);

    

    /*// 重置文件内部位置指针,让位置指针指向文件开头(很重要!)

    rewind(fp);

    */

    printf("两对密钥已成功放入密钥容器(demo.txt)~\n");



 /*   // 从文件中读取加密公钥和签名公钥的信息

    printf("\n读取密钥容器(文件)中的加密公钥和签名公钥内容:\n");

    while(fscanf(fp, "%d\t%d\t%s\t%s", &uiKeyIndex, &bits, x, y) != EOF){ //fscanf是从文件中读取内容的啦

       // 挑选一下,我想要加密公钥和签名公钥

        if(uiKeyIndex == SGD_PUBLIC_KEY_ENCRYPT || uiKeyIndex == SGD_PUBLIC_KEY_SIGN)

        printf("%d\t%d\t%s\t%s\n", uiKeyIndex, bits, x, y); //打印到显示器

    } */

    fclose(fp);//关闭文件





   

   printf("*************************从密钥容器中导出签名公钥和加密公钥************************\n");

   

   ECCrefPublicKey key;

   //导出ECC签名公钥

   ret = SDF_ExportSignPublicKey_ECC(*pdh,SGD_PUBLIC_KEY_SIGN,&key);

    if(ret !=SDR_OK)

   {

	   printf("导出签名公钥失败!"); 

   }

    else

   {

         printf("导出签名公钥成功!\n");

	 printf("签名公钥的长度为%d\n",key.bits);

	 printf("签名公钥的x坐标为%s\n",key.x);

	 printf("签名公钥的y坐标为%s\n",key.y);



   }





    ECCrefPublicKey key1;

   //导出ECC加密公钥

    ret = SDF_ExportEncPublicKey_ECC(*pdh,SGD_PUBLIC_KEY_ENCRYPT,&key1);

   if(ret !=SDR_OK)

   {

           printf("导出加密公钥失败!");

   }

    else

   {

         printf("导出加密公钥成功!\n");

         printf("加密公钥的长度为%d\n",key1.bits);

         printf("加密公钥的x坐标为%s\n",key1.x);

         printf("加密公钥的y坐标为%s\n",key1.y);



   }

   

   

   ret = SDF_CloseDevice(*pdh);

   if(ret != SDR_OK)

   {

	   printf("关闭不成功!\n");

   }

   else

   {

	   printf("关闭成功!\n");

   }

   free(pdh);



}

src/sdf.c

#include<stdio.h>

# include <stdlib.h>

#include<string.h>

#include"sdf.h"

#include<time.h>

#include <openssl/bn.h>

#include <openssl/ec.h>

#include <openssl/ecdsa.h>

#include <openssl/objects.h>

#include <openssl/err.h>

#include <openssl/ecdh.h>

#include<openssl/obj_mac.h>

int SDF_OpenDevice( void * * phDeviceHandle)

{

	return SDR_OK;

}

int SDF_CloseDevice( void * hDeviceHandle)

{

	return SDR_OK;

}

int SDF_GetDeviceInfo(void * hSessionHandle,DEVICEINFO * pstDeviceInfo)

{

	DEVICEINFO di;

	strcpy(di.IssuerName,"HYW");

	strcpy(di.DeviceName,"SDFhyw");

	strcpy(di.DeviceSerial,"20220512");

	di.DeviceVersion=1;

	(*pstDeviceInfo)= di;	

	

	return SDR_OK;

}

int SDF_GenerateRandom (void * hSessionHandle,unsigned int uiLength,unsigned char * pucRandom)

{

	BIGNUM *bn;

        

        int i;

        bn = BN_new(); //生成一个BIGNUM结构



        //int bits = 20;

        int top = -1;

        int bottom = 1;



        BN_rand(bn, uiLength, top, bottom); //生成指定bits的随机数



        char *a = BN_bn2hex(bn); //转化成16进制字符串

        //puts(a);

        //printf("\n");

        for(i=0;*(a+i)!='\0';i++)

        {

            *(pucRandom+i)=*(a+i);

        }



        *(pucRandom+i)='\0';

        BN_free(bn); //释放BIGNUM结构

        return SDR_OK;

}

//导出ECC签名公钥

int SDF_ExportSignPublicKey_ECC(void * hSessionHandle,unsigned int uiKeyIndex,ECCrefPublicKey * pucPublicKey){

    FILE *fp;  // 文件指针

    unsigned int KeyIndex;

    unsigned int Bits;

    unsigned char X[ECCref_MAX_LEN];

    unsigned char Y[ECCref_MAX_LEN];

    // 判断文件是否能够正确创建/打开

    if( (fp=fopen(FILE_PATH,"r")) == NULL ){

        perror(FILE_PATH);

        exit(1);

    }

    //printf("\n读取密钥容器(文件)中的签名公钥并取出来(放到key中):\n");





   while(fscanf(fp, "%d\t%d\t%s\t%s", &KeyIndex, &Bits, X, Y) != EOF){ //fscanf是从文件中读取内容的啦

       // 挑选一下,我想要签名公钥

        if(KeyIndex == SGD_PUBLIC_KEY_SIGN){

          //printf("%d\t%d\t%s\t%s\n", KeyIndex, Bits, X, Y); //打印到显示器

          (*pucPublicKey).bits=Bits;

          strcpy((*pucPublicKey).x,X);

          strcpy((*pucPublicKey).y,Y); 

        }

    }

    fclose(fp);

    return SDR_OK;

}



//导出ECC加密公钥

int SDF_ExportEncPublicKey_ECC(void * hSessionHandle,unsigned int uiKeyIndex,ECCrefPublicKey * pucPublicKey){

        

    FILE *fp;  // 文件指针

    unsigned int KeyIndex;

    unsigned int Bits;

    unsigned char X[ECCref_MAX_LEN];

    unsigned char Y[ECCref_MAX_LEN];

    // 判断文件是否能够正确创建/打开

    if( (fp=fopen(FILE_PATH,"r")) == NULL ){

        perror(FILE_PATH);

        exit(1);

    }

   // printf("\n读取密钥容器(文件)中的加密公钥并取出来(放到key1中):\n");



   

   while(fscanf(fp, "%d\t%d\t%s\t%s", &KeyIndex, &Bits, X, Y) != EOF){ //fscanf是从文件中读取内容的啦

       // 挑选一下,我想要签名公钥

        if(KeyIndex == SGD_PUBLIC_KEY_ENCRYPT){

          //printf("%d\t%d\t%s\t%s\n", KeyIndex, Bits, X, Y); //打印到显示器

          (*pucPublicKey).bits=Bits;

          strcpy((*pucPublicKey).x,X);

          strcpy((*pucPublicKey).y,Y); 

        }

    }

    fclose(fp);

    return SDR_OK;

}

/*产生ECC密钥对并输出*/

int SDF_GenerateKeyPair_ECC(void * hSessionHandle,unsigned int uiAlgID,unsigned int uiKeyBits,ECCrefPublicKey * pucPublicKey,ECCrefPrivateKey * pucPrivateKey)

{

        

	BN_CTX* ctx = NULL;

	BIGNUM* bn_d = NULL, * bn_x = NULL, * bn_y = NULL;

	const BIGNUM* bn_order;

	EC_GROUP* group = NULL;

	EC_POINT* ec_pt = NULL;

        unsigned char pri_key[32];

	unsigned char pub_key_x[32], pub_key_y[32];

	if (!(ctx = BN_CTX_secure_new()))

	{

		goto clean_up;

	}

	BN_CTX_start(ctx);

	bn_d = BN_CTX_get(ctx);

	bn_x = BN_CTX_get(ctx);

	bn_y = BN_CTX_get(ctx);

	if (!(bn_y))

	{

		goto clean_up;

	}



	if (!(group = EC_GROUP_new_by_curve_name(NID_sm2)))

	{

		goto clean_up;

	}

	if (!(bn_order = EC_GROUP_get0_order(group)))

	{

		goto clean_up;

	}

	if (!(ec_pt = EC_POINT_new(group)))

	{

		goto clean_up;

	}

	do

	{

		if (!(BN_rand_range(bn_d, bn_order)))

		{

			goto clean_up;

		}

	} while (BN_is_zero(bn_d));



	if (!(EC_POINT_mul(group, ec_pt, bn_d, NULL, NULL, ctx)))

	{

		goto clean_up;

	}

	if (!(EC_POINT_get_affine_coordinates_GFp(group,

		ec_pt,

		bn_x,

		bn_y,

		ctx)))

	{

		goto clean_up;

	}

        if (BN_bn2binpad(bn_d,pri_key,

		sizeof(pri_key)) != sizeof(pri_key))

	{

		goto clean_up;

	}

        if (BN_bn2binpad(bn_x,

		pub_key_x,

		sizeof(pub_key_x)) != sizeof(pub_key_x))

	{

		goto clean_up;

	}

        if (BN_bn2binpad(bn_y,

		pub_key_y,

		sizeof(pub_key_y)) != sizeof(pub_key_y))

	{

		goto clean_up;

	}



        //下面打印一下密钥进行测试~~~

        //printf("打印一下私钥");

        int i;

        int j=1;

        //printf("\n");

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

          //printf("0x%x",pri_key[i]);

          if(pri_key[i]%16>=0 && pri_key[i]%16 <=9)

            (*pucPrivateKey).K[j]=pri_key[i]%16 + '0';

          else

            (*pucPrivateKey).K[j]= 'a'-10 + pri_key[i]%16;

          

          pri_key[i]=pri_key[i]/16;

          if(pri_key[i]%16>=0 && pri_key[i]%16 <=9)

            (*pucPrivateKey).K[j-1]=pri_key[i]%16 + '0';

          else

            (*pucPrivateKey).K[j-1]= 'a'-10 + pri_key[i]%16;

          

          j=j+2;

       

         }

         (*pucPrivateKey).K[j-1]='\0';

 

        //公钥的x坐标

        j=1;

        //printf("打印一下公钥的x坐标");

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

          //printf("0x%x",pub_key_x[i]);

          if(pub_key_x[i]%16>=0 && pub_key_x[i]%16 <=9)

            (*pucPublicKey).x[j]=pub_key_x[i]%16 + '0';

          else

            (*pucPublicKey).x[j]= 'a'-10 + pub_key_x[i]%16;

          

          pub_key_x[i]=pub_key_x[i]/16;

         if(pub_key_x[i]%16>=0 && pub_key_x[i]%16 <=9)

            (*pucPublicKey).x[j-1]=pub_key_x[i]%16 + '0';

          else

            (*pucPublicKey).x[j-1]= 'a'-10 + pub_key_x[i]%16;

          

          j=j+2;

       

          

         }

        //printf("\n");

         (*pucPublicKey).x[j-1] = '\0';

       // printf("再此打印一下公钥的x坐标");

       // printf("%s\n",(*pucPublicKey).x);

        

        //下面打印公钥进行测试

        j=1;

        //printf("打印一下公钥的y坐标");

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

          //printf("0x%x",pub_key_y[i]);

          if(pub_key_y[i]%16>=0 && pub_key_y[i]%16 <=9)

            (*pucPublicKey).y[j]=pub_key_y[i]%16 + '0';

          else

            (*pucPublicKey).y[j]= 'a'-10 + pub_key_y[i]%16;

          

          pub_key_y[i]=pub_key_y[i]/16;

         if(pub_key_y[i]%16>=0 && pub_key_y[i]%16 <=9)

            (*pucPublicKey).y[j-1]=pub_key_y[i]%16 + '0';

          else

            (*pucPublicKey).y[j-1]= 'a'-10 + pub_key_y[i]%16;

          

          j=j+2;

       

          

         }

        //printf("\n");

         (*pucPublicKey).y[j-1] = '\0';

        //printf("再此打印一下公钥的y坐标");

        //printf("%s\n",(*pucPublicKey).y);

	//位数信息

        (*pucPublicKey).bits=256;

        (*pucPrivateKey).bits=256;

	

        return SDR_OK;	

clean_up:

	if (ctx)

	{

		BN_CTX_end(ctx);

		BN_CTX_free(ctx);

	}



	if (group)

	{

		EC_GROUP_free(group);

	}



	if (ec_pt)

	{

		EC_POINT_free(ec_pt);

	}

        return SDR_OK;

      

}

compile.sh

gcc src/sdf.c test/main.c -o bin/test -Iinclude -lpthread -lcrypto

2.4 编译执行

2.5 运行结果

posted @ 2022-05-12 16:58  Kylin0  阅读(250)  评论(0编辑  收藏  举报