Source for gnu.java.security.key.rsa.RSAKeyPairRawCodec

   1: /* RSAKeyPairRawCodec.java --
   2:    Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is a part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2 of the License, or (at
   9: your option) any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: USA
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version.  */
  37: 
  38: 
  39: package gnu.java.security.key.rsa;
  40: 
  41: import gnu.java.security.Registry;
  42: import gnu.java.security.key.IKeyPairCodec;
  43: 
  44: import java.io.ByteArrayOutputStream;
  45: import java.math.BigInteger;
  46: import java.security.PrivateKey;
  47: import java.security.PublicKey;
  48: 
  49: /**
  50:  * An object that implements the {@link IKeyPairCodec} interface for the <i>Raw</i>
  51:  * format to use with RSA keypairs.
  52:  */
  53: public class RSAKeyPairRawCodec
  54:     implements IKeyPairCodec
  55: {
  56:   // implicit 0-arguments constructor
  57: 
  58:   public int getFormatID()
  59:   {
  60:     return RAW_FORMAT;
  61:   }
  62: 
  63:   /**
  64:    * Returns the encoded form of the designated RSA public key according to the
  65:    * <i>Raw</i> format supported by this library.
  66:    * <p>
  67:    * The <i>Raw</i> format for an RSA public key, in this implementation, is a
  68:    * byte sequence consisting of the following:
  69:    * <ol>
  70:    * <li>4-byte magic consisting of the value of the literal
  71:    * {@link Registry#MAGIC_RAW_RSA_PUBLIC_KEY},</li>
  72:    * <li>1-byte version consisting of the constant: 0x01,</li>
  73:    * <li>4-byte count of following bytes representing the RSA parameter
  74:    * <code>n</code> (the modulus) in internet order,</li>
  75:    * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
  76:    * the <code>toByteArray()</code> method on the RSA parameter <code>n</code>,
  77:    * </li>
  78:    * <li>4-byte count of following bytes representing the RSA parameter
  79:    * <code>e</code> (the public exponent) in internet order,</li>
  80:    * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
  81:    * the <code>toByteArray()</code> method on the RSA parameter <code>e</code>.
  82:    * </li>
  83:    * </ol>
  84:    *
  85:    * @param key the key to encode.
  86:    * @return the <i>Raw</i> format encoding of the designated key.
  87:    * @exception IllegalArgumentException if the designated key is not an RSA
  88:    *                                     one.
  89:    */
  90:   public byte[] encodePublicKey(PublicKey key)
  91:   {
  92:     if (! (key instanceof GnuRSAPublicKey))
  93:       throw new IllegalArgumentException("key");
  94: 
  95:     GnuRSAPublicKey rsaKey = (GnuRSAPublicKey) key;
  96:     ByteArrayOutputStream baos = new ByteArrayOutputStream();
  97:     // magic
  98:     baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0]);
  99:     baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]);
 100:     baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]);
 101:     baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3]);
 102:     // version
 103:     baos.write(0x01);
 104:     // n
 105:     byte[] buffer = rsaKey.getModulus().toByteArray();
 106:     int length = buffer.length;
 107:     baos.write(length >>> 24);
 108:     baos.write((length >>> 16) & 0xFF);
 109:     baos.write((length >>> 8) & 0xFF);
 110:     baos.write(length & 0xFF);
 111:     baos.write(buffer, 0, length);
 112:     // e
 113:     buffer = rsaKey.getPublicExponent().toByteArray();
 114:     length = buffer.length;
 115:     baos.write(length >>> 24);
 116:     baos.write((length >>> 16) & 0xFF);
 117:     baos.write((length >>> 8) & 0xFF);
 118:     baos.write(length & 0xFF);
 119:     baos.write(buffer, 0, length);
 120:     return baos.toByteArray();
 121:   }
 122: 
 123:   public PublicKey decodePublicKey(byte[] k)
 124:   {
 125:     // magic
 126:     if (k[0] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0]
 127:         || k[1] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]
 128:         || k[2] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]
 129:         || k[3] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3])
 130:       throw new IllegalArgumentException("magic");
 131: 
 132:     // version
 133:     if (k[4] != 0x01)
 134:       throw new IllegalArgumentException("version");
 135: 
 136:     int i = 5;
 137:     int l;
 138:     byte[] buffer;
 139:     // n
 140:     l =  k[i++]         << 24
 141:       | (k[i++] & 0xFF) << 16
 142:       | (k[i++] & 0xFF) << 8
 143:       | (k[i++] & 0xFF);
 144:     buffer = new byte[l];
 145:     System.arraycopy(k, i, buffer, 0, l);
 146:     i += l;
 147:     BigInteger n = new BigInteger(1, buffer);
 148:     // e
 149:     l =  k[i++]         << 24
 150:       | (k[i++] & 0xFF) << 16
 151:       | (k[i++] & 0xFF) << 8
 152:       | (k[i++] & 0xFF);
 153:     buffer = new byte[l];
 154:     System.arraycopy(k, i, buffer, 0, l);
 155:     i += l;
 156:     BigInteger e = new BigInteger(1, buffer);
 157:     return new GnuRSAPublicKey(n, e);
 158:   }
 159: 
 160:   /**
 161:    * Returns the encoded form of the designated RSA private key according to the
 162:    * <i>Raw</i> format supported by this library.
 163:    * <p>
 164:    * The <i>Raw</i> format for an RSA private key, in this implementation, is a
 165:    * byte sequence consisting of the following:
 166:    * <ol>
 167:    * <li>4-byte magic consisting of the value of the literal
 168:    * {@link Registry#MAGIC_RAW_RSA_PRIVATE_KEY},</li>
 169:    * <li>1-byte version consisting of the constant: 0x01,</li>
 170:    * <li>4-byte count of following bytes representing the RSA parameter
 171:    * <code>p</code> (the first prime factor of the modulus) in internet order,
 172:    * </li>
 173:    * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
 174:    * the <code>toByteArray()</code> method on the RSA parameter <code>p</code>,
 175:    * </li>
 176:    * <li>4-byte count of following bytes representing the RSA parameter
 177:    * <code>q</code> (the second prime factor of the modulus) in internet
 178:    * order,</li>
 179:    * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
 180:    * the <code>toByteArray()</code> method on the RSA parameter <code>q</code>,
 181:    * </li>
 182:    * <li>4-byte count of following bytes representing the RSA parameter
 183:    * <code>e</code> (the public exponent) in internet order,</li>
 184:    * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
 185:    * the <code>toByteArray()</code> method on the RSA parameter <code>e</code>,
 186:    * </li>
 187:    * <li>4-byte count of following bytes representing the RSA parameter
 188:    * <code>d</code> (the private exponent) in internet order,</li>
 189:    * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
 190:    * the <code>toByteArray()</code> method on the RSA parameter <code>d</code>,
 191:    * </li>
 192:    * </ol>
 193:    *
 194:    * @param key the key to encode.
 195:    * @return the <i>Raw</i> format encoding of the designated key.
 196:    */
 197:   public byte[] encodePrivateKey(PrivateKey key)
 198:   {
 199:     if (! (key instanceof GnuRSAPrivateKey))
 200:       throw new IllegalArgumentException("key");
 201: 
 202:     GnuRSAPrivateKey rsaKey = (GnuRSAPrivateKey) key;
 203:     ByteArrayOutputStream baos = new ByteArrayOutputStream();
 204:     // magic
 205:     baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0]);
 206:     baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]);
 207:     baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]);
 208:     baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[3]);
 209:     // version
 210:     baos.write(0x01);
 211:     // p
 212:     byte[] buffer = rsaKey.getPrimeP().toByteArray();
 213:     int length = buffer.length;
 214:     baos.write(length >>> 24);
 215:     baos.write((length >>> 16) & 0xFF);
 216:     baos.write((length >>> 8) & 0xFF);
 217:     baos.write(length & 0xFF);
 218:     baos.write(buffer, 0, length);
 219:     // q
 220:     buffer = rsaKey.getPrimeQ().toByteArray();
 221:     length = buffer.length;
 222:     baos.write(length >>> 24);
 223:     baos.write((length >>> 16) & 0xFF);
 224:     baos.write((length >>> 8) & 0xFF);
 225:     baos.write(length & 0xFF);
 226:     baos.write(buffer, 0, length);
 227:     // e
 228:     buffer = rsaKey.getPublicExponent().toByteArray();
 229:     length = buffer.length;
 230:     baos.write(length >>> 24);
 231:     baos.write((length >>> 16) & 0xFF);
 232:     baos.write((length >>> 8) & 0xFF);
 233:     baos.write(length & 0xFF);
 234:     baos.write(buffer, 0, length);
 235:     // d
 236:     buffer = rsaKey.getPrivateExponent().toByteArray();
 237:     length = buffer.length;
 238:     baos.write(length >>> 24);
 239:     baos.write((length >>> 16) & 0xFF);
 240:     baos.write((length >>> 8) & 0xFF);
 241:     baos.write(length & 0xFF);
 242:     baos.write(buffer, 0, length);
 243:     return baos.toByteArray();
 244:   }
 245: 
 246:   public PrivateKey decodePrivateKey(byte[] k)
 247:   {
 248:     // magic
 249:     if (k[0] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0]
 250:         || k[1] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]
 251:         || k[2] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]
 252:         || k[3] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[3])
 253:       throw new IllegalArgumentException("magic");
 254: 
 255:     // version
 256:     if (k[4] != 0x01)
 257:       throw new IllegalArgumentException("version");
 258: 
 259:     int i = 5;
 260:     int l;
 261:     byte[] buffer;
 262:     // p
 263:     l =  k[i++]         << 24
 264:       | (k[i++] & 0xFF) << 16
 265:       | (k[i++] & 0xFF) << 8
 266:       | (k[i++] & 0xFF);
 267:     buffer = new byte[l];
 268:     System.arraycopy(k, i, buffer, 0, l);
 269:     i += l;
 270:     BigInteger p = new BigInteger(1, buffer);
 271:     // q
 272:     l =  k[i++]         << 24
 273:       | (k[i++] & 0xFF) << 16
 274:       | (k[i++] & 0xFF) << 8
 275:       | (k[i++] & 0xFF);
 276:     buffer = new byte[l];
 277:     System.arraycopy(k, i, buffer, 0, l);
 278:     i += l;
 279:     BigInteger q = new BigInteger(1, buffer);
 280:     // e
 281:     l =  k[i++]         << 24
 282:       | (k[i++] & 0xFF) << 16
 283:       | (k[i++] & 0xFF) << 8
 284:       | (k[i++] & 0xFF);
 285:     buffer = new byte[l];
 286:     System.arraycopy(k, i, buffer, 0, l);
 287:     i += l;
 288:     BigInteger e = new BigInteger(1, buffer);
 289:     // d
 290:     l =  k[i++]         << 24
 291:       | (k[i++] & 0xFF) << 16
 292:       | (k[i++] & 0xFF) << 8
 293:       | (k[i++] & 0xFF);
 294:     buffer = new byte[l];
 295:     System.arraycopy(k, i, buffer, 0, l);
 296:     i += l;
 297:     BigInteger d = new BigInteger(1, buffer);
 298:     return new GnuRSAPrivateKey(p, q, e, d);
 299:   }
 300: }