Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SecretKeySpec的C#等价物是什么_Java_C#_Cryptography_Sha1_Hmac - Fatal编程技术网

Java SecretKeySpec的C#等价物是什么

Java SecretKeySpec的C#等价物是什么,java,c#,cryptography,sha1,hmac,Java,C#,Cryptography,Sha1,Hmac,我用Java编写了以下代码 Mac mac = Mac.getInstance("HmacSHA1"); String secretKey ="sKey"; String content ="Hello"; byte[] secretKeyBArr = secretKey.getBytes(); byte[] contentBArr = content.getBytes(); SecretKeySpec secret_key = new SecretKeySpec(secretKey

我用Java编写了以下代码

Mac mac = Mac.getInstance("HmacSHA1");
String secretKey ="sKey";
String content ="Hello";

byte[] secretKeyBArr = secretKey.getBytes();    
byte[] contentBArr = content.getBytes();

SecretKeySpec secret_key = new SecretKeySpec(secretKeyBArr,"HmacSHA1");
byte[] secretKeySpecArr = secret_key.getEncoded();

mac.init(secret_key);

byte[] final = mac.doFinal(contentBArr);
我想用C#做同样的例子。因此,我编写了以下代码

HMACSHA1 hmacsha1 = new HMACSHA1();
string secretKey = "sKey";
string content = "Hello";

byte[] secretKeyBArr = Encoding.UTF8.GetBytes(secretKey);
byte[] contentBArr = Encoding.UTF8.GetBytes(content);

hmacsha1.Key = secretKeyBArr;
byte[] final = hmacsha1.ComputeHash(contentBArr);

最终的结果并不相同。secretKeyBArr和contentBArr是字节数组,在这两个示例中它们的值相同。未知的是传递给mac.init()的SecretKeySpec。那么,在C#中什么是等效的同一类?

结果是相同的,但是Java使用有符号字节,而C#默认使用无符号字节


此外,
SecretKeySpec
本身通常不会更改基础数据。例如,您需要将DES密钥规范放入
SecretKey工厂
,以确保奇偶校验位设置正确(在生成的
SecretKey
中)。因此,不需要一个等价的类,因为类本身除了包装数据之外几乎没有什么作用。

我正在从一个提供程序(cardinity)实现一个信用卡支付方法,它不提供.net实现。我正在寻找类似的东西,并最终写了我自己的谷歌技能似乎是

我需要的是javax.crypto.mac的base64字符串

我支持以下方法:

enum EncryptionMethods
{
    None=0,
    HMACSHA1,
    HMACSHA256,
    HMACSHA384,
    HMACSHA512,
    HMACMD5
}
我以以下方式实现了上面的代码、SecretKeySpec和Mac(您需要System.Security.Cryptography.ProtectedData):

然后,这不是您所要求的,但我需要一个帮助器方法,因为我正在将文本发送到一个类似这样的web服务,我将其包括在内,因为有些人可能会复制代码:

public static String PercentEncode(string textToEncode)
{

    return string.IsNullOrEmpty(textToEncode)
        ?""
        : UrlEncoder.Default.Encode(Cardinity.ENCODING.GetString(Cardinity.ENCODING.GetBytes(textToEncode)))
            .Replace("+", "%20").Replace("*", "%2A")
            .Replace("%7E", "~");

}
类UrlEncoder来自System.Text.Encodings.Web,您可能需要添加一个引用

名为Cardinity的类实现了我用于Cardinity的编码的“捷径”

public abstract class Cardinity
{
    ...
    public static String API_BASE = "https://api.cardinity.com";
    public static String API_VERSION = "v1";
    public static String VERSION = "0.1";
    public static String ENCODING_CHARSET = "UTF-8";
    public static Encoding ENCODING => Encoding.UTF8;
}
由于Java经常使用string.GetBytes,因此我为此添加了一个扩展方法,我在上面的key.GetBytes()中调用了该方法,下面是扩展代码:

public static byte[] GetBytes(this string sender)=>
            Cardinity.ENCODING.GetBytes(sender);
在我的测试方法中,我复制了Cardinity Pass的值,没有任何问题

private OAuthSigner signer;
public HmacOAuthSigner_Test()
{
    signer = new HmacOAuthSigner();
}

[TestMethod]
public void Test_HmacOAuthSigner_ComputeSignature_DefaultText()
{
    var expects = "PxkffxyQh6jsDNcgJ23GpAxs2y8=";
    var test_data = "justsomerandommessage";
    var secretkey = "yvp0leodf231ihv9u29uuq6w8o4cat9qz2nkvs55oeu833s621";

    var actual = signer.ComputeSignature(test_data, secretkey);
    Assert.AreEqual(expects, actual, $"Expecting {test_data} to return {expects} received {actual}");
}
HmacOAuthSigner的整个实现在这里,它实现了一个抽象类,其中包含PercentEncode方法

