Skip to content

Commit 3a53da9

Browse files
committed
Refactor MPInteger
1 parent 5fbd878 commit 3a53da9

2 files changed

Lines changed: 45 additions & 27 deletions

File tree

core/src/main/java/org/bouncycastle/util/BigIntegers.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.bouncycastle.util;
22

3+
import java.io.IOException;
4+
import java.io.OutputStream;
35
import java.math.BigInteger;
46
import java.security.SecureRandom;
57
import java.util.Map;
@@ -393,6 +395,16 @@ public static BigInteger createRandomPrime(int bitLength, int certainty, SecureR
393395
return rv;
394396
}
395397

398+
public static void writeUnsignedByteArray(OutputStream out, BigInteger n) throws IOException
399+
{
400+
byte[] b = n.toByteArray();
401+
402+
int off = b[0] == 0 ? 1 : 0;
403+
int len = b.length - off;
404+
405+
out.write(b, off, len);
406+
}
407+
396408
private static byte[] createRandom(int bitLength, SecureRandom random)
397409
throws IllegalArgumentException
398410
{

pg/src/main/java/org/bouncycastle/bcpg/MPInteger.java

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,30 @@
33
import java.io.IOException;
44
import java.math.BigInteger;
55

6+
import org.bouncycastle.util.BigIntegers;
7+
68
/**
79
* a multiple precision integer
810
*/
911
public class MPInteger
1012
extends BCPGObject
1113
{
12-
BigInteger value = null;
13-
14-
public MPInteger(
15-
BCPGInputStream in)
16-
throws IOException
14+
private final BigInteger value;
15+
16+
public MPInteger(BCPGInputStream in) throws IOException
1717
{
18-
int length = StreamUtil.read2OctetLength(in);
19-
byte[] bytes = new byte[(length + 7) / 8];
20-
21-
in.readFully(bytes);
22-
23-
value = new BigInteger(1, bytes);
18+
/*
19+
* TODO RFC 9580 3.2. When parsing an MPI in a version 6 Key, Signature, or Public Key Encrypted
20+
* Session Key (PKESK) packet, the implementation MUST check that the encoded length matches the
21+
* length starting from the most significant non-zero bit; if it doesn't match, reject the packet as
22+
* malformed.
23+
*/
24+
boolean validateLength = false;
25+
26+
this.value = readMPI(in, validateLength);
2427
}
25-
26-
public MPInteger(
27-
BigInteger value)
28+
29+
public MPInteger(BigInteger value)
2830
{
2931
if (value == null || value.signum() < 0)
3032
{
@@ -33,27 +35,31 @@ public MPInteger(
3335

3436
this.value = value;
3537
}
36-
38+
3739
public BigInteger getValue()
3840
{
3941
return value;
4042
}
41-
42-
public void encode(
43-
BCPGOutputStream out)
44-
throws IOException
43+
44+
public void encode(BCPGOutputStream out) throws IOException
4545
{
4646
StreamUtil.write2OctetLength(out, value.bitLength());
47+
BigIntegers.writeUnsignedByteArray(out, value);
48+
}
4749

48-
byte[] bytes = value.toByteArray();
49-
50-
if (bytes[0] == 0)
51-
{
52-
out.write(bytes, 1, bytes.length - 1);
53-
}
54-
else
50+
private static BigInteger readMPI(BCPGInputStream in, boolean validateLength) throws IOException
51+
{
52+
int bitLength = StreamUtil.read2OctetLength(in);
53+
int byteLength = (bitLength + 7) / 8;
54+
byte[] bytes = new byte[byteLength];
55+
in.readFully(bytes);
56+
BigInteger n = new BigInteger(1, bytes);
57+
58+
if (validateLength && n.bitLength() != bitLength)
5559
{
56-
out.write(bytes, 0, bytes.length);
60+
throw new IOException("malformed MPI");
5761
}
62+
63+
return n;
5864
}
5965
}

0 commit comments

Comments
 (0)