- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我见过很多问题,但没有一个真正提供好的答案,或者即使他们尝试了,他们也会假设提出问题的人并没有问他实际上在问什么。郑重声明,我不是在询问签名、加密或 PEM 文件!
就我而言,我将收到一个加密数据的小文件。它已使用 RSA key 对的私钥加密。
我可用的公钥是 ASN.1 格式的 DER 文件,它本身不是证书,也没有签名。
在 Java 中,这很容易,在 C# 中,据我所知这是一场噩梦。当我尝试将 X509Certificate2 解析为 key 的字节数组时,它声称“找不到对象”。
key 是使用以下 openSSL 命令生成的:
>openssl genrsa -out private_key.pem 2048
Generating RSA private key, 2048 bit long modulus
...........+++
....................................................................................................
...........................+++
e is 65537 (0x10001)
>openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
>openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
writing RSA key
编辑:我正在尝试的代码:
private byte[] ReadBytesFromStream(string streamName)
{
using (Stream stream = this.GetType().Assembly.GetManifestResourceStream(streamName))
{
byte[] result = new byte[stream.Length];
stream.Read(result, 0, (int) stream.Length);
return result;
}
}
public void LoadPublicKey()
{
byte[] key = ReadBytesFromStream("my.namespace.Resources.public_key.der");
X509Certificate2 myCertificate;
try
{
myCertificate = new X509Certificate2(key);
}
catch (Exception e)
{
throw new CryptographicException(String.Format("Unable to open key file. {0}", e));
}
}
ReadBytesFromStream 方法确实返回了正确的字节流,public_key.der 文件是一个嵌入式资源。
最佳答案
只是为了完善这一点。虽然下面的代码仍然有点困惑,但它似乎是我可以开始工作的。
我们不能在 Windows 中使用公钥解密消息的原因解释如下: http://www.derkeiler.com/Newsgroups/microsoft.public.dotnet.security/2004-05/0270.html
接下来,您需要 C# 代码中的公钥模数和指数,在某个地方,无论是在文件中还是嵌入在此处真的不是问题。不过,我确实使用 Base64 来包装二进制 key 。我放弃了生成 Windows 实际导入的 key 。此外,对于我所需要的,公钥将是一个嵌入式资源。
我遇到的最后一个问题是从 key 生成的模数在 Windows (c#) 上不起作用。这篇 StackOverflow 帖子确实掌握了解决这个问题的关键,Windows 中的模数不能包含前导零。 Android in-app billing Verification of Receipt in Dot Net(C#)
从 Java 生成的模数在 C# 上不起作用。使用该帖子中的 stripLeadingZeros 代码创建一个有效的公钥模数:
private static byte[] stripLeadingZeros(byte[] a) {
int lastZero = -1;
for (int i = 0; i < a.length; i++) {
if (a[i] == 0) {
lastZero = i;
}
else {
break;
}
}
lastZero++;
byte[] result = new byte[a.length - lastZero];
System.arraycopy(a, lastZero, result, 0, result.length);
return result;
}
对于初学者,这是我生成 key 文件的方式:
$ openssl genrsa -out private_key.pem 2048
$ openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
$ openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
Java 代码:
package com.example.signing;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import jcifs.util.Base64;
public class SigningExample {
private static String PRIVATE_KEY_FILE = "private_key.der";
private static String PUBLIC_KEY_FILE = "public_key.der";
/**
* @param args
*/
public static void main(String[] args) {
SigningExample.sign();
}
private static void sign() {
try {
String text = new String(SigningExample.loadFromFile("message.xml"));
String message = Base64.encode(text.getBytes());
RSAPrivateKey privateKey = PrivateRSAKeyReader.getKeyFile(SigningExample.PRIVATE_KEY_FILE);
RSAPublicKey publicKey = PublicRSAKeyReader.getKeyFile(SigningExample.PUBLIC_KEY_FILE);
byte[] modulusBytes = publicKey.getModulus().toByteArray();
byte[] exponentBytes = publicKey.getPublicExponent().toByteArray();
modulusBytes = SigningExample.stripLeadingZeros(modulusBytes);
String modulusB64 = Base64.encode(modulusBytes);
String exponentB64 = Base64.encode(exponentBytes);
System.out.println("Copy these two into your c# code:");
System.out.println("DotNet Modulus : " + modulusB64);
System.out.println("DotNet Exponent: " + exponentB64);
// Testing
byte[] signature = SigningExample.sign(message.getBytes(), privateKey, "SHA1withRSA");
String signedMessage = message + "\n" + Base64.encode(signature);
SigningExample.saveToBase64File("message.signed", signedMessage.getBytes());
System.out.println("\nMessage :\n" + signedMessage);
String[] newkey = new String(SigningExample.loadFromBase64File("message.signed")).split("\\n");
System.out.println("Verified : " + SigningExample.verify(newkey[0].getBytes(), publicKey, "SHA1withRSA", Base64.decode(newkey[1])));
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] stripLeadingZeros(byte[] a) {
int lastZero = -1;
for (int i = 0; i < a.length; i++) {
if (a[i] == 0) {
lastZero = i;
} else {
break;
}
}
lastZero++;
byte[] result = new byte[a.length - lastZero];
System.arraycopy(a, lastZero, result, 0, result.length);
return result;
}
private static byte[] sign(byte[] data, PrivateKey prvKey,
String sigAlg) throws Exception {
Signature sig = Signature.getInstance(sigAlg);
sig.initSign(prvKey);
sig.update(data, 0, data.length);
return sig.sign();
}
private static boolean verify(byte[] data, PublicKey pubKey,
String sigAlg, byte[] sigbytes) throws Exception {
Signature sig = Signature.getInstance(sigAlg);
sig.initVerify(pubKey);
sig.update(data, 0, data.length);
return sig.verify(sigbytes);
}
public static void saveToBase64File(String fileName, byte[] data) throws IOException {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));
try {
String b64 = Base64.encode(data);
int lineLength = 64;
int idx = 0;
int len = b64.length();
while (len - idx >= lineLength) {
out.write(b64.substring(idx, idx + lineLength).getBytes());
out.write('\n');
idx += lineLength;
}
out.write(b64.substring(idx, len).getBytes());
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
out.close();
}
}
public static byte[] loadFromBase64File(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
try {
StringBuffer sb = new StringBuffer();
String buffer;
while ((buffer = br.readLine()) != null) {
sb.append(buffer);
}
return Base64.decode(sb.toString());
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
br.close();
}
}
public static void saveToFile(String fileName, byte[] data) throws IOException {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));
try {
out.write(data);
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
out.close();
}
}
public static byte[] loadFromFile(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
try {
StringBuffer sb = new StringBuffer();
String buffer;
while ((buffer = br.readLine()) != null) {
sb.append(buffer);
}
return sb.toString().getBytes();
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
br.close();
}
}
}
class PrivateRSAKeyReader {
public static RSAPrivateKey getKeyFile(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
return PrivateRSAKeyReader.generateKey(keyBytes);
}
public static RSAPrivateKey getKey(String base64) throws Exception {
byte[] keyBytes = Base64.decode(base64);
return PrivateRSAKeyReader.generateKey(keyBytes);
}
private static RSAPrivateKey generateKey(byte[] keyBytes) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
return (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(spec);
}
}
class PublicRSAKeyReader {
public static RSAPublicKey getKeyFile(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
return PublicRSAKeyReader.generateKey(keyBytes);
}
public static RSAPublicKey getKey(String base64) throws Exception {
byte[] keyBytes = Base64.decode(base64);
return PublicRSAKeyReader.generateKey(keyBytes);
}
private static RSAPublicKey generateKey(byte[] keyBytes) throws Exception {
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
return (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(spec);
}
}
在 c# 中,这段代码片段应该可以解决问题:
String signedMessage = ""; // load Base64 coded the message generated in Java here.
byte[] message = Convert.FromBase64String(signedMessage);
String messageString = Encoding.ASCII.GetString(message);
String[] lines = Regex.Split(messageString, "\n");
byte[] content = Convert.FromBase64String(lines[0]); // first line of the message were the content
byte[] signature = Convert.FromBase64String(lines[1]); // second line were the signature
RSACryptoServiceProvider rsaObj = new RSACryptoServiceProvider(2048);
//Create a new instance of the RSAParameters structure.
RSAParameters rsaPars = new RSAParameters();
rsaPars.Modulus = Convert.FromBase64String("insert your modulus revealed in the Java example here");
rsaPars.Exponent = Convert.FromBase64String("AQAB"); // Exponent. Should always be this.
// Import key parameters into RSA.
rsaObj.ImportParameters(rsaPars);
// verify the message
Console.WriteLine(rsaObj.VerifyData(Encoding.ASCII.GetBytes(lines[0]), "SHA1", signature));
代码正在使用:
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
我承认将最终消息打包到另一层 Base64 有点矫枉过正,应该改变。
关于C# 使用 RSA DER 格式公钥解密文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10299262/
如何选择随机哈希键?对于 my Flash+Perl card game我正在尝试从哈希中随机选择一张卡片,其中的键是:“6 黑桃”、“6 俱乐部”等,如下所示: my $card; my $i =
每当我收到对端点的请求时,我都会使用openssl crate 生成随 secret 钥。我将使用新生成的 key 来加密请求数据,并将其作为响应发送回去。 use openssl::rsa::{Rs
我们知道,我们在代码中生成的“随机”数实际上是伪随机数。在Java的情况下,它们默认使用时间戳作为随机种子,并且从该点开始确定性地创建时间戳之后产生的每个随机数。 如果您使用随机数生成密码,并且恶意方
我想用java生成一个128位随 secret 钥。我正在使用以下内容: byte[] byteBucket = new byte[bytelength]; randomizer.nextBytes(
这个问题已经有答案了: Pick random property from a Javascript object (9 个回答) 已关闭 7 个月前。 如果我有以下内容: var liststuff
我做了一些研究,找不到我需要的东西,基本上我想生成一个具有以下格式的随 secret 钥 XXX-XXX-XXXX 最佳答案 这是一个快速的 Javascript 解决方案: let r = Math
在 Firebase 中,可以使用 .childByAutoId() 创建随 secret 钥 let newEntry = FBRef.child("category").childByAutoId
假设我有一个带有大量键的对象: const myObject = { "a": 1, "b": 2, "c": 3, ... } 如果我存储了一个单独的 key 列表,
我需要计算一些字符串的签名,并计划这样做: using (HMACSHA256 hmacSha256 = new HMACSHA256( )) { Byte[] dataToHmac
我的任务是生成随机的 80 字节 key ,我决定遵循以下策略 在我的电脑中sizeof(char)=1 所以我创建了一个英文字母数组 char *p=" "; char a[0..26] and i
我正在设计一个广告系统,该系统根据广告的权重(出价)在广告之间随机轮换。 local ads = local ads = { ["a"] = { views = 0,
我有一个整数列表(员工 ID)它们都是8位长(虽然几乎都是00开头,但实际上都是8位长) 我需要为每个员工生成一个 key : - 5 chars including [A-Z][a-z][0-9]
我使用 KeyPairGenerator 生成 RSA key 对,我注意到它始终生成完全匹配的 key ,而不是应有的随 secret 钥?也许有人知道为什么会这样? 我的代码现在看起来像这样: p
我正在运行一个 FIRESTORE 数据库,我想创建一个具有与 firestore 相同的模式 的随 secret 钥。 在链接中,我找到了创建文档后调用的函数with: 'db.ref.add()'
这个问题已经有答案了: Add a property to a JavaScript object using a variable as the name? (14 个回答) Creating ob
我想生成 1M 随机(出现)唯一字母数字键并将它们存储在数据库中。每个 key 的长度为 8 个字符,并且仅使用子集“abcdefghijk n pqrstuvxyz 和 0-9”。 字母 l、m、o
我想生成像“7HzdUakp”这样的唯一 key 。 我想将其放入数据库(mysql)中,但我想要几乎无限的组合。 我可以使用随机函数生成它,但有时它可以生成相同的 key 两次 已解决 - 我根据“
我有一个我似乎无法弄清楚的基本问题。我正在尝试在 AES-256-CBC 中生成一个可用于加密/解密数据的随 secret 钥。 这是我正在做的: require 'openssl' cipher =
如果您对 Azure 网站使用自动缩放,是否需要设置计算 secret 钥,以便可以在计算机之间共享加密的身份验证 token ? 这里有一个问题,似乎be the same正如我所问的那样。然而,这
我想根据创建日期和时间从 Firebase 中检索数据我还没有找到任何其他方法,而不是通过使用 orderByChild("Create") 创建每个用户的 child 来保存创建日期和时间排序,但是
我是一名优秀的程序员,十分优秀!