public class HmacOAuthSigner : OAuthSigner
{
    public override string ComputeSignature(string signatureBaseString, string consumerSecret)
    {
        var key = PercentEncode(consumerSecret) + "&";
        var secretKey = new SecretKeySpec(key.GetBytes(), EncryptionMethods.HMACSHA1);
        using (Mac mac = new Mac(secretKey, signatureBaseString))
        {
            return mac.AsBase64();
        }
    }

    public override string GetSignatureMethod()
    {
        return "HMAC-SHA1";
    }
}
以及我用作所有实现契约的抽象类:

public abstract class OAuthSigner
{
    /// <summary>
    /// Signature method used
    /// </summary>
    /// <returns>a string that tells the implementation method</returns>
    public abstract string GetSignatureMethod();

    /// <summary>
    /// computes the signature that is used with the encryption based on the keys provided by cardinity
    /// </summary>
    /// <param name="signatureBaseString">The secret string that services as a base</param>
    /// <param name="consumerSecret">The consumer key as specified in the API settings</param>
    /// <returns>signature string computed by the provided parameters using the signature method</returns>
    public abstract string ComputeSignature(String signatureBaseString, String consumerSecret);

    /// <summary>
    /// Encode a string into a format expected by Cardinity
    /// </summary>
    /// <param name="textToEncode">The text that is to be encoded</param>
    /// <returns>web encoded string ready for using to send to Cardinity</returns>
    public static String PercentEncode(string textToEncode)
    {

        return string.IsNullOrEmpty(textToEncode)
            ?""
            : UrlEncoder.Default.Encode(Cardinity.ENCODING.GetString(Cardinity.ENCODING.GetBytes(textToEncode)))
                .Replace("+", "%20").Replace("*", "%2A")
                .Replace("%7E", "~");

    }
}
公共抽象类OAuthSigner
{
/// 
///使用的签名方法
/// 
///告诉实现方法的字符串
公共抽象字符串GetSignatureMethod();
/// 
///根据cardinity提供的密钥计算与加密一起使用的签名
/// 
///用作基的秘密字符串
///API设置中指定的使用者密钥
///使用签名方法由提供的参数计算的签名字符串
公共抽象字符串ComputeSignature(字符串SignatureBasString,字符串ConsumerCret);
/// 
///将字符串编码为Cardinity期望的格式
/// 
///要编码的文本
///web编码字符串,可用于发送到Cardinity
公共静态字符串百分比编码(字符串文本编码)
{
返回字符串.IsNullOrEmpty(textToEncode)
?""
:UrlEncoder.Default.Encode(Cardinity.ENCODING.GetString(Cardinity.ENCODING.GetBytes(textToEncode)))
.替换(“+”,“%20”).替换(“*”,“%2A”)
.替换(“%7E”和“~”);
}
}

您可能想编辑问题的标题,以表示关于java SecretKeySpec的C#equalent的实际问题密钥有多长?
SecretKeySpec
除了在
“HmacSha1”的情况下存储字节之外,没有什么作用。问题可能在别处。PS如何比较结果?只需读取示例Java和C#中的字节数组。好的,但Java代码现在使用默认字符编码。如果它返回与UTF-8不同的编码(对于ASCII文本不太可能,但对于其他文本很可能),那么比较将失败。我像使用getBytes(Charset.forName(“UTF-8”))之前一样获得相同的值。我希望结果中没有“[”字符?没有。我比较了VS和Eclipse中的最终字节数组。这是正确的。将C#中的字节数组转换为有符号字节数组。
public class HmacOAuthSigner : OAuthSigner
{
    public override string ComputeSignature(string signatureBaseString, string consumerSecret)
    {
        var key = PercentEncode(consumerSecret) + "&";
        var secretKey = new SecretKeySpec(key.GetBytes(), EncryptionMethods.HMACSHA1);
        using (Mac mac = new Mac(secretKey, signatureBaseString))
        {
            return mac.AsBase64();
        }
    }

    public override string GetSignatureMethod()
    {
        return "HMAC-SHA1";
    }
}
public abstract class OAuthSigner
{
    /// <summary>
    /// Signature method used
    /// </summary>
    /// <returns>a string that tells the implementation method</returns>
    public abstract string GetSignatureMethod();

    /// <summary>
    /// computes the signature that is used with the encryption based on the keys provided by cardinity
    /// </summary>
    /// <param name="signatureBaseString">The secret string that services as a base</param>
    /// <param name="consumerSecret">The consumer key as specified in the API settings</param>
    /// <returns>signature string computed by the provided parameters using the signature method</returns>
    public abstract string ComputeSignature(String signatureBaseString, String consumerSecret);

    /// <summary>
    /// Encode a string into a format expected by Cardinity
    /// </summary>
    /// <param name="textToEncode">The text that is to be encoded</param>
    /// <returns>web encoded string ready for using to send to Cardinity</returns>
    public static String PercentEncode(string textToEncode)
    {

        return string.IsNullOrEmpty(textToEncode)
            ?""
            : UrlEncoder.Default.Encode(Cardinity.ENCODING.GetString(Cardinity.ENCODING.GetBytes(textToEncode)))
                .Replace("+", "%20").Replace("*", "%2A")
                .Replace("%7E", "~");

    }
}