gpt4 book ai didi

Java:如何对文件使用 PKCS#1 编码

转载 作者:行者123 更新时间:2023-11-30 07:04:41 25 4
gpt4 key购买 nike

我已经用 Java 实现了 RSA key 对生成。我正在生成公钥和私钥,然后将它们作为 BigInteger 值存储在文件中。

我必须对这些文件使用 PKCS#1 编码。我对密码学比较陌生。谁能给我一个简单的例子,如何做到这一点?

<小时/>

注意:我可能不会使用任何外部 Java 库。

为了完整起见,我发布了用于生成公钥/私钥的代码:

private void generateKeys(int bits, int certainty,
String publicKeyFile, String secretKeyFile) throws IOException {
p = new BigInteger(bits, certainty, new Random());

do
q = new BigInteger(bits, certainty, new Random());
while (!p.gcd(q).equals(BigInteger.valueOf(1)));

n = p.multiply(q);
BigInteger phiN = p.subtract(BigInteger.valueOf(1)).
multiply(q.subtract(BigInteger.valueOf(1)));

do
e = new BigInteger(bits, new Random());
while (!e.gcd(phiN).equals(new BigInteger("1")));

BigInteger d = e.modInverse(phiN);
dp = d.mod((p.subtract(BigInteger.valueOf(1))));
dq = d.mod((q.subtract(BigInteger.valueOf(1))));
qinv = q.modInverse(p);

write(secretKeyFile, n + "\n" + e + "\n" + d + "\n" + p + "\n" + q + "\n" +
dp + "\n" + dq + "\n" + qinv);

write(publicKeyFile, n + "\n" + e);

System.out.println("n = " + n.toString(16));
System.out.println("e = " + e.toString(16));
System.out.println("d = " + d.toString(16));
System.out.println("p = " + p.toString(16));
System.out.println("q = " + q.toString(16));
System.out.println("dp = " + dp.toString(16));
System.out.println("dq = " + dq.toString(16));
System.out.println("qinv = " + qinv.toString(16));
}

最佳答案

好的,所以您必须实现 PKCS#1 中的结构,以下代码应该可以工作(警告,大部分未经测试,但 ASN.1 可以解析):

package nl.owlstead.stackoverflow;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Random;

