我想使用SHA-384生成384位椭圆曲线签名,以生成我运行以下步骤的密钥,方法是查看此SO从OpenSSL命令行生成EC密钥对
openssl ecparam -name secp384r1 -genkey -noout -out d:/private.ec.key
openssl ec -in d:/private.pem -pubout -out d:/public.pem
openssl pkcs8 -topk8 -nocrypt -in d:/private.ec.key -out d:/private.pem
当我被要求输入密码时,我按了enter键(因为我不想有密码保护的密钥)。
然后我为我的JRE 14下载了BC prov-JDK 15 on-168 . jar Bouncy Castle lib,并将其添加到我的类路径中。并制作了小的测试应用程序,把这些密钥的内容直接复制到java源代码中去。
制作了一个简单的剥离方法来删除密钥的“文本”部分并解码其base 64内容:
private static byte[] bytesFromKeyStrings(String string) {
string = string.replaceAll("-----BEGIN PRIVATE KEY-----", "");
string = string.replaceAll("-----BEGIN EC PRIVATE KEY-----", "");
string = string.replaceAll("-----END EC PRIVATE KEY-----", "");
string = string.replaceAll("-----END PRIVATE KEY-----", "");
string = string.replaceAll("\r", "");
string = string.replaceAll("\n", "");
var bytes = Base64.getDecoder().decode(string);
return bytes;
}
然后我从这些字节中产生一个私钥:
private static PrivateKey keyFromBytes(byte[] pkcs8key) throws NoSuchAlgorithmException, InvalidKeySpecException {
Security.addProvider(BOUNCY_CASTLE_PROVIDER);
var spec = ECNamedCurveTable.getParameterSpec("secp384r1");;
var ecPrivateKeySpec = new ECPrivateKeySpec(new BigInteger(1, pkcs8key), spec);
var factory = KeyFactory.getInstance("ECDSA", BOUNCY_CASTLE_PROVIDER);
return factory.generatePrivate(ecPrivateKeySpec);
}
但是当我要使用PriateKey对消息进行签名(在本例中为零数组)时,我会得到异常:
var key = keyFromBytes(bytesFromKeyStrings(privatePem));
var ecdsaSign = Signature.getInstance("SHA384withECDSA", BOUNCY_CASTLE_PROVIDER);
ecdsaSign.initSign(key, new SecureRandom());
ecdsaSign.update(content);
var signature = ecdsaSign.sign();
在线上造成:
ecdsaSign。initSign(key,new SecureRandom());
java.lang.IllegalArgumentException: Scalar is not in the interval [1, n - 1]
at org.bouncycastle.provider/org.bouncycastle.crypto.params.ECDomainParameters.validatePrivateScalar(ECDomainParameters.java:146)
at org.bouncycastle.provider/org.bouncycastle.crypto.params.ECPrivateKeyParameters.<init>(ECPrivateKeyParameters.java:16)
at org.bouncycastle.provider/org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.generatePrivateKeyParameter(ECUtil.java:245)
at org.bouncycastle.provider/org.bouncycastle.jcajce.provider.asymmetric.ec.SignatureSpi.engineInitSign(Unknown Source)
at java.base/java.security.SignatureSpi.engineInitSign(SignatureSpi.java:131)
at java.base/java.security.Signature$Delegate.engineInitSign(Signature.java:1364)
at java.base/java.security.Signature.initSign(Signature.java:658)
at ecdsa/ecdsa.Main.main(Main.java:75)
如果我正确地理解ECDSA,我们需要将私钥乘以一些随机值,所以我为它提供了安全的Random。奇怪的是,我以前的尝试,当我没有尝试读取密钥并使用KeyPairGenerator.getInstance(“EC”)(没有弹跳城堡库)动态生成它们时,这些生成的密钥可用于无一例外地对消息进行签名,并且我单独验证了生成的签名是正确的。
我生产的密钥不好,还是有其他方法来提供乘数常量,所以它不试图直接与私钥签名并给我例外?
还是我错过了什么愚蠢的事情?
下面是我的测试应用程序的完整列表,它可以复制异常:
package ecdsa;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
public class Main {
private final static String privatePem = "-----BEGIN PRIVATE KEY-----\r\n"
+ "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBBdsy5smSA2+DvnIdx\r\n"
+ "bqq6GwwHadEdtHqcKO9N8hB0/NKvFOCmHBSfBpYPgCWlybGhZANiAAQ0iyw2wPjs\r\n"
+ "zhale0mPkiCCTzcNzTW1g7zqUoN3XNuZbaK1FHhVVMsywUaS6MSUJI6r1QcUziMm\r\n"
+ "MWGYZUSSq4noniTDt8INj/ElndKhbh3oSCq3j1oKK9cYXi3uGuDFXks=\r\n"
+ "-----END PRIVATE KEY-----\r\n";
private final static String privateEc = "-----BEGIN EC PRIVATE KEY-----\r\n"
+ "MIGkAgEBBDBBdsy5smSA2+DvnIdxbqq6GwwHadEdtHqcKO9N8hB0/NKvFOCmHBSf\r\n"
+ "BpYPgCWlybGgBwYFK4EEACKhZANiAAQ0iyw2wPjszhale0mPkiCCTzcNzTW1g7zq\r\n"
+ "UoN3XNuZbaK1FHhVVMsywUaS6MSUJI6r1QcUziMmMWGYZUSSq4noniTDt8INj/El\r\n"
+ "ndKhbh3oSCq3j1oKK9cYXi3uGuDFXks=\r\n"
+ "-----END EC PRIVATE KEY-----\r\n";
private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider();
private static byte[] bytesFromKeyStrings(String string) {
string = string.replaceAll("-----BEGIN PRIVATE KEY-----", "");
string = string.replaceAll("-----BEGIN EC PRIVATE KEY-----", "");
string = string.replaceAll("-----END EC PRIVATE KEY-----", "");
string = string.replaceAll("-----END PRIVATE KEY-----", "");
string = string.replaceAll("\r", "");
string = string.replaceAll("\n", "");
var bytes = Base64.getDecoder().decode(string);
return bytes;
}
private static PrivateKey keyFromBytes(byte[] pkcs8key) throws NoSuchAlgorithmException, InvalidKeySpecException {
Security.addProvider(BOUNCY_CASTLE_PROVIDER);
var spec = ECNamedCurveTable.getParameterSpec("secp384r1");;
var ecPrivateKeySpec = new ECPrivateKeySpec(new BigInteger(1, pkcs8key), spec);
var factory = KeyFactory.getInstance("ECDSA", BOUNCY_CASTLE_PROVIDER);
return factory.generatePrivate(ecPrivateKeySpec);
}
public static void main(String[] args) {
var content = new byte[100];
try {
var key = keyFromBytes(bytesFromKeyStrings(privatePem));
var ecdsaSign = Signature.getInstance("SHA384withECDSA", BOUNCY_CASTLE_PROVIDER);
ecdsaSign.initSign(key, new SecureRandom());
ecdsaSign.update(content);
var signature = ecdsaSign.sign();
} catch (Exception e) {
e.printStackTrace();
}
}
}
编辑:更新了示例(之前我使用加密的私钥)
根据 https://lapo.it/asn1js/ 您在PEM编码中的私钥仍然是加密的 - 直接可见“-----开始加密的私钥-----”:
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.5.13 pkcs5PBES2 (PKCS #5 v2.0)
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.5.12 pkcs5PBKDF2 (PKCS #5 v2.0)
SEQUENCE (3 elem)
OCTET STRING (8 byte) 1B9485597126CBC4
INTEGER 2048
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.2.9 hmacWithSHA256 (RSADSI digestAlgorithm)
NULL
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.16.840.1.101.3.4.1.42 aes256-CBC (NIST Algorithm)
OCTET STRING (16 byte) 6EE87374559F76BC362E29AE5A2E80FC
OCTET STRING (192 byte) 50AF006CB4E8E42D9992155F9D749F35E7D4BA9D88975C70174157AC0D96909FDDF9F…
要获取工作且未加密的文件,请使用此OpenSSL命令将加密文件转换为未加密文件:
openssl pkcs8 -topk8 -nocrypt -in ecprivateencrypted.pem -out ecprivateunencrypted.pem
我试着自己转换文件,但是我的OpenSSL拒绝了,因为密码长度太短了。
我在第二个答案中回答,因为我的第一个答案不再适合这个问题,因为您编辑了您的问题并将私钥pem更改为未加密数据。
由于您的密钥是私钥的编码形式,因此它具有PKCS#8结构,因此任何读取器都能够识别密钥的类型和底层曲线,因此您无需使用ECPrivateKeySpec构建它。有一种更简单的方法可以使用此代码:
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(pkcs8key);
return keyFactory.generatePrivate(privateKeySpec);
公钥也是如此,只需使用X509EncodedKeySpec(参见完整代码示例)。
我添加了bytesFromKeyStrings-函数来将公钥的密钥数据转换成一个字节数组。
下面是一个完整的示例代码,用于读取私钥pem、对消息进行签名、读取公钥pem(源自私钥)并按照预期结果以“true”验证签名。
输出:
signatureVerified: true
安全警告:以下代码没有异常处理,仅用于教育目的:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class MainSo {
private final static String privatePem = "-----BEGIN PRIVATE KEY-----\r\n"
+ "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBBdsy5smSA2+DvnIdx\r\n"
+ "bqq6GwwHadEdtHqcKO9N8hB0/NKvFOCmHBSfBpYPgCWlybGhZANiAAQ0iyw2wPjs\r\n"
+ "zhale0mPkiCCTzcNzTW1g7zqUoN3XNuZbaK1FHhVVMsywUaS6MSUJI6r1QcUziMm\r\n"
+ "MWGYZUSSq4noniTDt8INj/ElndKhbh3oSCq3j1oKK9cYXi3uGuDFXks=\r\n"
+ "-----END PRIVATE KEY-----\r\n";
/*
Key Details:
Type: EC
Size (bits): 384
Curve Name: secp384r1
Curve OID: 1.3.132.0.34
Public key (x):
348b2c36c0f8ecce16a57b498f9220824f370dcd35b583bcea5283775cdb996d
a2b514785554cb32c14692e8c494248e
Public key (y):
abd50714ce2326316198654492ab89e89e24c3b7c20d8ff1259dd2a16e1de848
2ab78f5a0a2bd7185e2dee1ae0c55e4b
Private key (d):
4176ccb9b26480dbe0ef9c87716eaaba1b0c0769d11db47a9c28ef4df21074fc
d2af14e0a61c149f06960f8025a5c9b1
Public Key in PEM Format:
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENIssNsD47M4WpXtJj5Iggk83Dc01tYO8
6lKDd1zbmW2itRR4VVTLMsFGkujElCSOq9UHFM4jJjFhmGVEkquJ6J4kw7fCDY/x
JZ3SoW4d6Egqt49aCivXGF4t7hrgxV5L
-----END PUBLIC KEY-----
*/
private final static String publicPem = "-----BEGIN PUBLIC KEY-----\n" +
"MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENIssNsD47M4WpXtJj5Iggk83Dc01tYO8\n" +
"6lKDd1zbmW2itRR4VVTLMsFGkujElCSOq9UHFM4jJjFhmGVEkquJ6J4kw7fCDY/x\n" +
"JZ3SoW4d6Egqt49aCivXGF4t7hrgxV5L\n" +
"-----END PUBLIC KEY-----";
private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider();
private static byte[] bytesFromKeyStrings(String string) {
string = string.replaceAll("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
string = string.replaceAll("-----BEGIN PRIVATE KEY-----", "");
string = string.replaceAll("-----BEGIN PUBLIC KEY-----", "");
string = string.replaceAll("-----BEGIN EC PRIVATE KEY-----", "");
string = string.replaceAll("-----END EC PRIVATE KEY-----", "");
string = string.replaceAll("-----END ENCRYPTED PRIVATE KEY-----", "");
string = string.replaceAll("-----END PRIVATE KEY-----", "");
string = string.replaceAll("-----END PUBLIC KEY-----", "");
string = string.replaceAll("\r", "");
string = string.replaceAll("\n", "");
return Base64.getDecoder().decode(string);
}
private static PrivateKey privateKeyFromBytes(byte[] pkcs8key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
Security.addProvider(BOUNCY_CASTLE_PROVIDER);
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(pkcs8key);
return keyFactory.generatePrivate(privateKeySpec);
}
private static PublicKey publicKeyFromBytes(byte[] x509key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
Security.addProvider(BOUNCY_CASTLE_PROVIDER);
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(x509key);
return keyFactory.generatePublic(publicKeySpec);
}
public static void main(String[] args) {
System.out.println("https://stackoverflow.com/questions/65740255/scalar-is-not-in-the-interval-1-n-1-exception-when-signing-ecdsa-with-sha/65742506?noredirect=1#comment116237430_65742506");
var content = new byte[100];
try {
// signature with private key
var privateKey = privateKeyFromBytes(bytesFromKeyStrings(privatePem));
var ecdsaSign = Signature.getInstance("SHA384withECDSA", BOUNCY_CASTLE_PROVIDER);
ecdsaSign.initSign(privateKey, new SecureRandom());
ecdsaSign.update(content);
var signature = ecdsaSign.sign();
// verification with the public key
var publicKey = publicKeyFromBytes(bytesFromKeyStrings(publicPem));
var ecdsaVerify = Signature.getInstance("SHA384withECDSA", BOUNCY_CASTLE_PROVIDER);
ecdsaVerify.initVerify(publicKey);
ecdsaVerify.update(content);
boolean signatureVerified = ecdsaVerify.verify(signature);
System.out.println("signatureVerified: " + signatureVerified);
} catch (Exception e) {
e.printStackTrace();
}
}
}
为什么它不起作用
OpenSSL支持的所有密钥格式不仅仅是原始密钥,还包括一些元数据;特别是,所有EC关键点都是meaningul,仅可用于关键点文件中包含的特定曲线。openssl pkcs8-topk8[-nocrypt]
产生的两种格式是pkcs8中定义的未加密和加密格式,更方便地作为RFC5208获得,您可以在维基百科中轻松找到。在PEM类型“开始/结束私钥”和“开始/终止加密私钥”中使用这些格式在RFC7468第10节和第11节中进行了形式化,尽管OpenSSL早在几十年前就将其作为事实上的标准。
Michael Fehr的第一个答案向您展示了加密形式的分解,但即使是未加密的形式也仍然包含元数据,这些元数据使用secp384r1(也称为P-384曲线)将其识别为EC算法:
$ cat 65740255.clr
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBBdsy5smSA2+DvnIdx
bqq6GwwHadEdtHqcKO9N8hB0/NKvFOCmHBSfBpYPgCWlybGhZANiAAQ0iyw2wPjs
zhale0mPkiCCTzcNzTW1g7zqUoN3XNuZbaK1FHhVVMsywUaS6MSUJI6r1QcUziMm
MWGYZUSSq4noniTDt8INj/ElndKhbh3oSCq3j1oKK9cYXi3uGuDFXks=
-----END PRIVATE KEY-----
$ openssl asn1parse <65740255.clr -i
0:d=0 hl=3 l= 182 cons: SEQUENCE
3:d=1 hl=2 l= 1 prim: INTEGER :00
6:d=1 hl=2 l= 16 cons: SEQUENCE
8:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
17:d=2 hl=2 l= 5 prim: OBJECT :secp384r1
24:d=1 hl=3 l= 158 prim: OCTET STRING [HEX DUMP]:30819B02010104304176CCB9B26480DBE0EF9C87716EAABA1B0C0769D11DB47A9C28EF4DF21074FCD2AF14E0A61C149F06960F8025A5C9B1A16403620004348B2C36C0F8ECCE16A57B498F9220824F370DCD35B583BCEA5283775CDB996DA2B514785554CB32C14692E8C494248EABD50714CE2326316198654492AB89E89E24C3B7C20D8FF1259DD2A16E1DE8482AB78F5A0A2BD7185E2DEE1AE0C55E4B
对于任何熟悉ASN.1的人来说,PKCS8中未加密的最后一个字段(依赖于算法的编码)本身就是一个ASN.1结构。RFC5915基于“SEC1”文档指定了X9类型EC privatekey的ASN.1结构(但不是更新的EC算法,如Bernstein等人的EdDSA)。解析我们看到它实际上包含实际的privatekey(即在Java S中通常表示为d的数字)和publickey(在Java W中通常表示为Q的点,以X9未压缩格式表示)(这在技术上是多余的,因为它可以从privatekey和曲线方程中重新计算出来):
$ openssl asn1parse <65740255.clr -i -strparse 27 -dump
0:d=0 hl=3 l= 155 cons: SEQUENCE
3:d=1 hl=2 l= 1 prim: INTEGER :01
6:d=1 hl=2 l= 48 prim: OCTET STRING
0000 - 41 76 cc b9 b2 64 80 db-e0 ef 9c 87 71 6e aa ba Av...d......qn..
0010 - 1b 0c 07 69 d1 1d b4 7a-9c 28 ef 4d f2 10 74 fc ...i...z.(.M..t.
0020 - d2 af 14 e0 a6 1c 14 9f-06 96 0f 80 25 a5 c9 b1 ............%...
56:d=1 hl=2 l= 100 cons: cont [ 1 ]
58:d=2 hl=2 l= 98 prim: BIT STRING
0000 - 00 04 34 8b 2c 36 c0 f8-ec ce 16 a5 7b 49 8f 92 ..4.,6......{I..
0010 - 20 82 4f 37 0d cd 35 b5-83 bc ea 52 83 77 5c db .O7..5....R.w\.
0020 - 99 6d a2 b5 14 78 55 54-cb 32 c1 46 92 e8 c4 94 .m...xUT.2.F....
0030 - 24 8e ab d5 07 14 ce 23-26 31 61 98 65 44 92 ab $......#&1a.eD..
0040 - 89 e8 9e 24 c3 b7 c2 0d-8f f1 25 9d d2 a1 6e 1d ...$......%...n.
0050 - e8 48 2a b7 8f 5a 0a 2b-d7 18 5e 2d ee 1a e0 c5 .H*..Z.+..^-....
0060 - 5e 4b ^K
另一种选择
如果您除了bcprov
之外还使用BouncyCastle bcpkix
jar,它还提供了直接读取(和写入)所有OpenSSL PEM格式的例程,包括PKCS8和OpenSSL的“传统”或“传统”算法特定格式 BEGIN/END EC PRIVATE KEY
,这只是PEM包装中的SEC1。例如:
读取 JAVA 中格式为 PKCS1 的
RSA 私钥 从 RSA .pem 文件
获取私钥 使用 BouncyCastle 从文件中读取椭圆曲线私钥
如何从文件加载 RSA 私钥
(尽管其中一些是针对 RSA 的,但问题与 EC 相同)。
String pk8e = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n"
+ "MIIBHDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIG5SFWXEmy8QCAggA\r\n"
+ "MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBBu6HN0VZ92vDYuKa5aLoD8BIHA\r\n"
+ "UK8AbLTo5C2ZkhVfnXSfNefUup2Il1xwF0FXrA2WkJ/d+fokLijgkTyal43t8iMJ\r\n"
+ "ne3gOjYP8Q558x+4k4TAMWug0nDh9RPINMqABnhPkf5wyCCYI2RN2b3C4SZCBMQw\r\n"
+ "r+cwVgwiShhPHcuUM9BmFlt9eCr3kuFnfMxlvvpR482kIT+Q6+hZsyUL/oJjOVC9\r\n"
+ "R2S7AwiKH4BPj5TBjMKF4ZI5cS0DMXn1q3h21AUdMPUchX6itcDTfWvEIfTwpUr0\r\n"
+ "-----END ENCRYPTED PRIVATE KEY-----\r\n";
String pk8u = "-----BEGIN PRIVATE KEY-----\r\n"
+ "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBBdsy5smSA2+DvnIdx\r\n"
+ "bqq6GwwHadEdtHqcKO9N8hB0/NKvFOCmHBSfBpYPgCWlybGhZANiAAQ0iyw2wPjs\r\n"
+ "zhale0mPkiCCTzcNzTW1g7zqUoN3XNuZbaK1FHhVVMsywUaS6MSUJI6r1QcUziMm\r\n"
+ "MWGYZUSSq4noniTDt8INj/ElndKhbh3oSCq3j1oKK9cYXi3uGuDFXks=\r\n"
+ "-----END PRIVATE KEY-----\r\n";
String trad = "-----BEGIN EC PRIVATE KEY-----\r\n"
+ "MIGkAgEBBDBBdsy5smSA2+DvnIdxbqq6GwwHadEdtHqcKO9N8hB0/NKvFOCmHBSf\r\n"
+ "BpYPgCWlybGgBwYFK4EEACKhZANiAAQ0iyw2wPjszhale0mPkiCCTzcNzTW1g7zq\r\n"
+ "UoN3XNuZbaK1FHhVVMsywUaS6MSUJI6r1QcUziMmMWGYZUSSq4noniTDt8INj/El\r\n"
+ "ndKhbh3oSCq3j1oKK9cYXi3uGuDFXks=\r\n"
+ "-----END EC PRIVATE KEY-----\r\n";
@SuppressWarnings("resource") // should use try-resources or similar
Object o1 = new PEMParser (new StringReader (pk8e)).readObject();
PrivateKey k1 = new JcaPEMKeyConverter().getPrivateKey(
((org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo)o1).decryptPrivateKeyInfo(
new JceOpenSSLPKCS8DecryptorProviderBuilder().build(/*password*/"".toCharArray()) ));
System.out.println ( ((java.security.interfaces.ECPrivateKey)k1).getS() .toString(16));
@SuppressWarnings("resource") // should use try-resources or similar
Object o2 = new PEMParser (new StringReader (pk8u)).readObject();
PrivateKey k2 = new JcaPEMKeyConverter().getPrivateKey((PrivateKeyInfo)o2);
System.out.println ( ((java.security.interfaces.ECPrivateKey)k2).getS() .toString(16));
@SuppressWarnings("resource") // should use try-resources or similar
Object o3 = new PEMParser (new StringReader (trad)).readObject();
PrivateKey k3 = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair)o3).getPrivate();
System.out.println ( ((java.security.interfaces.ECPrivateKey)k3).getS() .toString(16));
->
4176ccb9b26480dbe0ef9c87716eaaba1b0c0769d11db47a9c28ef4df21074fcd2af14e0a61c149f06960f8025a5c9b1
4176ccb9b26480dbe0ef9c87716eaaba1b0c0769d11db47a9c28ef4df21074fcd2af14e0a61c149f06960f8025a5c9b1
4176ccb9b26480dbe0ef9c87716eaaba1b0c0769d11db47a9c28ef4df21074fcd2af14e0a61c149f06960f8025a5c9b1
并且该(十六进制)数字是“原始”私钥,这是您可以在ECPrivateKeySpec
中为您发布的方法放置的值(作为正BigInteger
)。(我不得不使一些名称符合包条件,因为在我的开发环境中,我有冲突的导入;你可能不需要它。
我正在使用C#和.NET4.7使用BouncyCastle进行签名验证。 我在这里跟随一个回答,所以在这里解释了使用SHA-256withECDSA的验证过程。 因此,我使用两种方法验证签名的代码在下面的代码片段中运行良好。 我正在尝试将其调整到我的用例,该用例正在使用ECDSA签名验证SHA-384。我发现的唯一区别是密钥长度不同。对于 SHA-256 与 ECDSA,使用的公钥长度转换为 64
问题内容: 我正在尝试从字符串计算SHA-1哈希,但是当我使用php的sha1函数计算字符串时,我得到的东西与在C#中尝试时有所不同。我需要C#计算与PHP相同的字符串(因为php的字符串是由我无法修改的第三方计算的)。如何获取C#以生成与PHP相同的哈希值?谢谢!!! 字串= s934kladfklada@a.com C#代码(生成d32954053ee93985f5c3ca2583145668
两者的区别是什么 和 ? 第一个语句的输出是 [0 0…n次] 而第二个是 ([0] [0] .... n行)
我正在将我们的DAO从使用Hibernate Criteria API迁移到JPA Criteria API。我有一个包含多个的类: 在查询中,我使用的是JoinType。左键以消除默认生成的交叉连接: 我得到了正确的结果,所有的A和B记录都得到了正确的检索。然而,在迁移之后,我遇到了一个问题:尽管在生成的查询中使用了左外连接,但所有的记录都是逐个检索的。以前(使用Hibernate Criter
问题内容: 我在sql中有一个普遍的疑问。实际上,“ Top 1 1”将做什么?以下查询的含义是什么? SQL Server查询中选择“ TOP 1 1”和“ SELECT 1”之间的区别是什么? 问题答案: 表示在结果集中选择第一条记录 平均值返回1作为结果集 表示如果条件为true,并且从select返回了任何行,则仅返回顶部行,并且仅返回该行的整数(仅返回整数1就没有数据)。
问题内容: 为什么呢?如我所料是0。 问题答案: 所有移位都针对整数进行mod 32,对long进行mod 64。 从规范的第15.19节开始: 如果左侧操作数的提升类型为,则仅将右侧操作数的最低5位用作移位距离。就像右侧操作数受到掩码值0x1f的按位逻辑AND运算符&(§15.22.1)一样。因此,实际使用的移动距离始终在0到31(含)范围内。 如果左侧操作数的提升类型为,则仅将右侧操作数的六个