点击或拖拽改变大小

HslCertificate 类

基于RSA加密模型的证书,支持自定义的颁发证书,以及校验证书合法性
Certificates based on RSA encryption model support custom issuance certificates and verify certificate legitimacy
继承层次
SystemObject
  HslCommunication.Core.SecurityHslCertificate

命名空间:  HslCommunication.Core.Security
程序集:  HslCommunication (在 HslCommunication.dll 中) 版本:12.1.2.0 (12.1.2.0)
语法
public class HslCertificate

HslCertificate 类型公开以下成员。

构造函数
  名称说明
公共方法HslCertificate
实例化一个默认的对象
Instantiate a default object
公共方法HslCertificate(Byte, Byte)
使用指定的公钥,私钥来实例化一个的对象
An object is instantiated using the specified public key and private key
公共方法HslCertificate(RSACryptoServiceProvider, RSACryptoServiceProvider)
使用指定的公钥,私钥来实例化一个的对象
An object is instantiated using the specified public key and private key
Top
属性
  名称说明
公共属性CreateTime
发证日期
公共属性Descriptions
证书的其他描述信息
公共属性EffectiveHours
有效小时数,小于等于0 表示无期限
公共属性From
证书的颁发者
公共属性KeyWord
获取或设置当前证书的关键字,可以用来给证书做分类
公共属性NotAfter
证书有效的截止时间
公共属性NotBefore
证书有效的起始时间
公共属性PublicKey
证书的公钥信息
公共属性To
证书的持有者
公共属性UniqueID
获取或设置当前证书的唯一编号信息
Top
方法
  名称说明
公共方法静态成员CreateFrom
从证书的原始字节创建一个HslCertificate对象,方便浏览证书的基本信息。
Create a HslCertificate object from the original bytes of the certificate to facilitate browsing the basic information of the certificate.
公共方法Equals
Determines whether the specified object is equal to the current object.
(继承自 Object。)
受保护的方法Finalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(继承自 Object。)
公共方法GetHashCode
Serves as the default hash function.
(继承自 Object。)
公共方法GetSaveBytes
获取当前证书的原始字节信息,可以存储到文件中,必须提供私钥信息,否则无法进行签名的操作
Gets the raw byte information of the current certificate, which can be stored in a file, and the private key information must be provided, otherwise the signing operation cannot be performed
公共方法GetType
Gets the Type of the current instance.
(继承自 Object。)
公共方法LoadFrom
从文件的二进制数据中加载相关的参数
受保护的方法MemberwiseClone
Creates a shallow copy of the current Object.
(继承自 Object。)
公共方法ToString
Returns a string that represents the current object.
(继承自 Object。)
公共方法静态成员VerifyCer
使用给定的公钥,校验当前的证书是否合法的,如果公钥为 null,则直接校验证书本身是否合法。
Use the given public key to verify whether the current certificate is valid, and if the public key is null, directly verify whether the certificate itself is valid.
Top
扩展方法
  名称说明
公共扩展器方法ToJsonString
获取当前对象的JSON格式表示的字符串。
Gets the string represented by the JSON format of the current object.
(由 HslExtension 定义。)
Top
备注
证书可以用于接口的权限认证,不需要修改接口源代码或是配置文件,颁发证书就可以修改用户的权限,而且只要保密好私钥,那么证书本身就无法伪造,具有极高的安全性,具体用法参考示例代码。
The certificate can be used for the permission authentication of the interface, no need to modify the interface source code or configuration file, the issuance of the certificate can modify the user's permissions, and as long as the private key is kept secret, then the certificate itself cannot be forged, with extremely high security, the specific usage refer to the sample code.
示例
证书这部分的功能主要分为,制作证书,以及校验证书,至于为什么不使用X509Certificate2证书的形式, 因为这种证书都是要授信机构颁发的,自己颁发的证书验签不了,所以在本库里提供一个用于自己颁发,自己验签的证书。
假设我们有一些API接口需要使用证书来控制权限,有调用时间检验的,或是按接口名称校验的,或是按调用次数来校验的,接口见下面的代码。
接口的权限控制示例
// 先使用hslcommunicationdemo,生成公私钥的密钥对,例如下面的
private string pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwAs1K7u" +
    "qRb89J0DJZ/rFz5dHHWC0vTiGDayy//cc8jvd3MHY3aUiH2l0Th69rbBY81C" +
    "I5dzaUKMml393VOf1qTzt+CLV0XrVOPnZ3I9SuTmBh8dyB2pX/9wm/X3JL/Jg9tE" +
    "OofqmD6ChLPn01Nf5xiaRpyG1fntxJO8jS3+ckJQIDAQAB";