/**
* Generates a key pair and then saves the key to PKCS#1 format on disk.
* <p>
* From <a href="https://tools.ietf.org/html/rfc3447#appendix-C">RFC 3441,
* Appendix C</a>:
*
* <pre>
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER -- e
* }
*
* --
* -- Representation of RSA private key with information for the CRT
* -- algorithm.
* --
* RSAPrivateKey ::= SEQUENCE {
* version Version,
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* privateExponent INTEGER, -- d
* prime1 INTEGER, -- p
* prime2 INTEGER, -- q
* exponent1 INTEGER, -- d mod (p-1)
* exponent2 INTEGER, -- d mod (q-1)
* coefficient INTEGER, -- (inverse of q) mod p
* otherPrimeInfos OtherPrimeInfos OPTIONAL
* }
* </pre>
*
* @author owlstead
*
*/
public class SimplePKCS1 {

private static final byte SEQUENCE_TAG = 0x30;
private static final byte INTEGER_TAG = 0x02;

private static void writePublicKeyToPKCS1(
String publicKeyFile,
BigInteger n, BigInteger e) {

try {
ByteArrayOutputStream integerStream =
new ByteArrayOutputStream();
encodeInteger(integerStream, n);
encodeInteger(integerStream, e);
byte[] encodedIntegers = integerStream.toByteArray();

try (FileOutputStream fos =
new FileOutputStream(publicKeyFile)) {
fos.write(SEQUENCE_TAG);
encodeLength(fos, encodedIntegers.length);
fos.write(encodedIntegers);
}
} catch (IOException ex) {
throw new IllegalStateException("Somaliland?");
}
}

private static void writePrivateKeyToPKCS1(
String secretKeyFile,
BigInteger n, BigInteger e, BigInteger d,
BigInteger p, BigInteger q,
BigInteger dp, BigInteger dq,
BigInteger qinv) {
try {
ByteArrayOutputStream integerStream =
new ByteArrayOutputStream();
encodeInteger(integerStream, n);
encodeInteger(integerStream, e);
encodeInteger(integerStream, d);
encodeInteger(integerStream, p);
encodeInteger(integerStream, q);
encodeInteger(integerStream, dp);
encodeInteger(integerStream, dq);
encodeInteger(integerStream, qinv);
byte[] encodedIntegers = integerStream.toByteArray();

try (FileOutputStream fos = new FileOutputStream(secretKeyFile)) {
fos.write(SEQUENCE_TAG);
encodeLength(fos, encodedIntegers.length);
fos.write(encodedIntegers);
}
} catch (IOException ex) {
throw new IllegalStateException("Somaliland?");
}
}

/**
* Writes an explicit DER encoded integer (tag, length and value).
*
* @param os
* the stream to write to
* @param i
* the integer to write
* @throws IOException
* any IOException thrown by the output stream
*/
private static void encodeInteger(OutputStream os, BigInteger i)
throws IOException {
os.write(INTEGER_TAG);
byte[] encodedInteger = i.toByteArray();
encodeLength(os, encodedInteger.length);
os.write(encodedInteger);
}

/**
* Encodes a length in DER format (minimum, definite BER size).
*
* @param os
* the stream to write to
* @param length
* the length of the value to write
* @throws IOException
* any IOException thrown by the output stream
*/
private static void encodeLength(OutputStream os, int length)
throws IOException {
final DataOutputStream dos = new DataOutputStream(os);
if (length < (1 << (Byte.SIZE - 1))) {
dos.write(length);
} else if (length < (1 << Byte.SIZE)) {
dos.write(0x81);
dos.write(length);
} else if (length < (1 << Short.SIZE)) { // let's hope so :)
dos.write(0x82);
dos.writeShort(length);
} else {
throw new IllegalArgumentException(
"Cannot handle integers over 65535 bytes in size");
}
}

/*
* === the existing code and calls to the required functionality ===
*/

private static void generateAndWriteKeys(
int bits, int certainty,
String publicKeyFile, String secretKeyFile) {
BigInteger p = new BigInteger(bits, certainty, new Random());

BigInteger q;
do {
q = new BigInteger(bits, certainty, new Random());
} while (!p.gcd(q).equals(BigInteger.valueOf(1)));

BigInteger n = p.multiply(q);
BigInteger phiN = p.subtract(BigInteger.valueOf(1)).multiply(
q.subtract(BigInteger.valueOf(1)));

BigInteger e;
do {
e = new BigInteger(bits, new Random());
} while (!e.gcd(phiN).equals(new BigInteger("1")));

BigInteger d = e.modInverse(phiN);
BigInteger dp = d.mod((p.subtract(BigInteger.valueOf(1))));
BigInteger dq = d.mod((q.subtract(BigInteger.valueOf(1))));
BigInteger qinv = q.modInverse(p);

writePublicKeyToPKCS1(publicKeyFile, n, e);
writePrivateKeyToPKCS1(secretKeyFile, n, e, d, p, q, dp, dq, qinv);

}

public static void main(String[] args) {
generateAndWriteKeys(1024, Integer.MAX_VALUE, args[0], args[1]);
}
}
<小时/>

以下方法展示了如何解析回内容。

private static PublicKey readPublicKeyFromPKCS1(
String publicKeyFile) {

try {
try (FileInputStream fis =
new FileInputStream(publicKeyFile)) {

byte sequence = read(fis);
if (sequence != SEQUENCE_TAG) {
throw new IOException("No sequence tag found");
}


int length = decodeLength(fis);
// use a CountingInputStream to check if the length of the SEQUENCE is correct

BigInteger n = decodeInteger(fis);
BigInteger e = decodeInteger(fis);

return new PublicKey(n, e);
}
} catch (IOException ex) {
throw new IllegalStateException("Somaliland?", ex);
}
}

private static BigInteger decodeInteger(InputStream is) throws IOException {
byte integer = read(is);
if (integer != INTEGER_TAG) {
throw new IOException("No integer tag found");
}
int size = decodeLength(is);
ByteArrayOutputStream integerValueStream = new ByteArrayOutputStream(size);
for (int i = 0; i < size; i++) {
byte b = read(is);
integerValueStream.write(b);
}
byte[] integerValue = integerValueStream.toByteArray();
return new BigInteger(integerValue);
}

private static int decodeLength(InputStream is) throws IOException {
int firstByte = read(is) & 0xFF;
if (firstByte < 0x80) {
return firstByte;
}

switch (firstByte) {
case 0x80:
throw new IOException("Invalid length");
case 0x81:
byte length = read(is);
return length & 0xFF;
case 0x82:
int lengthHi = read(is) & 0xFF;
int lengthLo = read(is) & 0xFF;
return (int) (lengthHi << Byte.SIZE + lengthLo);
default:
throw new IOException("Length encoding unsupported");
}
}

private static byte read(InputStream is) throws IOException {
int x = is.read();
if (x == -1) {
throw new IOException("End of file reached before structure could be read");
}
return (byte) x;
}

PublicKey 只是一个带有 ne 字段的数据容器。

关于Java:如何对文件使用 PKCS#1 编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40352835/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com