zoukankan      html  css  js  c++  java
  • 实验一-密码引擎-加密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) 在就绪状态下进行的密钥操作,设备操作员应经过密码设备的认证。

    接口文档学习
    基础密码服务包括密钥生成、单一的密码运算、文件管理等服务。
    本标准采用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
    设备管理中的打开设备,关闭设备,获取设备信息,产生随机数
    mkdir sdfproject
    cd sdfproject
    mkdir src include libs docs test
    touch Makefile
    touch readme.md
    touch compile.shcd docs
    mkdir ref
    将GMT0018-2012放入ref文件夹下

    接着在include文件夹里创建一个sdf.h(可以在notepad++里写)

    #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;
    
    //Error Code
    
    #define SDF_OK 0x0 //操作成功
    #define SDR_BASE   0x01000000   //错误码基础值
    #define SDR_UNKNOWERR   SDR_BASE+0x00000001  //未知错误
    #define SDR_NOTSUPPORT   SDR_BASE+0x00000002  //不支持的接口调用
    #define SDR_COMMFAIL   SDR_BASE +0x00000003  //与设备通信失败
    #define SDR_HARDFAIL    SDR_BASE+ 0x00000004   //运算模块无响应
    #define SDR_OPENDEVICE   SDR_BASE+0x00000005  //打开设备失败
    #define SDR_OPENSESSION  SDR_BASE + 0x00000006  //创建会话失败
    #define SDR_PARDENY   SDR_BASE +0x00000007    //无私钥使用权限
    #define SDR_KEYNOTEXIST   SDR_ BASE+0x00000008   //不存在的密钥调用
    #define SDR_ALGNOTSUPPORT   SDR_BASE + 0x00000009  //不支持的算法调用
    #define SDR_ALGMODNOTSUPPORT   SDR_BASE+ 0x0000000A   //不支持的算法模式调用
    #define SDR_PKOPERR   SDR_BASE+ 0x0000000B   //公钥运算失败
    #define SDR_SK OPERR  SDR_BASE + 0x0000000C  //私钥运算失败
    #define SDR_SIGNERR    SDR _BASE+0x0000000D   //签名运算失败
    #define SDR_VERIFYERR   SDR_BASE +0x0000000E   //验证签名失败
    #define SDR_SYMOPERR   SDR_BASE+ 0x0000000F   //对称算法运算失败
    #define SDR_STEPERR   SDR_BASE+0x00000010  //多步运算步骤锗误
    #define SDR_FILES1ZEERR   SDR_BASE+0x00000011  //文件长度超出限制
    #define SDR_FILENOEXIST   SDR_BASE+0x00000012   //指定的文件不存在
    #define SDR_FILEOFSERR  SDR_BASE+0x00000013  //文件起始位置错误
    #define SDR_KEYTYPEERR  SDR_BASE+0x00000014  //密钥类型缙误
    #define SDR_KEYERR  SDR_BASE+0x00000015  //密钥缙误
    #define SDR_ENCDATAERR  SDR_BA3E+0x00000016  //ECC加密数据错误
    #define SDR_RANDERR  SDR_BASE+0x00000017  //随机数产生失败
    #define SDR_PRKRERR  SDR_BASE+0x00000018  //私钥使用权限获取失败
    #define SDR_MACFRR  SDR_BASE+0x00000019 //MAC运算失败
    #define SDR_FILEEXISTS   SDR_BASE+ 0x0000001A  //指定文件已存在
    #define SDR_FILEWERR  SDR_BASE+0x0000001B  //文件写入失败
    #define SDR_NORUFFER  SDR_BASE+0x0000001c  //存储空间不足
    #define SDR_INARGERR  SDR_BASE+0x0000001D  //输入参数错误
    #define SDR_OUTARGERR  SDR_BASE +0x0000001E  //输出参数错误
    
    
    //设备管理
    /*
    功能:打开密码设备
    参数:
    phDeviceHandle[out]返回设备句柄
    返回值:
    0       成功
    非0   失败,返回错误代码
    备注:
    phDeviceHandle由函数初始化并填写内容
    */
    int SDF_OpenDevice(void ** phDeviceHandle);
    
    /*
    功能:关闭密码设备,并释放相关资源。
    参数:
    hDeviceHandle[in]   已打开的设备句柄
    返回值:
    0        成功
    非0     失败,返回错误代码
    */
    int SDF_CloseDevice( void * hDeviceHandle);
    
    /*
    功能:获取密码设备能力描述。
    参数:
    hSessionHandle[in]  与设备建立的会话句柄
    pstDeviceInfo [out]  设备能力描述信息,内容及格式见设备信息定义
    返回值:
    0        成功
    非0     失败,返回错误代码 
    */
    int SDF_GetDeviceInfo(
    void * hSessionHandle,
    DEVICEINFO * pstDeviceInfo);
    
    /*
    功能:获取指定长度的随机数。
    参数:hSessionHandle[in]   与设备建立的会话句柄
    uilength[in]   欲获取的随机数长度
    pucRandom[out]   缓冲区指针,用于存放获取的随机数
    返回值:
    0        成功
    非0     失败,返回错误代码 
    */
    int SDF_GenerateRandom (
    void * hSessionHandle,unsigned int uiLength,
    unsigned char * pucRandom);
    
    
    #endif
    写main.c,其中调用src里定义的函数
    test/main.c
    
    
    #include
    #include
    #include "sdf.h"
    int main(){
       void **pdh;
       pdh=(void **)malloc(20);  //给pdh分配空间
       int ret;
       ret = SDF_OpenDevice(pdh);  //返回handle的指针
    
       if(ret != SDF_OK)
       {
        printf("打开设备失败
    ");
       }
       else
       {
        printf("打开设备成功!
    ");
      }
       printf("查看设备信息
    ");
       DEVICEINFO a;
       ret = SDF_GetDeviceInfo(*pdh,&a);
       if(ret !=SDF_OK)
               printf("查看设备信息失败!
    ");
       else
               printf("查看设备信息成功!
    ");
       printf("设备名字叫做%s
    ",a.DeviceName);
       printf("设备版本号为%d
    ",a.DeviceVersion);
       printf("想要获取的随机数长度为:
    ");
       int n;
       scanf("%d",&n);
       char string[100];
       ret = SDF_GenerateRandom(*pdh,n,string);
       if(ret !=SDF_OK)
        printf("生成随机数失败!");
        else
         printf("生成的随机数为%s
    ",string);
       ret = SDF_CloseDevice(*pdh);
       if(ret != SDF_OK)
       {
        printf("关闭不成功!
    ");
       }
       else
       {
        printf("关闭成功!
    ");
       }
    }
    
    
    sdf.c实现函数
    src/sdf.c
    
    
    #include
    # include 
    #include
    #include "sdf.h"
    #include
    #include 
    int SDF_OpenDevice( void ** phDeviceHandle)
    {
     return SDF_OK;
    }
    int SDF_CloseDevice( void * hDeviceHandle)
    {
     return SDF_OK;
    }
    int SDF_GetDeviceInfo(void * hSessionHandle,DEVICEINFO * pstDeviceInfo)
    {
     DEVICEINFO di;
     strcpy(di.IssuerName,"lzySDF");
     strcpy(di.DeviceName,"SDFlzy20181309");
     strcpy(di.DeviceSerial,"20210425");
     di.DeviceVersion=1;
     (*pstDeviceInfo)= di; 
     
     return SDF_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("
    ");
            for(i=0;*(a+i)!='';i++)
            {
                *(pucRandom+i)=*(a+i);
            }
            *(pucRandom+i)='';
            BN_free(bn); //释放BIGNUM结构
            return SDF_OK;
    }
    
    
    compile.sh
    
    gcc test/main.c src/sdf.c -o bin/test -Iinclude  -lpthread -lcrypto
    遇到的问题
    
    
    后来找到原因是没有创建bin文件夹,后来创建文件夹后即可成功
  • 相关阅读:
    else 的特殊用法和三目运算
    pycharm快捷键
    5、【排序算法】选择排序
    4、【排序算法】希尔排序
    3、【排序算法】直接插入排序
    1、【常见算法】不使用第三个变量交换两个数的值
    1、【排序算法】冒泡排序
    7、【树形结构】哈夫曼树
    6、【树形结构】红黑树
    5、【树形结构】AVL树
  • 原文地址:https://www.cnblogs.com/20181309lzy/p/14701818.html
Copyright © 2011-2022 走看看