private string priKey = "MIICXgIBAAKBgQCwAs1K7uqRb89J0DJZ/rFz5dHHWC0vTiGDayy//cc8jvd3" +
    "MHY3aUiH2l0Th69rbBY81CI5dzaUKMml393VOf1qTzt+CLV0XrVOPnZ3I9SuTmBh8dyB2pX/9wm/X3JL/Jg9t" +
    "EOofqmD6ChLPn01Nf5xiaRpyG1fntxJO8jS3+ckJQIDAQABAoGBAKJt84ZzdYVB6cn0mIL0yE5siGuutAQz1jmx" +
    "blq/mF4KkdUso+v+/TBiFAMx9HDuDpeULQFbQsL34R9yuQVNvs4U+Oo0vqAD8aXrS9bDZWuPvpKM4fCLof5gxVnLK" +
    "5c2MV/Nq060ztcNBnzEpLhGLbcPZbTOShlAVnml4UJxsesBAkEA19JXl2nEEjvSIEzzXjsl0cp18OXO7C4UNIE5sEpQ" +
    "eNbJbgfcHRavd82OvrLzYKy4aHRQZvCEQBo+1ja7EdrOtwJBANDHJ9/rs88+hb9oWs0zeedpnr+5weijefhtLzKFBr/b6MP" +
    "iSAvYIUGie7UD+MedC37MHpQmiyPFUR3wd1onCAMCQEIB5yA8DOe2vBF894H+fRao4WGIJ708apmUXFx6nhoXNwwcA0oyQgBWMi" +
    "5I9P7AVLY9vMl/DjO80zMZEiXn0gkCQQCNeyjuedA0VW5Vs+Y0wPmPdOf7jWp2uLHjRDqDxdo5ElG+zQ192U1QKUgj9zkULLyph" +
    "LIEO8p2xzSdUWPQWDr5AkEAp9FfsofKAYIa6+rb4EWn9zavWz+gfIX9J/Zz3d7Mi0JnVX8dgC5o6yOxhM1h6oDgeHxeqZPTvtRUtI4U5dAmHQ==";

// 假设下面的接口就是使用证书校验的,不是谁都可以访问的
// Assume that the following interface is authenticated using a certificate and cannot be accessed by anyone
[HslMqttApi]
public OperateResult<int> ApiAdd( string certificate, int a, int b )
{
    // 下面演示如何针对 certificate 校验对象
    if (!HslCommunication.Core.Security.HslCertificate.VerifyCer( Convert.FromBase64String( pubKey ), Convert.FromBase64String( certificate )))
    {
        // 调用失败
        return new OperateResult<int>( "Called api failed, check certificate failed" );
    }

    // 如果证书校验通过,则开始解析证书内容
    HslCommunication.Core.Security.HslCertificate cert = HslCommunication.Core.Security.HslCertificate.CreateFrom( Convert.FromBase64String( certificate ) );
    if (cert.NotBefore <= DateTime.Now && DateTime.Now <= cert.NotAfter)
    {
        // 一般证书都是有时间有效期的,所以这里可以根据有效期决定是否开放接口
        return new OperateResult<int>( "Called api failed, the current certificate validity period has expired." );
    }

    return OperateResult.CreateSuccessResult( a + b );
}

// 假设下面的接口就是使用证书校验的,不仅要校验时间是否符合,还要校验系统名称是否匹配,证书的权限是否包含当前的接口名称
// Assume that the following interface is verified using a certificate, not only to verify whether the time is in line,
// but also to verify whether the system name matches, and whether the certificate's authority contains the current interface name
[HslMqttApi]
public OperateResult<int> ApiMulti( string certificate, int a, int b )
{
    // 下面演示如何针对 certificate 校验对象
    if (!HslCommunication.Core.Security.HslCertificate.VerifyCer( Convert.FromBase64String( pubKey ), Convert.FromBase64String( certificate ) ))
    {
        // 调用失败
        return new OperateResult<int>( "Called api failed, check certificate failed" );
    }

    // 如果证书校验通过,则开始解析证书内容
    HslCommunication.Core.Security.HslCertificate cert = HslCommunication.Core.Security.HslCertificate.CreateFrom( Convert.FromBase64String( certificate ) );
    if (cert.NotBefore <= DateTime.Now && DateTime.Now <= cert.NotAfter)
    {
        // 一般证书都是有时间有效期的,所以这里可以根据有效期决定是否开放接口
        return new OperateResult<int>( "Called api failed, the current certificate validity period has expired." );
    }

    // 如果希望多个系统,接口,软件的证书都用同一套的公私钥,那么不同系统的证书校验,可以使用KeyWord来区分,例如下面的 HslCommunication 软件校验
    // 否则只能每一套系统,分配一个公私钥密钥对了
    if (cert.KeyWord != "HslCommunication") return new OperateResult<int>( "Certificate key word not correct!" );

    // 如果希望你得证书支持接口列表信息,可以使用证书里的集合数据功能
    if (cert.Descriptions != null && cert.Descriptions.ContainsKey( "ApiMulti" ))
    {
        // 证书当前的接口列表里,包含了当前的接口名称,有权限调用
        return OperateResult.CreateSuccessResult( a * b );
    }
    else
    {
        return new OperateResult<int>( "Called ApiMulti failed, the current certificate does not have access." );
    }
}

