001: /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
002: /*
003: Copyright (c) 2002-2008 ymnk, JCraft,Inc. All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions are met:
007:
008: 1. Redistributions of source code must retain the above copyright notice,
009: this list of conditions and the following disclaimer.
010:
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in
013: the documentation and/or other materials provided with the distribution.
014:
015: 3. The names of the authors may not be used to endorse or promote products
016: derived from this software without specific prior written permission.
017:
018: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
019: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
020: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
021: INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
022: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
024: OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
027: EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jcraft.jsch;
031:
032: import java.io.*;
033:
034: class IdentityFile implements Identity {
035: String identity;
036: byte[] key;
037: byte[] iv;
038: private JSch jsch;
039: private HASH hash;
040: private byte[] encoded_data;
041:
042: private Cipher cipher;
043:
044: // DSA
045: private byte[] P_array;
046: private byte[] Q_array;
047: private byte[] G_array;
048: private byte[] pub_array;
049: private byte[] prv_array;
050:
051: // RSA
052: private byte[] n_array; // modulus
053: private byte[] e_array; // public exponent
054: private byte[] d_array; // private exponent
055:
056: // private String algname="ssh-dss";
057: private String algname = "ssh-rsa";
058:
059: private static final int ERROR = 0;
060: private static final int RSA = 1;
061: private static final int DSS = 2;
062: private static final int UNKNOWN = 3;
063:
064: private static final int OPENSSH = 0;
065: private static final int FSECURE = 1;
066: private static final int PUTTY = 2;
067:
068: private int type = ERROR;
069: private int keytype = OPENSSH;
070:
071: private byte[] publickeyblob = null;
072:
073: private boolean encrypted = true;
074:
075: static IdentityFile newInstance(String prvfile, String pubfile,
076: JSch jsch) throws JSchException {
077: byte[] prvkey = null;
078: byte[] pubkey = null;
079:
080: File file = null;
081: FileInputStream fis = null;
082: try {
083: file = new File(prvfile);
084: fis = new FileInputStream(prvfile);
085: prvkey = new byte[(int) (file.length())];
086: int len = 0;
087: while (true) {
088: int i = fis.read(prvkey, len, prvkey.length - len);
089: if (i <= 0)
090: break;
091: len += i;
092: }
093: fis.close();
094: } catch (Exception e) {
095: try {
096: if (fis != null)
097: fis.close();
098: } catch (Exception ee) {
099: }
100: if (e instanceof Throwable)
101: throw new JSchException(e.toString(), (Throwable) e);
102: throw new JSchException(e.toString());
103: }
104:
105: String _pubfile = pubfile;
106: if (pubfile == null) {
107: _pubfile = prvfile + ".pub";
108: }
109:
110: try {
111: file = new File(_pubfile);
112: fis = new FileInputStream(_pubfile);
113: pubkey = new byte[(int) (file.length())];
114: int len = 0;
115: while (true) {
116: int i = fis.read(pubkey, len, pubkey.length - len);
117: if (i <= 0)
118: break;
119: len += i;
120: }
121: fis.close();
122: } catch (Exception e) {
123: try {
124: if (fis != null)
125: fis.close();
126: } catch (Exception ee) {
127: }
128: if (pubfile != null) {
129: // The pubfile is explicitry given, but not accessible.
130: if (e instanceof Throwable)
131: throw new JSchException(e.toString(), (Throwable) e);
132: throw new JSchException(e.toString());
133: }
134: }
135: return newInstance(prvfile, prvkey, pubkey, jsch);
136: }
137:
138: static IdentityFile newInstance(String name, byte[] prvkey,
139: byte[] pubkey, JSch jsch) throws JSchException {
140: try {
141: return new IdentityFile(name, prvkey, pubkey, jsch);
142: } finally {
143: Util.bzero(prvkey);
144: }
145: }
146:
147: private IdentityFile(String name, byte[] prvkey, byte[] pubkey,
148: JSch jsch) throws JSchException {
149: this .identity = name;
150: this .jsch = jsch;
151: try {
152: Class c;
153: c = Class.forName((String) jsch.getConfig("3des-cbc"));
154: cipher = (Cipher) (c.newInstance());
155: key = new byte[cipher.getBlockSize()]; // 24
156: iv = new byte[cipher.getIVSize()]; // 8
157: c = Class.forName((String) jsch.getConfig("md5"));
158: hash = (HASH) (c.newInstance());
159: hash.init();
160:
161: byte[] buf = prvkey;
162: int len = buf.length;
163:
164: int i = 0;
165: while (i < len) {
166: if (buf[i] == 'B' && buf[i + 1] == 'E'
167: && buf[i + 2] == 'G' && buf[i + 3] == 'I') {
168: i += 6;
169: if (buf[i] == 'D' && buf[i + 1] == 'S'
170: && buf[i + 2] == 'A') {
171: type = DSS;
172: } else if (buf[i] == 'R' && buf[i + 1] == 'S'
173: && buf[i + 2] == 'A') {
174: type = RSA;
175: } else if (buf[i] == 'S' && buf[i + 1] == 'S'
176: && buf[i + 2] == 'H') { // FSecure
177: type = UNKNOWN;
178: keytype = FSECURE;
179: } else {
180: //System.err.println("invalid format: "+identity);
181: throw new JSchException("invalid privatekey: "
182: + identity);
183: }
184: i += 3;
185: continue;
186: }
187: if (buf[i] == 'C' && buf[i + 1] == 'B'
188: && buf[i + 2] == 'C' && buf[i + 3] == ',') {
189: i += 4;
190: for (int ii = 0; ii < iv.length; ii++) {
191: iv[ii] = (byte) (((a2b(buf[i++]) << 4) & 0xf0) + (a2b(buf[i++]) & 0xf));
192: }
193: continue;
194: }
195: if (buf[i] == 0x0d && i + 1 < buf.length
196: && buf[i + 1] == 0x0a) {
197: i++;
198: continue;
199: }
200: if (buf[i] == 0x0a && i + 1 < buf.length) {
201: if (buf[i + 1] == 0x0a) {
202: i += 2;
203: break;
204: }
205: if (buf[i + 1] == 0x0d && i + 2 < buf.length
206: && buf[i + 2] == 0x0a) {
207: i += 3;
208: break;
209: }
210: boolean inheader = false;
211: for (int j = i + 1; j < buf.length; j++) {
212: if (buf[j] == 0x0a)
213: break;
214: //if(buf[j]==0x0d) break;
215: if (buf[j] == ':') {
216: inheader = true;
217: break;
218: }
219: }
220: if (!inheader) {
221: i++;
222: encrypted = false; // no passphrase
223: break;
224: }
225: }
226: i++;
227: }
228:
229: if (type == ERROR) {
230: throw new JSchException("invalid privatekey: "
231: + identity);
232: }
233:
234: int start = i;
235: while (i < len) {
236: if (buf[i] == 0x0a) {
237: boolean xd = (buf[i - 1] == 0x0d);
238: System.arraycopy(buf, i + 1, buf, i - (xd ? 1 : 0),
239: len - i - 1 - (xd ? 1 : 0));
240: if (xd)
241: len--;
242: len--;
243: continue;
244: }
245: if (buf[i] == '-') {
246: break;
247: }
248: i++;
249: }
250: encoded_data = Util.fromBase64(buf, start, i - start);
251:
252: if (encoded_data.length > 4
253: && // FSecure
254: encoded_data[0] == (byte) 0x3f
255: && encoded_data[1] == (byte) 0x6f
256: && encoded_data[2] == (byte) 0xf9
257: && encoded_data[3] == (byte) 0xeb) {
258:
259: Buffer _buf = new Buffer(encoded_data);
260: _buf.getInt(); // 0x3f6ff9be
261: _buf.getInt();
262: byte[] _type = _buf.getString();
263: //System.err.println("type: "+new String(_type));
264: byte[] _cipher = _buf.getString();
265: String cipher = new String(_cipher);
266: //System.err.println("cipher: "+cipher);
267: if (cipher.equals("3des-cbc")) {
268: _buf.getInt();
269: byte[] foo = new byte[encoded_data.length
270: - _buf.getOffSet()];
271: _buf.getByte(foo);
272: encoded_data = foo;
273: encrypted = true;
274: throw new JSchException(
275: "unknown privatekey format: " + identity);
276: } else if (cipher.equals("none")) {
277: _buf.getInt();
278: //_buf.getInt();
279:
280: encrypted = false;
281:
282: byte[] foo = new byte[encoded_data.length
283: - _buf.getOffSet()];
284: _buf.getByte(foo);
285: encoded_data = foo;
286: }
287:
288: }
289:
290: if (pubkey == null) {
291: return;
292: }
293:
294: buf = pubkey;
295: len = buf.length;
296:
297: if (buf.length > 4
298: && // FSecure's public key
299: buf[0] == '-' && buf[1] == '-' && buf[2] == '-'
300: && buf[3] == '-') {
301: i = 0;
302: do {
303: i++;
304: } while (len > i && buf[i] != 0x0a);
305: if (len <= i)
306: return;
307: while (i < len) {
308: if (buf[i] == 0x0a) {
309: boolean inheader = false;
310: for (int j = i + 1; j < len; j++) {
311: if (buf[j] == 0x0a)
312: break;
313: if (buf[j] == ':') {
314: inheader = true;
315: break;
316: }
317: }
318: if (!inheader) {
319: i++;
320: break;
321: }
322: }
323: i++;
324: }
325: if (len <= i)
326: return;
327:
328: start = i;
329: while (i < len) {
330: if (buf[i] == 0x0a) {
331: System.arraycopy(buf, i + 1, buf, i, len - i
332: - 1);
333: len--;
334: continue;
335: }
336: if (buf[i] == '-') {
337: break;
338: }
339: i++;
340: }
341: publickeyblob = Util.fromBase64(buf, start, i - start);
342:
343: if (type == UNKNOWN && publickeyblob.length > 8) {
344: if (publickeyblob[8] == 'd') {
345: type = DSS;
346: } else if (publickeyblob[8] == 'r') {
347: type = RSA;
348: }
349: }
350: } else {
351: if (buf[0] != 's' || buf[1] != 's' || buf[2] != 'h'
352: || buf[3] != '-')
353: return;
354: i = 0;
355: while (i < len) {
356: if (buf[i] == ' ')
357: break;
358: i++;
359: }
360: i++;
361: if (i >= len)
362: return;
363: start = i;
364: while (i < len) {
365: if (buf[i] == ' ' || buf[i] == '\n')
366: break;
367: i++;
368: }
369: publickeyblob = Util.fromBase64(buf, start, i - start);
370: if (publickeyblob.length < 4 + 7) { // It must start with "ssh-XXX".
371: if (JSch.getLogger().isEnabled(Logger.WARN)) {
372: JSch.getLogger().log(Logger.WARN,
373: "failed to parse the public key");
374: }
375: publickeyblob = null;
376: }
377: }
378: } catch (Exception e) {
379: //System.err.println("IdentityFile: "+e);
380: if (e instanceof JSchException)
381: throw (JSchException) e;
382: if (e instanceof Throwable)
383: throw new JSchException(e.toString(), (Throwable) e);
384: throw new JSchException(e.toString());
385: }
386: }
387:
388: public String getAlgName() {
389: if (type == RSA)
390: return "ssh-rsa";
391: return "ssh-dss";
392: }
393:
394: public boolean setPassphrase(byte[] _passphrase)
395: throws JSchException {
396: /*
397: hash is MD5
398: h(0) <- hash(passphrase, iv);
399: h(n) <- hash(h(n-1), passphrase, iv);
400: key <- (h(0),...,h(n))[0,..,key.length];
401: */
402: try {
403: if (encrypted) {
404: if (_passphrase == null)
405: return false;
406: byte[] passphrase = _passphrase;
407: int hsize = hash.getBlockSize();
408: byte[] hn = new byte[key.length / hsize * hsize
409: + (key.length % hsize == 0 ? 0 : hsize)];
410: byte[] tmp = null;
411: if (keytype == OPENSSH) {
412: for (int index = 0; index + hsize <= hn.length;) {
413: if (tmp != null) {
414: hash.update(tmp, 0, tmp.length);
415: }
416: hash.update(passphrase, 0, passphrase.length);
417: hash.update(iv, 0, iv.length);
418: tmp = hash.digest();
419: System.arraycopy(tmp, 0, hn, index, tmp.length);
420: index += tmp.length;
421: }
422: System.arraycopy(hn, 0, key, 0, key.length);
423: } else if (keytype == FSECURE) {
424: for (int index = 0; index + hsize <= hn.length;) {
425: if (tmp != null) {
426: hash.update(tmp, 0, tmp.length);
427: }
428: hash.update(passphrase, 0, passphrase.length);
429: tmp = hash.digest();
430: System.arraycopy(tmp, 0, hn, index, tmp.length);
431: index += tmp.length;
432: }
433: System.arraycopy(hn, 0, key, 0, key.length);
434: }
435: Util.bzero(passphrase);
436: }
437: if (decrypt()) {
438: encrypted = false;
439: return true;
440: }
441: P_array = Q_array = G_array = pub_array = prv_array = null;
442: return false;
443: } catch (Exception e) {
444: if (e instanceof JSchException)
445: throw (JSchException) e;
446: if (e instanceof Throwable)
447: throw new JSchException(e.toString(), (Throwable) e);
448: throw new JSchException(e.toString());
449: }
450: }
451:
452: public byte[] getPublicKeyBlob() {
453: if (publickeyblob != null)
454: return publickeyblob;
455: if (type == RSA)
456: return getPublicKeyBlob_rsa();
457: return getPublicKeyBlob_dss();
458: }
459:
460: byte[] getPublicKeyBlob_rsa() {
461: if (e_array == null)
462: return null;
463: Buffer buf = new Buffer("ssh-rsa".length() + 4 + e_array.length
464: + 4 + n_array.length + 4);
465: buf.putString("ssh-rsa".getBytes());
466: buf.putString(e_array);
467: buf.putString(n_array);
468: return buf.buffer;
469: }
470:
471: byte[] getPublicKeyBlob_dss() {
472: if (P_array == null)
473: return null;
474: Buffer buf = new Buffer("ssh-dss".length() + 4 + P_array.length
475: + 4 + Q_array.length + 4 + G_array.length + 4
476: + pub_array.length + 4);
477: buf.putString("ssh-dss".getBytes());
478: buf.putString(P_array);
479: buf.putString(Q_array);
480: buf.putString(G_array);
481: buf.putString(pub_array);
482: return buf.buffer;
483: }
484:
485: public byte[] getSignature(byte[] data) {
486: if (type == RSA)
487: return getSignature_rsa(data);
488: return getSignature_dss(data);
489: }
490:
491: byte[] getSignature_rsa(byte[] data) {
492: try {
493: Class c = Class.forName((String) jsch
494: .getConfig("signature.rsa"));
495: SignatureRSA rsa = (SignatureRSA) (c.newInstance());
496:
497: rsa.init();
498: rsa.setPrvKey(d_array, n_array);
499:
500: rsa.update(data);
501: byte[] sig = rsa.sign();
502: Buffer buf = new Buffer("ssh-rsa".length() + 4 + sig.length
503: + 4);
504: buf.putString("ssh-rsa".getBytes());
505: buf.putString(sig);
506: return buf.buffer;
507: } catch (Exception e) {
508: }
509: return null;
510: }
511:
512: byte[] getSignature_dss(byte[] data) {
513: /*
514: byte[] foo;
515: int i;
516: System.err.print("P ");
517: foo=P_array;
518: for(i=0; i<foo.length; i++){
519: System.err.print(Integer.toHexString(foo[i]&0xff)+":");
520: }
521: System.err.println("");
522: System.err.print("Q ");
523: foo=Q_array;
524: for(i=0; i<foo.length; i++){
525: System.err.print(Integer.toHexString(foo[i]&0xff)+":");
526: }
527: System.err.println("");
528: System.err.print("G ");
529: foo=G_array;
530: for(i=0; i<foo.length; i++){
531: System.err.print(Integer.toHexString(foo[i]&0xff)+":");
532: }
533: System.err.println("");
534: */
535:
536: try {
537: Class c = Class.forName((String) jsch
538: .getConfig("signature.dss"));
539: SignatureDSA dsa = (SignatureDSA) (c.newInstance());
540: dsa.init();
541: dsa.setPrvKey(prv_array, P_array, Q_array, G_array);
542:
543: dsa.update(data);
544: byte[] sig = dsa.sign();
545: Buffer buf = new Buffer("ssh-dss".length() + 4 + sig.length
546: + 4);
547: buf.putString("ssh-dss".getBytes());
548: buf.putString(sig);
549: return buf.buffer;
550: } catch (Exception e) {
551: //System.err.println("e "+e);
552: }
553: return null;
554: }
555:
556: public boolean decrypt() {
557: if (type == RSA)
558: return decrypt_rsa();
559: return decrypt_dss();
560: }
561:
562: boolean decrypt_rsa() {
563: byte[] p_array;
564: byte[] q_array;
565: byte[] dmp1_array;
566: byte[] dmq1_array;
567: byte[] iqmp_array;
568:
569: try {
570: byte[] plain;
571: if (encrypted) {
572: if (keytype == OPENSSH) {
573: cipher.init(Cipher.DECRYPT_MODE, key, iv);
574: plain = new byte[encoded_data.length];
575: cipher.update(encoded_data, 0, encoded_data.length,
576: plain, 0);
577: } else if (keytype == FSECURE) {
578: for (int i = 0; i < iv.length; i++)
579: iv[i] = 0;
580: cipher.init(Cipher.DECRYPT_MODE, key, iv);
581: plain = new byte[encoded_data.length];
582: cipher.update(encoded_data, 0, encoded_data.length,
583: plain, 0);
584: } else {
585: return false;
586: }
587: } else {
588: if (n_array != null)
589: return true;
590: plain = encoded_data;
591: }
592:
593: if (keytype == FSECURE) { // FSecure
594: Buffer buf = new Buffer(plain);
595: int foo = buf.getInt();
596: if (plain.length != foo + 4) {
597: return false;
598: }
599: e_array = buf.getMPIntBits();
600: d_array = buf.getMPIntBits();
601: n_array = buf.getMPIntBits();
602: byte[] u_array = buf.getMPIntBits();
603: p_array = buf.getMPIntBits();
604: q_array = buf.getMPIntBits();
605: return true;
606: }
607:
608: int index = 0;
609: int length = 0;
610:
611: if (plain[index] != 0x30)
612: return false;
613: index++; // SEQUENCE
614: length = plain[index++] & 0xff;
615: if ((length & 0x80) != 0) {
616: int foo = length & 0x7f;
617: length = 0;
618: while (foo-- > 0) {
619: length = (length << 8) + (plain[index++] & 0xff);
620: }
621: }
622:
623: if (plain[index] != 0x02)
624: return false;
625: index++; // INTEGER
626: length = plain[index++] & 0xff;
627: if ((length & 0x80) != 0) {
628: int foo = length & 0x7f;
629: length = 0;
630: while (foo-- > 0) {
631: length = (length << 8) + (plain[index++] & 0xff);
632: }
633: }
634: index += length;
635:
636: //System.err.println("int: len="+length);
637: //System.err.print(Integer.toHexString(plain[index-1]&0xff)+":");
638: //System.err.println("");
639:
640: index++;
641: length = plain[index++] & 0xff;
642: if ((length & 0x80) != 0) {
643: int foo = length & 0x7f;
644: length = 0;
645: while (foo-- > 0) {
646: length = (length << 8) + (plain[index++] & 0xff);
647: }
648: }
649: n_array = new byte[length];
650: System.arraycopy(plain, index, n_array, 0, length);
651: index += length;
652: /*
653: System.err.println("int: N len="+length);
654: for(int i=0; i<n_array.length; i++){
655: System.err.print(Integer.toHexString(n_array[i]&0xff)+":");
656: }
657: System.err.println("");
658: */
659: index++;
660: length = plain[index++] & 0xff;
661: if ((length & 0x80) != 0) {
662: int foo = length & 0x7f;
663: length = 0;
664: while (foo-- > 0) {
665: length = (length << 8) + (plain[index++] & 0xff);
666: }
667: }
668: e_array = new byte[length];
669: System.arraycopy(plain, index, e_array, 0, length);
670: index += length;
671: /*
672: System.err.println("int: E len="+length);
673: for(int i=0; i<e_array.length; i++){
674: System.err.print(Integer.toHexString(e_array[i]&0xff)+":");
675: }
676: System.err.println("");
677: */
678: index++;
679: length = plain[index++] & 0xff;
680: if ((length & 0x80) != 0) {
681: int foo = length & 0x7f;
682: length = 0;
683: while (foo-- > 0) {
684: length = (length << 8) + (plain[index++] & 0xff);
685: }
686: }
687: d_array = new byte[length];
688: System.arraycopy(plain, index, d_array, 0, length);
689: index += length;
690: /*
691: System.err.println("int: D len="+length);
692: for(int i=0; i<d_array.length; i++){
693: System.err.print(Integer.toHexString(d_array[i]&0xff)+":");
694: }
695: System.err.println("");
696: */
697:
698: index++;
699: length = plain[index++] & 0xff;
700: if ((length & 0x80) != 0) {
701: int foo = length & 0x7f;
702: length = 0;
703: while (foo-- > 0) {
704: length = (length << 8) + (plain[index++] & 0xff);
705: }
706: }
707: p_array = new byte[length];
708: System.arraycopy(plain, index, p_array, 0, length);
709: index += length;
710: /*
711: System.err.println("int: P len="+length);
712: for(int i=0; i<p_array.length; i++){
713: System.err.print(Integer.toHexString(p_array[i]&0xff)+":");
714: }
715: System.err.println("");
716: */
717: index++;
718: length = plain[index++] & 0xff;
719: if ((length & 0x80) != 0) {
720: int foo = length & 0x7f;
721: length = 0;
722: while (foo-- > 0) {
723: length = (length << 8) + (plain[index++] & 0xff);
724: }
725: }
726: q_array = new byte[length];
727: System.arraycopy(plain, index, q_array, 0, length);
728: index += length;
729: /*
730: System.err.println("int: q len="+length);
731: for(int i=0; i<q_array.length; i++){
732: System.err.print(Integer.toHexString(q_array[i]&0xff)+":");
733: }
734: System.err.println("");
735: */
736: index++;
737: length = plain[index++] & 0xff;
738: if ((length & 0x80) != 0) {
739: int foo = length & 0x7f;
740: length = 0;
741: while (foo-- > 0) {
742: length = (length << 8) + (plain[index++] & 0xff);
743: }
744: }
745: dmp1_array = new byte[length];
746: System.arraycopy(plain, index, dmp1_array, 0, length);
747: index += length;
748: /*
749: System.err.println("int: dmp1 len="+length);
750: for(int i=0; i<dmp1_array.length; i++){
751: System.err.print(Integer.toHexString(dmp1_array[i]&0xff)+":");
752: }
753: System.err.println("");
754: */
755: index++;
756: length = plain[index++] & 0xff;
757: if ((length & 0x80) != 0) {
758: int foo = length & 0x7f;
759: length = 0;
760: while (foo-- > 0) {
761: length = (length << 8) + (plain[index++] & 0xff);
762: }
763: }
764: dmq1_array = new byte[length];
765: System.arraycopy(plain, index, dmq1_array, 0, length);
766: index += length;
767: /*
768: System.err.println("int: dmq1 len="+length);
769: for(int i=0; i<dmq1_array.length; i++){
770: System.err.print(Integer.toHexString(dmq1_array[i]&0xff)+":");
771: }
772: System.err.println("");
773: */
774: index++;
775: length = plain[index++] & 0xff;
776: if ((length & 0x80) != 0) {
777: int foo = length & 0x7f;
778: length = 0;
779: while (foo-- > 0) {
780: length = (length << 8) + (plain[index++] & 0xff);
781: }
782: }
783: iqmp_array = new byte[length];
784: System.arraycopy(plain, index, iqmp_array, 0, length);
785: index += length;
786: /*
787: System.err.println("int: iqmp len="+length);
788: for(int i=0; i<iqmp_array.length; i++){
789: System.err.print(Integer.toHexString(iqmp_array[i]&0xff)+":");
790: }
791: System.err.println("");
792: */
793: } catch (Exception e) {
794: //System.err.println(e);
795: return false;
796: }
797: return true;
798: }
799:
800: boolean decrypt_dss() {
801: try {
802: byte[] plain;
803: if (encrypted) {
804: if (keytype == OPENSSH) {
805: cipher.init(Cipher.DECRYPT_MODE, key, iv);
806: plain = new byte[encoded_data.length];
807: cipher.update(encoded_data, 0, encoded_data.length,
808: plain, 0);
809: /*
810: for(int i=0; i<plain.length; i++){
811: System.err.print(Integer.toHexString(plain[i]&0xff)+":");
812: }
813: System.err.println("");
814: */
815: } else if (keytype == FSECURE) {
816: for (int i = 0; i < iv.length; i++)
817: iv[i] = 0;
818: cipher.init(Cipher.DECRYPT_MODE, key, iv);
819: plain = new byte[encoded_data.length];
820: cipher.update(encoded_data, 0, encoded_data.length,
821: plain, 0);
822: } else {
823: return false;
824: }
825: } else {
826: if (P_array != null)
827: return true;
828: plain = encoded_data;
829: }
830:
831: if (keytype == FSECURE) { // FSecure
832: Buffer buf = new Buffer(plain);
833: int foo = buf.getInt();
834: if (plain.length != foo + 4) {
835: return false;
836: }
837: P_array = buf.getMPIntBits();
838: G_array = buf.getMPIntBits();
839: Q_array = buf.getMPIntBits();
840: pub_array = buf.getMPIntBits();
841: prv_array = buf.getMPIntBits();
842: return true;
843: }
844:
845: int index = 0;
846: int length = 0;
847: if (plain[index] != 0x30)
848: return false;
849: index++; // SEQUENCE
850: length = plain[index++] & 0xff;
851: if ((length & 0x80) != 0) {
852: int foo = length & 0x7f;
853: length = 0;
854: while (foo-- > 0) {
855: length = (length << 8) + (plain[index++] & 0xff);
856: }
857: }
858: if (plain[index] != 0x02)
859: return false;
860: index++; // INTEGER
861: length = plain[index++] & 0xff;
862: if ((length & 0x80) != 0) {
863: int foo = length & 0x7f;
864: length = 0;
865: while (foo-- > 0) {
866: length = (length << 8) + (plain[index++] & 0xff);
867: }
868: }
869: index += length;
870:
871: index++;
872: length = plain[index++] & 0xff;
873: if ((length & 0x80) != 0) {
874: int foo = length & 0x7f;
875: length = 0;
876: while (foo-- > 0) {
877: length = (length << 8) + (plain[index++] & 0xff);
878: }
879: }
880: P_array = new byte[length];
881: System.arraycopy(plain, index, P_array, 0, length);
882: index += length;
883:
884: index++;
885: length = plain[index++] & 0xff;
886: if ((length & 0x80) != 0) {
887: int foo = length & 0x7f;
888: length = 0;
889: while (foo-- > 0) {
890: length = (length << 8) + (plain[index++] & 0xff);
891: }
892: }
893: Q_array = new byte[length];
894: System.arraycopy(plain, index, Q_array, 0, length);
895: index += length;
896:
897: index++;
898: length = plain[index++] & 0xff;
899: if ((length & 0x80) != 0) {
900: int foo = length & 0x7f;
901: length = 0;
902: while (foo-- > 0) {
903: length = (length << 8) + (plain[index++] & 0xff);
904: }
905: }
906: G_array = new byte[length];
907: System.arraycopy(plain, index, G_array, 0, length);
908: index += length;
909:
910: index++;
911: length = plain[index++] & 0xff;
912: if ((length & 0x80) != 0) {
913: int foo = length & 0x7f;
914: length = 0;
915: while (foo-- > 0) {
916: length = (length << 8) + (plain[index++] & 0xff);
917: }
918: }
919: pub_array = new byte[length];
920: System.arraycopy(plain, index, pub_array, 0, length);
921: index += length;
922:
923: index++;
924: length = plain[index++] & 0xff;
925: if ((length & 0x80) != 0) {
926: int foo = length & 0x7f;
927: length = 0;
928: while (foo-- > 0) {
929: length = (length << 8) + (plain[index++] & 0xff);
930: }
931: }
932: prv_array = new byte[length];
933: System.arraycopy(plain, index, prv_array, 0, length);
934: index += length;
935: } catch (Exception e) {
936: //System.err.println(e);
937: //e.printStackTrace();
938: return false;
939: }
940: return true;
941: }
942:
943: public boolean isEncrypted() {
944: return encrypted;
945: }
946:
947: public String getName() {
948: return identity;
949: }
950:
951: private byte a2b(byte c) {
952: if ('0' <= c && c <= '9')
953: return (byte) (c - '0');
954: if ('a' <= c && c <= 'z')
955: return (byte) (c - 'a' + 10);
956: return (byte) (c - 'A' + 10);
957: }
958:
959: public boolean equals(Object o) {
960: if (!(o instanceof IdentityFile))
961: return super .equals(o);
962: IdentityFile foo = (IdentityFile) o;
963: return getName().equals(foo.getName());
964: }
965:
966: public void clear() {
967: Util.bzero(encoded_data);
968: Util.bzero(prv_array);
969: Util.bzero(d_array);
970: Util.bzero(key);
971: Util.bzero(iv);
972: }
973:
974: public void finalize() {
975: clear();
976: }
977: }
|