summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java
blob: 92c2ed4d032a304ebeda2ebd3df455a1af51dd29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package org.bouncycastle.pqc.math.ntru.util;

import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.bouncycastle.pqc.math.ntru.euclid.IntEuclidean;
import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
import org.bouncycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
import org.bouncycastle.util.Integers;

public class Util
{
    private static volatile boolean IS_64_BITNESS_KNOWN;
    private static volatile boolean IS_64_BIT_JVM;

    /**
     * Calculates the inverse of n mod modulus
     */
    public static int invert(int n, int modulus)
    {
        n %= modulus;
        if (n < 0)
        {
            n += modulus;
        }
        return IntEuclidean.calculate(n, modulus).x;
    }

    /**
     * Calculates a^b mod modulus
     */
    public static int pow(int a, int b, int modulus)
    {
        int p = 1;
        for (int i = 0; i < b; i++)
        {
            p = (p * a) % modulus;
        }
        return p;
    }

    /**
     * Calculates a^b mod modulus
     */
    public static long pow(long a, int b, long modulus)
    {
        long p = 1;
        for (int i = 0; i < b; i++)
        {
            p = (p * a) % modulus;
        }
        return p;
    }

    /**
     * Generates a "sparse" or "dense" polynomial containing numOnes ints equal to 1,
     * numNegOnes int equal to -1, and the rest equal to 0.
     *
     * @param N
     * @param numOnes
     * @param numNegOnes
     * @param sparse     whether to create a {@link SparseTernaryPolynomial} or {@link DenseTernaryPolynomial}
     * @return a ternary polynomial
     */
    public static TernaryPolynomial generateRandomTernary(int N, int numOnes, int numNegOnes, boolean sparse, SecureRandom random)
    {
        if (sparse)
        {
            return SparseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
        }
        else
        {
            return DenseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
        }
    }

    /**
     * Generates an array containing numOnes ints equal to 1,
     * numNegOnes int equal to -1, and the rest equal to 0.
     *
     * @param N
     * @param numOnes
     * @param numNegOnes
     * @return an array of integers
     */
    public static int[] generateRandomTernary(int N, int numOnes, int numNegOnes, SecureRandom random)
    {
        Integer one = Integers.valueOf(1);
        Integer minusOne = Integers.valueOf(-1);
        Integer zero = Integers.valueOf(0);

        List list = new ArrayList();
        for (int i = 0; i < numOnes; i++)
        {
            list.add(one);
        }
        for (int i = 0; i < numNegOnes; i++)
        {
            list.add(minusOne);
        }
        while (list.size() < N)
        {
            list.add(zero);
        }

        Collections.shuffle(list, random);

        int[] arr = new int[N];
        for (int i = 0; i < N; i++)
        {
            arr[i] = ((Integer)list.get(i)).intValue();
        }
        return arr;
    }

    /**
     * Takes an educated guess as to whether 64 bits are supported by the JVM.
     *
     * @return <code>true</code> if 64-bit support detected, <code>false</code> otherwise
     */
    public static boolean is64BitJVM()
    {
        if (!IS_64_BITNESS_KNOWN)
        {
            String arch = System.getProperty("os.arch");
            String sunModel = System.getProperty("sun.arch.data.model");
            IS_64_BIT_JVM = "amd64".equals(arch) || "x86_64".equals(arch) || "ppc64".equals(arch) || "64".equals(sunModel);
            IS_64_BITNESS_KNOWN = true;
        }
        return IS_64_BIT_JVM;
    }

    /**
     * Reads a given number of bytes from an <code>InputStream</code>.
     * If there are not enough bytes in the stream, an <code>IOException</code>
     * is thrown.
     *
     * @param is
     * @param length
     * @return an array of length <code>length</code>
     * @throws IOException
     */
    public static byte[] readFullLength(InputStream is, int length)
        throws IOException
    {
        byte[] arr = new byte[length];
        if (is.read(arr) != arr.length)
        {
            throw new IOException("Not enough bytes to read.");
        }
        return arr;
    }
}