// 假设下面的接口就是使用证书校验的,不仅要校验时间是否符合,还希望对证书持有者限制调用接口的次数,总次数写入到证书里去,这样比较灵活,不需要修改代码,甚至配置文件,只要颁发不同的证书即可
// Assuming that the following interface is using certificate verification, not only to verify whether the time is met, but also to limit the number of times the interface is called to the certificate holder,
// the total number of times written to the certificate, which is more flexible, no need to modify the code, or even the configuration file, as long as different certificates are issued
[HslMqttApi]
public OperateResult<int> ApiDivision( string certificate, int a, int b )
{
    // 下面演示如何针对 certificate 校验对象
    if (!HslCommunication.Core.Security.HslCertificate.VerifyCer( Convert.FromBase64String( pubKey ), Convert.FromBase64String( certificate ) ))
    {
        // 调用失败
        return new OperateResult<int>( "Called api failed, check certificate failed" );
    }

    // 如果证书校验通过,则开始解析证书内容
    HslCommunication.Core.Security.HslCertificate cert = HslCommunication.Core.Security.HslCertificate.CreateFrom( Convert.FromBase64String( certificate ) );
    if (cert.NotBefore <= DateTime.Now && DateTime.Now <= cert.NotAfter)
    {
        // 一般证书都是有时间有效期的,所以这里可以根据有效期决定是否开放接口
        return new OperateResult<int>( "Called api failed, the current certificate validity period has expired." );
    }

    // 如果希望多个系统,接口,软件的证书都用同一套的公私钥,那么不同系统的证书校验,可以使用KeyWord来区分,例如下面的 HslCommunication 软件校验
    // 否则只能每一套系统,分配一个公私钥密钥对了
    if (cert.KeyWord != "HslCommunication") return new OperateResult<int>( "Certificate key word not correct!" );


    // cert.EffectiveHours 是个 int 数据,用来存放接口的调用次数,当然使用另一个字符串属性 cert.UniqueID 也可以。
    bool enable = false; // 检查是否通过
    lock (dictLock)
    {
        // 没有
        if (!apiCalledCount.ContainsKey( cert.To )) apiCalledCount.Add( cert.To, 0 );
        enable = apiCalledCount[cert.To] < cert.EffectiveHours;

        if (enable) apiCalledCount[cert.To]++;
    }

    if (!enable) return new OperateResult<int>( "Called ApiDivision failed, The number of calls has reached the maximum." );
    return OperateResult.CreateSuccessResult( a / b ); // 返回正常的调用信息
}

// 当前系统的所有API调用次数,初始化时,应该从本地或是数据库加载之前的次数,这次简略处理
private Dictionary<string, long> apiCalledCount = new Dictionary<string, long>( );
private object dictLock = new object( );
当然我们还可以自己颁发证书,注意,这时候的私钥就非常有用了,私钥丢了,就发不了证书了。如果要重新生成公私钥,那么之前发出去的证书都失效了。
颁发证书的例子
// 如果需要实现发证的话,就是下面的代码,当然也可以使用 hslcommunicationdemo 来颁发证书的
public void CreateCert( )
{
    // 还是用了上个方法创建的公私钥对
    HslCommunication.Core.Security.HslCertificate cert = new HslCommunication.Core.Security.HslCertificate( Convert.FromBase64String( pubKey ), Convert.FromBase64String( priKey ) );
    cert.From = "Company A";   // 发证方
    cert.To = "Company B";     // 使用方,持有者
    cert.CreateTime = DateTime.Today;  // 发证日期
    cert.NotBefore = new DateTime( 2023, 2, 16 ); // 起始日期
    cert.NotAfter = new DateTime( 2023, 3, 15 );  // 假设一个月有效期
    cert.KeyWord = "HslCommunication";    // 可以根据实际情况指定
    cert.Descriptions = new Dictionary<string, string>( )
    {
        { "ApiMulti", "1" }
    };

    // 获取证书的字节
    byte[] source = cert.GetSaveBytes( );

    // 证书写入到文件
    System.IO.File.WriteAllBytes( "C:\\cert.cert", source );

    // 变成字符串发给别人使用
    string str = Convert.ToBase64String( source );
    System.IO.File.WriteAllText( "C:\\cert.txt", str, Encoding.UTF8 );
}
参见