c6590a8255cf2e4d9fd2e3191fee357e04b6948e
[org.ibex.crypto.git] / src / org / ibex / crypto / RSA.java
1 package org.ibex.crypto;
2 import java.math.BigInteger;
3 import java.util.*;
4
5 public class RSA {
6     private final BigInteger pq;
7     private final BigInteger e;
8     private final boolean reverse;
9     
10     public RSA(BigInteger pq, BigInteger e, boolean reverse) {
11         this.pq = pq;
12         this.e = e;
13         this.reverse = reverse;
14     }
15     
16     public int getInputBlockSize() { return (pq.bitLength()+7) / 8 - (reverse ? 0 : 1); }
17     public int getOutputBlockSize() { return (pq.bitLength()+7) / 8 - (reverse ? 1 : 0); }
18     
19     // FEATURE: Check that in.length is within the expected range
20     public byte[] process(byte[] in) {
21         // output block is the same size as the modulus (rounded up)
22         int outSize = getOutputBlockSize();
23         BigInteger t = new BigInteger(1,in);
24         BigInteger c = t.modPow(e,pq);
25         byte[] cbytes = c.toByteArray();
26         if(cbytes.length > outSize + 1) throw new RuntimeException("should never happen");
27         if(reverse ? cbytes[0] == 0 : cbytes.length > outSize) {
28             if(cbytes[0] != 0) throw new RuntimeException("should never happen");
29             byte[] buf = new byte[cbytes.length-1];
30             System.arraycopy(cbytes,1,buf,0,buf.length);
31             return buf;
32         } else if(!reverse && cbytes.length < outSize) {
33             // output needs to be exactly outSize in length
34             byte[] buf = new byte[outSize];
35             System.arraycopy(cbytes,0,buf,outSize-cbytes.length,cbytes.length);
36             return buf;
37         } else {
38             return cbytes;
39         }
40     }
41
42     public static class PublicKey {
43         public final BigInteger modulus;
44         public final BigInteger exponent;
45         
46         public PublicKey(Object o) {
47             Vector seq = (Vector) o;
48             modulus = (BigInteger) seq.elementAt(0);
49             exponent = (BigInteger) seq.elementAt(1);
50         }
51     }
52     
53     public static class PrivateKey {
54         public final int version;
55         public final BigInteger modulus;
56         public final BigInteger publicExponent;
57         public final BigInteger privateExponent;
58         public final BigInteger prime1;
59         public final BigInteger prime2;
60         public final BigInteger exponent1;
61         public final BigInteger exponent2;
62         public final BigInteger coefficient;
63         
64         public PrivateKey(Object o) throws DER.Exception {
65             Vector seq = (Vector) o;
66             version = ((Number)seq.elementAt(0)).intValue();
67             if(version != 0) throw new DER.Exception("Only private key version 0 is supported");
68             modulus = (BigInteger) seq.elementAt(1);
69             publicExponent = (BigInteger) seq.elementAt(2);
70             privateExponent = (BigInteger) seq.elementAt(3);
71             prime1 = (BigInteger) seq.elementAt(4);
72             prime2 = (BigInteger) seq.elementAt(5);
73             exponent1 = (BigInteger) seq.elementAt(6);
74             exponent2 = (BigInteger) seq.elementAt(7);
75             coefficient = (BigInteger) seq.elementAt(8);
76         }
77     }
78 }