简体   繁体   English

在C#中为HMAC SHA1生成公钥和密钥

[英]Generate public key and secret for HMAC SHA1 in C#

我想在Asp.Net MVC 3上为REST API服务实现类似于HMAC-SHA Signature算法的AWS 。是否有任何最佳实践来生成用户的公钥和密钥?

We've built a similar system. 我们建立了一个类似的系统。 The question that @James references gives very good information. @James引用的问题提供了非常好的信息。 Be sure to read it. 一定要读它。 If possible, only deploy your service over SSL/TLS. 如果可能,仅通过SSL / TLS部署您的服务。

With HMAC-SHA signature you don't need a public key. 使用HMAC-SHA签名,您不需要公钥。 There is one secret key shared by the server (service) and the client that is used to compute the signature. 服务器(服务)和用于计算签名的客户端共享一个密钥。 Per the question on the security site referenced above, make sure you have different keys for each client. 根据上面引用的安全站点上的问题,确保每个客户端都有不同的密钥。

For each client you should also have service client id of some sort that is different than any other Ids you have to identify the client. 对于每个客户端,您还应该具有某种服务客户端ID,这与您必须识别客户端的任何其他ID不同。 This service client id is sent in the request header so you can identify the client. 此服务客户端ID在请求标头中发送,因此您可以标识客户端。 Once you've identified the client, you can obtain the required information about the client including the client's service key. 一旦确定了客户端,就可以获得有关客户端的必需信息,包括客户端的服务密钥。

In addition to the service client id, the request header should contain the actual signature that was generated. 除了服务客户端ID之外,请求标头还应包含生成的实际签名。 I would also recommend including a time stamp in the header as well (more on this below). 我还建议在标题中加入一个时间戳(下面有更多内容)。 So your request would have headers similar to these: 所以你的请求会有类似这样的标题:

MySvc-Clientid: ServiceId
MySvc-Signature: Signature
MySvc-Timestamp: TimeStamp

To generate client keys using .NET/C# you can create a method that generates a string representation of a Rijndael key which can be delivered to the client. 要使用.NET / C#生成客户端密钥,您可以创建一个方法,该方法生成可以传递给客户端的Rijndael密钥的字符串表示。 Here is an example. 这是一个例子。

    public string CreateServiceClientKey()
    {
        SymmetricAlgorithm symAlg = SymmetricAlgorithm.Create("Rijndael");

        symAlg.KeySize = 128;

        byte[] key = symAlg.Key;

        StringBuilder sb = new StringBuilder(key.Length * 2);

        foreach (byte b in key)
        {
            sb.AppendFormat("{0:x2}", b);
        }

        return sb.ToString();
    }

In our system, when a new service client is enabled, a service client id and service key are generated and stored in the database for the client. 在我们的系统中,当启用新的服务客户端时,将生成服务客户端ID和服务密钥,并将其存储在客户端的数据库中。 The service client id could just be a GUID. 服务客户端ID可以只是一个GUID。

The client's service key is a shared secret between you and the client. 客户端的服务密钥是您和客户之间的共享密钥。 Only deliver it to the client via a secure mechanism, such as a authenticated portion of your website running on SSL/TLS. 仅通过安全机制将其传递给客户端,例如在SSL / TLS上运行的网站的经过身份验证的部分。 Otherwise, you open yourself up to someone else obtaining the secret key. 否则,您将自己打开给其他获取密钥的人。

The timestamp should be generated by the client and be included in the string to sign from which the signature is generated. 时间戳应由客户端生成,并包含在要从中生成签名的字符串中。 This adds time specific variability to the signature. 这增加了签名的时间特定可变性。 AWS does this as well. AWS也是这样做的。

In regard to the string to sign, on your side I'd also recommend defining an interface that you program to for building your string to sign when comparing against the request signature. 关于要签名的字符串,在您身边我还建议您定义一个接口,您可以编程以在与请求签名进行比较时构建要签名的字符串。 This will allow you to build to different implementations for different services or even different operations. 这将允许您构建不同的服务甚至不同的操作的不同实现。 This came in handy for our implementation. 这对我们的实施很有用。 Here is an example: 这是一个例子:

public interface IStringToSignBuilder
{
    string Build(ServiceSignatureDetails details);
}

/// <summary>
/// Class is a data entity that defines the specific details
/// required for a Service Signature
/// </summary>
public class ServiceSignatureDetails
{
    public string HttpMethod { get; set; }
    public string ServiceClientId { get; set; }
    public string ServiceClientKey { get; set; }
    public string UriAbsolutePath { get; set; }
    public string DomainName { get; set; }
    public string CompanyName { get; set; }
    public string DateTimeStamp { get; set; }
    public string Data { get; set; }
}

You can then build specific implementations of IStringToSignBuilder that meet your needs and inject the correct one into your code accordingly. 然后,您可以构建满足您需求的IStringToSignBuilder特定实现,并相应地将正确的实现注入到您的代码中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM