我正在尝试使用OpenSSL中的DSA进行签名.我有包含公钥和私钥的文件.
首先,我建立一个单播连接,一切都很好.之后,我需要一个多播UDP连接,我想签署数据包.我正在尝试使用函数PEM_read_DSA_PUBKEY()来从我的证书加载我的公钥,但它不起作用.它总是返回NULL而不是DSA结构.
这里有一个简单的代码版本.我像这样编译:
gcc -Wall -g -lm prueba.c -o prueba -lcrypto
Run Code Online (Sandbox Code Playgroud)
任何的想法?谢谢!
#include <stdio.h>
#include <openssl/dsa.h>
#include <openssl/pem.h>
int main()
{
FILE *DSA_cert_file = fopen("./certs/cert.pem", "r");
if (DSA_cert_file == NULL)
return 1;
printf("Certificate read\n");
DSA *dsa = DSA_new();
if((dsa = PEM_read_DSA_PUBKEY(DSA_cert_file, 0, 0, 0)) == NULL)
return 1;
printf("DSA public key read\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我需要使用 java 生成 PEM 格式的 RSA 和 DSA 密钥对(公钥和私钥)。\n我希望使用以下格式打开公钥和私钥文件:
\n\n\n\n\n-----开始公钥----- MIIBIjANBgkqhkiG9w0BAQEFAOCAQ8AMIIBCgKCAQEAryQICCl6NZ5gDKrnSztO\n 3Hy8PEUcuyvg/ikC+VcIo2SFFSf18a3IMYldIugqqqZCs4/4uVW3sbdLs/6PfgdX\n 7O9D 22ZiFWHPYA2k2N744MNiCD1UE+tJyllUhSblK480亿+v1oZHCM0nYQ2NqUkvS\n j+hwUU3RiWl7x3D2s9wSdNt7XUtW05a/FXehsPSiJfKvHJJnGOX0BgTvkLnkAOTd\n OrUZ/wK69Dzu4I vrN4vs9Nes8vbwPa/ddZEzGR0cQMt0JBkhk9kU/qwqUseP1QRJ\n 5I1jR4g8aYPL/ke9K35PxZWuDp3U0UPAZ3PjFAh+5T+fc7gzCs9dPzSHloruU+gl\n FQIDAQAB\n -----结束公钥-----
\n
我的公钥之前已经以这种格式生成,但我不想要它:
\n\n\n\n\n0\xc5\xb80 *\xe2\x80\xa0H\xe2\x80\xa0\xc3\xb7 0\xc5\xb80 *\xe2\x80\xa0H\xe2\x80\xa0\xc3\xb7
\n
好的,这是我的密钥生成代码:
\n\nprivate static void createKey()\n throws Exception {\n\n Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());\n\n BufferedReader in = new BufferedReader(new InputStreamReader(System.in));\n System.out.print("Password to encrypt the private key: ");\n String password = in.readLine();\n System.out.println("Generating an RSA keypair...");\n\n // Create an RSA key\n KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");\n keyPairGenerator.initialize(1024);\n KeyPair keyPair = keyPairGenerator.genKeyPair();\n\n System.out.println("Done …Run Code Online (Sandbox Code Playgroud) 我终于设法验证了一些简单的PGP签名消息块.但是,我发现由于某种原因,我的实现限制了我验证长度为9-16个字节的数据.不会少.不再.
是否有某些指令(RFC4880或其他地方)指定如何处理任何长度的明文数据?也许我错过了某种填充?PKCS1?
我敢肯定我被格式化的数据正确地散列,因为在RFC 4880秒5.2.4说明书说的文本文档,只需更换所有\n与\r\n添加的拖车.由于我的测试值是单行数据,因此不需要替换任何内容
除非另有说明,否则所有这些值均以10为基数:
// DSA public key values
p = 175466718616740411615640156350265486163809613514213656685227237159351776260193236923030228927905671867677337184318134702903960237546408302010360724274436019639502405323187799029742776686067449287558904042137172927936686590837020160292525250748155580652384740664931255981772117478967314777932252547256795892071
q = 809260232002608708872165272150356204306578772713
g = 127751900783328740354741342100721884490035793278553520238434722215554870393020469115393573782393994875216405838455564598493958342322790638050051759023658096740912555025710033120777570527002197424160086000659457154926758682221072408093235236853997248304424303705425567765059722098677806247252106481642577996274
y = 172935968966072909036304664996424500241381878537444332146572958203083745609400290814117451480512268901233962890933482206538294509037615827035398352528065134903071886710296983781453184598843331365336270501467458073523376152406987560592548479865116940266729198119357206749848310472131186772143408998928864559411
Run Code Online (Sandbox Code Playgroud)
不工作:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
abcd
-----BEGIN PGP SIGNATURE-----
Version: BCPG v1.39
iFsEARECABsFAk/tB28UHGFiYyA8bWFrY21AYWFhLmNvbT4ACgkQMFIlRc933Ya2
RwCfdMyI08Iz0rDXVHOPlGA3s5Y9j/8An2He7+hHjWfGJNoOJT7gAxqJaoLo
=I2rT
-----END PGP SIGNATURE-----
data hashed (in hex): 6162636404011102001b05024fed076f141c616263203c6d616b636d406161612e636f6d3e04ff00000021
r = 666804200764671083282351405489424949903645052927
s = 558743769080942454889260816818443017172325925608
w = 702955297882281869313155599553522395227576660460 // s^-1 mod q
u1 = 190417717173929082607343542521304347388874234334
u2 = 306786785479358548892951170619047936651163362761
v = g^u1 * y^u2 % p % …Run Code Online (Sandbox Code Playgroud) 为了使用公钥身份验证 ssh,
DSA-2048 密钥对已使用 openssl 生成,并且均以 PEM 格式存储在本地。现在,为了在服务器端进行配置(authorized_keys),公钥必须采用 RFC-4716 格式。
通常作为一种实践,为了获取此密钥,ssh-keygen 通常与以下选项一起使用,
ssh-keygen -y -f private_key.pem
Run Code Online (Sandbox Code Playgroud)
它返回必须在服务器端配置的相应公钥(RFC-4716)。
如果没有 ssh-keygen,openssl 本身是否有可能从 openssl 生成的公钥(或)私钥生成 RFC-4716 特定公钥?
我需要一种计算方法:
(g^u * y^v) mod p
Run Code Online (Sandbox Code Playgroud)
在Java中.
我发现这个算法用于计算(g ^ u)mod p:
int modulo(int a,int b,int c) {
long x=1
long y=a;
while(b > 0){
if(b%2 == 1){
x=(x*y)%c;
}
y = (y*y)%c; // squaring the base
b /= 2;
}
return (int) x%c;
}
Run Code Online (Sandbox Code Playgroud)
它工作得很好,但我似乎找不到办法做到这一点
(g^u * y^v) mod p
Run Code Online (Sandbox Code Playgroud)
因为我的数学技能乏善可陈.
把它放在上下文中,它是用于"减少"DSA的java实现 - 验证部分要求解决它.
我正在编写一个大量使用密码学的应用程序。像大多数网络应用程序一样,我的将数据分解为不同类型的消息(即时消息、文件块、视频帧等)——并且必须检查每个消息的真实性,以防止篡改和正确的来源。到目前为止,我能够使用 ECDH 来协商我已经用于 AES 的共享秘密。当然,以后可以使用相同的共享秘密。
我的问题是:在这种情况下,使用 ECDSA 来签署每条消息是否有任何额外的好处,而不是简单地使用 ECDH 与 HMAC 建立的共享秘密?
下面,当我说 M 时,我的意思是加密消息或明文;应该没关系。请更正以下任何错误。
我知道在 ECDSA(或 DSA)中,通常M使用安全散列算法(我目前使用 SHA-2 之一)对消息 ( ) 进行散列处理H(M),然后H(M)使用签名者的私钥对其进行加密。这会产生R和S整数(签名)。然后,M、R 和 S 被发送给已经拥有发送者公钥的接收者。 H'(M)计算,并使用R和验证签名S。BouncyCastle 提供了ECDSASigner实现这一点的方法。
在 HMAC 中,需要一个共享机密,我有。然后:(
HMAC(K, M) := H( f2(K) || H(f1(K) || M) )
感谢您的更正,Pa?lo Ebermann。有关详细信息,请参阅他的回答。)
那么,考虑到 DH/ECDH 安全地协商共享秘密,我是否有理由不使用 HMAC?
相关:为什么NSA为 DSA 而不是 MAC 指定标准算法?仅仅因为它可以是 SHA-2 + AES?
速度在这里很重要,因为我希望我正在制定的这个协议不仅支持现在的文本消息,而且在不久的将来支持大文件和视频帧。因此,我更喜欢使用 HMAC,但要确保我可以达到上述目标。
谢谢你的帮助!
我正在尝试实现 DSA 签名算法,但遇到了一个问题。我正在使用java.security MessageDigest该类,这是代码:
MessageDigest md;
md = MessageDigest.getInstance("SHA-1");
md.update(text.getBytes());
return new BigInteger(md.digest());
Run Code Online (Sandbox Code Playgroud)
Text 是一个随机的 String 对象。问题是这段代码给了我散列的负值,这是算法不接受的。难道我做错了什么?提前致谢。
PS顺便说一句,我也尝试过不使用BigIntegers来实现DSA,这可能吗?我没有找到小于 1024 和 160 的 L 和 N 值,所以我不知道我应该取什么值以及我应该使用什么哈希函数。将非常感谢听到这些问题的答案。
我尝试了以下方法来生成具有2048位密钥长度的DSA私有(和公共)密钥:
通过keytool
keytool -genkeypair -alias MyKeyPair -keyalg DSA -keysize 2048 -validity 365 -keystore MyKeyStore.ks
Run Code Online (Sandbox Code Playgroud)
导致:
keytool错误:java.lang.IllegalArgumentException:模数大小必须介于512到1024之间,并且是64的倍数
通过代码
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(keyAlgorithm,"BC");
keyGen.initialize(numBits);
Run Code Online (Sandbox Code Playgroud)
导致:
Exception in thread "main" java.security.InvalidParameterException: strength must be from 512 - 1024 and a multiple of 64
at org.bouncycastle.jcajce.provider.asymmetric.dsa.KeyPairGeneratorSpi.initialize(Unknown Source)
at java.security.KeyPairGenerator.initialize(KeyPairGenerator.java:340)
Run Code Online (Sandbox Code Playgroud)
上面的例子使用了Bouncy Castle的实现,因为我读到的地方应该支持2048位的DSA密钥.我也尝试了具有相同错误的默认值.
我安装了(JCE)Unlimited Strength Jurisdiction Policy Files.根据此输出,您可能希望有大键:
System.out.println("DSA Max key length: " + Cipher.getMaxAllowedKeyLength("DSA"));
DSA Max key length: 2147483647
Run Code Online (Sandbox Code Playgroud)
但是,如果您在JCE Providers文档中选择了Keysize限制,则1024位是最大值.
谁可以判断Java 7中是否支持2048位私钥?或者,如果有另一种方法来创建此大小的密钥并将其导入Java密钥库?
在Java的API 8赠送它将支持更大的按键.所以我们可能需要等到明年.
情况
我有两个任意来源,比如说StringSource来自签名的一个和FileSource来自相应签名文件的一个。我现在想验证当前执行的文件签名,如下所示:
bool VerifyFile(const ECDSA<ECP, SHA512>::PublicKey &key,
const std::string &filename,
const std::string &signatureString) {
std::string fileContentString;
FileSource(filename.c_str(), true,
new CryptoPP::StringSink(fileContentString));
bool result = false;
StringSource(signatureString + fileContentString, true,
new SignatureVerificationFilter(
ECDSA<ECP, SHA512>::Verifier(key),
new ArraySink((byte *) &result, sizeof(result))
) // SignatureVerificationFilter
);
return result;
}
Run Code Online (Sandbox Code Playgroud)
我的问题
我不想将文件的内容显式提取到字符串中,然后进行串联并随后进行验证。
问题
有没有一种方法可以将两个任意源传递给验证实体,其中一个表示签名,另一个表示签名内容(可能是文件或字符串)?
到目前为止我尝试过的
我尝试重定向Source::TransferAll(...)到 a ,但没有成功。RedirecterSignatureVerificationFilter
我使用以下命令生成 DSA 密钥:
ssh-keygen -t dsa
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用 bouncycastle API 来签署数据,如下所示:
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
String privateKeyContent = // the content of the generated file
//init privateKey
byte[] pemContent = null;
PEMParser pemParser = new PEMParser(new StringReader(privateKeyContent));
Object pemObject = pemParser.readObject(); // throws
Run Code Online (Sandbox Code Playgroud)
并得到这个异常
java.io.IOException:无法识别的对象:OPENSSH 私钥
所以我一直在尝试使用此示例将密钥文件转换为 PEM ,并执行:
ssh-keygen -e -f key -m PEM > key.pem
Run Code Online (Sandbox Code Playgroud)
但我收到错误:
do_convert_to_pem: unsupported key type DSA
Run Code Online (Sandbox Code Playgroud)
关于如何解决这个问题有什么想法吗?