java - 如何将带有 ASN1 和 SHA256 的数字签名从 C# 转换为 Java
问题描述
昨天,我决定做数字签名,然后我找到了 c# 示例代码。我试图将其转换为 java,但由于我的知识有限,它还没有完成。
这是 C# 代码
public string Sign(string payload, string privateKey)
{
List<string> segments = new List<string>();
var header = new { alg = "RS256" };
DateTime issued = DateTime.Now;
DateTime expire = DateTime.Now.AddHours(10);
byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
byte[] payloadBytes = Encoding.UTF8.GetBytes(payload);
segments.Add(Base64UrlEncode(headerBytes));
segments.Add(Base64UrlEncode(payloadBytes));
string stringToSign = string.Join(".", segments.ToArray());
byte[] bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
byte[] keyBytes = Convert.FromBase64String(privateKey);
var privKeyObj = Asn1Object.FromByteArray(keyBytes);
var privStruct = RsaPrivateKeyStructure.GetInstance((Asn1Sequence)privKeyObj);
ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");
sig.Init(true, new RsaKeyParameters(true, privStruct.Modulus, privStruct.PrivateExponent));
sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length);
byte[] signature = sig.GenerateSignature();
//segments.Add(Base64UrlEncode(signature));
return Base64UrlEncode(signature);
}
private static string Base64UrlEncode(byte[] input)
{
var output = Convert.ToBase64String(input);
output = output.Split('=')[0]; // Remove any trailing '='s
output = output.Replace('+', '-'); // 62nd char of encoding
output = output.Replace('/', '_'); // 63rd char of encoding
return output;
}
然后这是我的转换 java 代码,我尝试从 Java 逐行覆盖到 C#。但是某些代码行让我感到困惑。
private static String sign(String payload, String privateKey) throws Exception{
String header = "{\"alg\":\"RS256\"}";
Date issued = new Date();
Date expire = new Date( issued.getTime() + 10 * 60 * 60 * 1000 );
byte[] headerBytes = header.getBytes(StandardCharsets.UTF_8);
byte[] payloadBytes = payload.getBytes(StandardCharsets.UTF_8);
String stringToSign = Base64UrlEncode(headerBytes) + "." + Base64UrlEncode(payloadBytes);
byte[] byteToSign = stringToSign.getBytes(StandardCharsets.UTF_8);
byte[] keyBytes = Base64.getDecoder().decode(privateKey.getBytes(StandardCharsets.UTF_8));
PemReader reader = new PemReader(new StringReader(privateKey));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(reader.readPemObject().getContent());
KeyFactory kf = KeyFactory.getInstance("RSA");
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(kf.generatePrivate(spec));
privateSignature.update(byteToSign);
byte[] signature = privateSignature.sign();
return Base64UrlEncode(signature);
}
private static String Base64UrlEncode(byte[] input){
String output = java.util.Base64.getEncoder().encodeToString(input);
output = output.split("=")[0];
output.replace('+','-');
output.replace('/','_');
return output;
}
我对那些 C# 代码行感到困惑
var privKeyObj = Asn1Object.FromByteArray(keyBytes);
var privStruct = RsaPrivateKeyStructure.GetInstance((Asn1Sequence)privKeyObj);
ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");
sig.Init(true, new RsaKeyParameters(true, privStruct.Modulus, privStruct.PrivateExponent));
sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length);
byte[] signature = sig.GenerateSignature();
//segments.Add(Base64UrlEncode(signature));
return Base64UrlEncode(signature);
SignerUtilities Init 和 BlockUpdate 到底是什么?我可以用什么类来用 ASN1Object 替换 SignerUtilities
感谢所有阅读这篇文章的人!
解决方案
推荐阅读
- field - micronaut 多值表单字段支持?
- c++ - 这个 C++ 隐式转换是如何发生的?
- html - 在 Bootstrap 中减少内容之间空间的最简洁方法
- java - 我想使用注释 @ComponentScan 但我收到错误“考虑定义类型的 bean”SpringBoot 2.1.0.RELEASE
- django - Django,在运行服务器中运行时从 STATIC_ROOT 提供静态文件?
- authentication - Kerberos 双跳类似问题 - 即使不使用 Windows 身份验证
- phonegap-build - 应用程序加载器警告,cordova webview
- android - 如何使用recyclerview实现Material Design父子过渡
- django - 如何在 Django 中获取过去 6 天的数据?
- javascript - Spotify API 对 api/token 授权的错误请求错误:400