blob: d2935e09ce2939243bcf831353bcfbb654d8b473 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dumpkey;
18
19import java.io.FileInputStream;
20import java.math.BigInteger;
21import java.security.cert.CertificateFactory;
22import java.security.cert.Certificate;
23import java.security.KeyStore;
24import java.security.Key;
25import java.security.PublicKey;
26import java.security.interfaces.RSAPublicKey;
27import sun.misc.BASE64Encoder;
28
29/**
30 * Command line tool to extract RSA public keys from X.509 certificates
31 * and output source code with data initializers for the keys.
32 * @hide
33 */
34class DumpPublicKey {
35 /**
36 * @param key to perform sanity checks on
37 * @throws Exception if the key has the wrong size or public exponent
38 */
39 static void check(RSAPublicKey key) throws Exception {
40 BigInteger pubexp = key.getPublicExponent();
41 BigInteger modulus = key.getModulus();
42
43 if (!pubexp.equals(BigInteger.valueOf(3)))
44 throw new Exception("Public exponent should be 3 but is " +
45 pubexp.toString(10) + ".");
46
47 if (modulus.bitLength() != 2048)
48 throw new Exception("Modulus should be 2048 bits long but is " +
49 modulus.bitLength() + " bits.");
50 }
51
52 /**
53 * @param key to output
54 * @return a C initializer representing this public key.
55 */
56 static String print(RSAPublicKey key) throws Exception {
57 check(key);
58
59 BigInteger N = key.getModulus();
60
61 StringBuilder result = new StringBuilder();
62
63 int nwords = N.bitLength() / 32; // # of 32 bit integers in modulus
64
65 result.append("{");
66 result.append(nwords);
67
68 BigInteger B = BigInteger.valueOf(0x100000000L); // 2^32
69 BigInteger N0inv = B.subtract(N.modInverse(B)); // -1 / N[0] mod 2^32
70
71 result.append(",0x");
72 result.append(N0inv.toString(16));
73
74 BigInteger R = BigInteger.valueOf(2).pow(N.bitLength());
75 BigInteger RR = R.multiply(R).mod(N); // 2^4096 mod N
76
77 // Write out modulus as little endian array of integers.
78 result.append(",{");
79 for (int i = 0; i < nwords; ++i) {
Doug Zongker5e12d732010-01-29 10:47:38 -080080 long n = N.mod(B).longValue();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080081 result.append(n);
82
83 if (i != nwords - 1) {
84 result.append(",");
85 }
86
87 N = N.divide(B);
88 }
89 result.append("}");
90
91 // Write R^2 as little endian array of integers.
92 result.append(",{");
93 for (int i = 0; i < nwords; ++i) {
Doug Zongker5e12d732010-01-29 10:47:38 -080094 long rr = RR.mod(B).longValue();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095 result.append(rr);
96
97 if (i != nwords - 1) {
98 result.append(",");
99 }
100
101 RR = RR.divide(B);
102 }
103 result.append("}");
104
105 result.append("}");
106 return result.toString();
107 }
108
109 public static void main(String[] args) {
110 if (args.length < 1) {
111 System.err.println("Usage: DumpPublicKey certfile ... > source.c");
112 System.exit(1);
113 }
114 try {
115 for (int i = 0; i < args.length; i++) {
116 FileInputStream input = new FileInputStream(args[i]);
117 CertificateFactory cf = CertificateFactory.getInstance("X.509");
118 Certificate cert = cf.generateCertificate(input);
119 RSAPublicKey key = (RSAPublicKey) (cert.getPublicKey());
120 check(key);
121 System.out.print(print(key));
122 System.out.println(i < args.length - 1 ? "," : "");
123 }
124 } catch (Exception e) {
125 e.printStackTrace();
126 System.exit(1);
127 }
128 System.exit(0);
129 }
130}