PageRenderTime 694ms CodeModel.GetById 201ms app.highlight 254ms RepoModel.GetById 229ms app.codeStats 1ms

/SharpSSH/jsch/IdentityFile.cs

https://bitbucket.org/ajlennon/sharpssh
C# | 949 lines | 727 code | 67 blank | 155 comment | 112 complexity | 6d7707cc1784c309e06525d921b95b37 MD5 | raw file
  1using System;
  2using System.IO;
  3
  4namespace Tamir.SharpSsh.jsch
  5{
  6	/* -*-mode:java; c-basic-offset:2; -*- */
  7	/*
  8	Copyright (c) 2002,2003,2004 ymnk, JCraft,Inc. All rights reserved.
  9
 10	Redistribution and use in source and binary forms, with or without
 11	modification, are permitted provided that the following conditions are met:
 12
 13	  1. Redistributions of source code must retain the above copyright notice,
 14		 this list of conditions and the following disclaimer.
 15
 16	  2. Redistributions in binary form must reproduce the above copyright 
 17		 notice, this list of conditions and the following disclaimer in 
 18		 the documentation and/or other materials provided with the distribution.
 19
 20	  3. The names of the authors may not be used to endorse or promote products
 21		 derived from this software without specific prior written permission.
 22
 23	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 24	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 25	FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 26	INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 27	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 28	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 29	OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 30	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 31	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 32	EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 33	*/
 34
 35	internal class IdentityFile : Identity
 36	{
 37		String identity;
 38		byte[] key;
 39		byte[] iv;
 40		private JSch jsch;
 41		private HASH hash;
 42		private byte[] encoded_data;
 43
 44		private Cipher cipher;
 45
 46		// DSA
 47		private byte[] P_array;    
 48		private byte[] Q_array;    
 49		private byte[] G_array;    
 50		private byte[] pub_array;    
 51		private byte[] prv_array;    
 52		 
 53		// RSA
 54		private  byte[] n_array;   // modulus
 55		private  byte[] e_array;   // public exponent
 56		private  byte[] d_array;   // private exponent
 57
 58		private byte[] p_array;
 59		private byte[] q_array;
 60		private byte[] dmp1_array;
 61		private byte[] dmq1_array;
 62		private byte[] iqmp_array;
 63		 
 64		//  private String algname="ssh-dss";
 65		private String algname="ssh-rsa";
 66
 67		private const int ERROR=0;
 68		private const int RSA=1;
 69		private const int DSS=2;
 70		internal const int UNKNOWN=3;
 71
 72		private const int OPENSSH=0;
 73		private const int FSECURE=1;
 74		private const int PUTTY=2;
 75
 76		private int type=ERROR;
 77		private int keytype=OPENSSH;
 78
 79		private byte[] publickeyblob=null;
 80
 81		private bool encrypted=true;
 82
 83		internal IdentityFile(String identity, JSch jsch) 
 84		{
 85			this.identity=identity;
 86			this.jsch=jsch;
 87			try
 88			{
 89				Type c=Type.GetType(jsch.getConfig("3des-cbc"));
 90				cipher=(Cipher)Activator.CreateInstance(c);
 91				key=new byte[cipher.getBlockSize()];   // 24
 92				iv=new byte[cipher.getIVSize()];       // 8
 93				c=Type.GetType(jsch.getConfig("md5"));
 94				hash=(HASH)(Activator.CreateInstance(c));
 95				hash.init();
 96				FileInfo file=new FileInfo(identity);
 97				FileStream fis = File.OpenRead(identity);
 98				byte[] buf=new byte[(int)(file.Length)];
 99				int len=fis.Read(buf, 0, buf.Length);
100				fis.Close();
101
102				int i=0;
103				while(i<len)
104				{
105					if(buf[i]=='B'&& buf[i+1]=='E'&& buf[i+2]=='G'&& buf[i+3]=='I')
106					{
107						i+=6;	    
108						if(buf[i]=='D'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=DSS; }
109						else if(buf[i]=='R'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=RSA; }
110						else if(buf[i]=='S'&& buf[i+1]=='S'&& buf[i+2]=='H')
111						{ // FSecure
112							type=UNKNOWN;
113							keytype=FSECURE;
114						}
115						else
116						{
117							//System.out.println("invalid format: "+identity);
118							throw new JSchException("invaid privatekey: "+identity);
119						}
120						i+=3;
121						continue;
122					}
123					if(buf[i]=='C'&& buf[i+1]=='B'&& buf[i+2]=='C'&& buf[i+3]==',')
124					{
125						i+=4;
126						for(int ii=0; ii<iv.Length; ii++)
127						{
128							iv[ii]=(byte)(((a2b(buf[i++])<<4)&0xf0)+
129								(a2b(buf[i++])&0xf));
130						}
131						continue;
132					}
133					if(buf[i]==0x0d &&
134						i+1<buf.Length && buf[i+1]==0x0a)
135					{
136						i++;
137						continue;
138					}
139					if(buf[i]==0x0a && i+1<buf.Length)
140					{
141						if(buf[i+1]==0x0a){ i+=2; break; }
142						if(buf[i+1]==0x0d &&
143							i+2<buf.Length && buf[i+2]==0x0a)
144						{
145							i+=3; break;
146						}
147						bool inheader=false;
148						for(int j=i+1; j<buf.Length; j++)
149						{
150							if(buf[j]==0x0a) break;
151							//if(buf[j]==0x0d) break;
152							if(buf[j]==':'){inheader=true; break;}
153						}
154						if(!inheader)
155						{
156							i++; 
157							encrypted=false;    // no passphrase
158							break;
159						}
160					}
161					i++;
162				}
163
164				if(type==ERROR)
165				{
166					throw new JSchException("invaid privatekey: "+identity);
167				}
168
169				int start=i;
170				while(i<len)
171				{
172					if(buf[i]==0x0a)
173					{
174						bool xd=(buf[i-1]==0x0d);
175						Array.Copy(buf, i+1, 
176							buf, 
177							i-(xd ? 1 : 0), 
178							len-i-1-(xd ? 1 : 0)
179							);
180						if(xd)len--;
181						len--;
182						continue;
183					}
184					if(buf[i]=='-'){  break; }
185					i++;
186				}
187				encoded_data=Util.fromBase64(buf, start, i-start);
188
189				if(encoded_data.Length>4 &&            // FSecure
190					encoded_data[0]==(byte)0x3f &&
191					encoded_data[1]==(byte)0x6f &&
192					encoded_data[2]==(byte)0xf9 &&
193					encoded_data[3]==(byte)0xeb)
194				{
195
196					Buffer _buf=new Buffer(encoded_data);
197					_buf.getInt();  // 0x3f6ff9be
198					_buf.getInt();
199					byte[]_type=_buf.getString();
200					//System.out.println("type: "+new String(_type)); 
201					byte[] _cipher=_buf.getString();
202					String s_cipher=System.Text.Encoding.Default.GetString(_cipher);
203					//System.out.println("cipher: "+cipher); 
204					if(s_cipher.Equals("3des-cbc"))
205					{
206						_buf.getInt();
207						byte[] foo=new byte[encoded_data.Length-_buf.getOffSet()];
208						_buf.getByte(foo);
209						encoded_data=foo;
210						encrypted=true;
211						throw new JSchException("unknown privatekey format: "+identity);
212					}
213					else if(s_cipher.Equals("none"))
214					{
215						_buf.getInt();
216						//_buf.getInt();
217
218						encrypted=false;
219
220						byte[] foo=new byte[encoded_data.Length-_buf.getOffSet()];
221						_buf.getByte(foo);
222						encoded_data=foo;
223					}
224
225				}
226
227				try
228				{
229					file=new FileInfo(identity+".pub");
230					fis=File.OpenRead(identity+".pub");
231					buf=new byte[(int)(file.Length)];
232					len=fis.Read(buf, 0, buf.Length);
233					fis.Close();
234				}
235				catch
236				{
237					return;
238				}
239
240				if(buf.Length>4 &&             // FSecure's public key
241					buf[0]=='-' && buf[1]=='-' && buf[2]=='-' && buf[3]=='-')
242				{
243
244					i=0;
245					do{i++;}while(buf.Length>i && buf[i]!=0x0a);
246					if(buf.Length<=i) return;
247
248					while(true)
249					{
250						if(buf[i]==0x0a)
251						{
252							bool inheader=false;
253							for(int j=i+1; j<buf.Length; j++)
254							{
255								if(buf[j]==0x0a) break;
256								if(buf[j]==':'){inheader=true; break;}
257							}
258							if(!inheader)
259							{
260								i++; 
261								break;
262							}
263						}
264						i++;
265					}
266					if(buf.Length<=i) return;
267
268					start=i;
269					while(i<len)
270					{
271						if(buf[i]==0x0a)
272						{
273							Array.Copy(buf, i+1, buf, i, len-i-1);
274							len--;
275							continue;
276						}
277						if(buf[i]=='-'){  break; }
278						i++;
279					}
280					publickeyblob=Util.fromBase64(buf, start, i-start);
281
282					if(type==UNKNOWN)
283					{
284						if(publickeyblob[8]=='d')
285						{
286							type=DSS;
287						}
288						else if(publickeyblob[8]=='r')
289						{
290							type=RSA;
291						}
292					}
293				}
294				else
295				{
296					if(buf[0]!='s'|| buf[1]!='s'|| buf[2]!='h'|| buf[3]!='-') return;
297					i=0;
298					while(i<len){ if(buf[i]==' ')break; i++;} i++;
299					if(i>=len) return;
300					start=i;
301					while(i<len){ if(buf[i]==' ')break; i++;}
302					publickeyblob=Util.fromBase64(buf, start, i-start);
303				}
304
305			}
306			catch(System.Exception e)
307			{
308				Console.WriteLine("Identity: "+e);
309				if(e is JSchException) throw (JSchException)e;
310				throw new JSchException(e.ToString());
311			}
312
313		}
314
315		public String getAlgName()
316		{
317			if(type==RSA) return "ssh-rsa";
318			return "ssh-dss"; 
319		}
320
321		public bool setPassphrase(String _passphrase) 
322		{
323			/*
324			hash is MD5
325			h(0) <- hash(passphrase, iv);
326			h(n) <- hash(h(n-1), passphrase, iv);
327			key <- (h(0),...,h(n))[0,..,key.Length];
328			*/
329			try
330			{
331				if(encrypted)
332				{
333					if(_passphrase==null) return false;
334					byte[] passphrase= System.Text.Encoding.Default.GetBytes( _passphrase );
335					int hsize=hash.getBlockSize();
336					byte[] hn=new byte[key.Length/hsize*hsize+
337						(key.Length%hsize==0?0:hsize)];
338					byte[] tmp=null;
339					if(keytype==OPENSSH)
340					{
341						for(int index=0; index+hsize<=hn.Length;)
342						{
343							if(tmp!=null){ hash.update(tmp, 0, tmp.Length); }
344							hash.update(passphrase, 0, passphrase.Length);
345							hash.update(iv, 0, iv.Length);
346							tmp=hash.digest();
347							Array.Copy(tmp, 0, hn, index, tmp.Length);
348							index+=tmp.Length;
349						}
350						Array.Copy(hn, 0, key, 0, key.Length); 
351					}
352					else if(keytype==FSECURE)
353					{
354						for(int index=0; index+hsize<=hn.Length;)
355						{
356							if(tmp!=null){ hash.update(tmp, 0, tmp.Length); }
357							hash.update(passphrase, 0, passphrase.Length);
358							tmp=hash.digest();
359							Array.Copy(tmp, 0, hn, index, tmp.Length);
360							index+=tmp.Length;
361						}
362						Array.Copy(hn, 0, key, 0, key.Length); 
363					}
364				}
365				if(decrypt())
366				{
367					encrypted=false;
368					return true;
369				}
370				P_array=Q_array=G_array=pub_array=prv_array=null;
371				return false;
372			}
373			catch(System.Exception e)
374			{
375				if(e is JSchException) throw (JSchException)e;
376				throw new JSchException(e.ToString());
377			}
378		}
379
380		public byte[] getPublicKeyBlob()
381		{
382			if(publickeyblob!=null) return publickeyblob;
383			if(type==RSA) return getPublicKeyBlob_rsa();
384			return getPublicKeyBlob_dss();
385		}
386
387		byte[] getPublicKeyBlob_rsa()
388		{
389			if(e_array==null) return null;
390			Buffer buf=new Buffer("ssh-rsa".Length+4+
391				e_array.Length+4+ 
392				n_array.Length+4);
393			buf.putString( System.Text.Encoding.Default.GetBytes( "ssh-rsa" ) );
394			buf.putString(e_array);
395			buf.putString(n_array);
396			return buf.buffer;
397		}
398
399		byte[] getPublicKeyBlob_dss()
400		{
401			if(P_array==null) return null;
402			Buffer buf=new Buffer("ssh-dss".Length+4+
403				P_array.Length+4+ 
404				Q_array.Length+4+ 
405				G_array.Length+4+ 
406				pub_array.Length+4);
407			buf.putString(System.Text.Encoding.Default.GetBytes("ssh-dss"));
408			buf.putString(P_array);
409			buf.putString(Q_array);
410			buf.putString(G_array);
411			buf.putString(pub_array);
412			return buf.buffer;
413		}
414
415		public byte[] getSignature(Session session, byte[] data)
416		{
417			if(type==RSA) return getSignature_rsa(session, data);
418			return getSignature_dss(session, data);
419		}
420
421		byte[] getSignature_rsa(Session session, byte[] data)
422		{
423			try
424			{      
425				Type t=Type.GetType(jsch.getConfig("signature.rsa"));
426				SignatureRSA rsa=(SignatureRSA)Activator.CreateInstance(t);
427
428				rsa.init();
429				rsa.setPrvKey(e_array, n_array, d_array, p_array, q_array, dmp1_array, dmq1_array, iqmp_array);
430
431				/*
432				byte[] goo=new byte[4];
433				goo[0]=(byte)(session.getSessionId().Length>>>24);
434				goo[1]=(byte)(session.getSessionId().Length>>>16);
435				goo[2]=(byte)(session.getSessionId().Length>>>8);
436				goo[3]=(byte)(session.getSessionId().Length);
437				rsa.update(goo);
438				rsa.update(session.getSessionId());
439				*/
440				rsa.update(data);
441				byte[] sig = rsa.sign();
442				Buffer buf=new Buffer("ssh-rsa".Length+4+
443					sig.Length+4);
444				buf.putString( System.Text.Encoding.Default.GetBytes( "ssh-rsa" ));
445				buf.putString(sig);
446				return buf.buffer;
447			}
448			catch(System.Exception e)
449			{
450				Console.WriteLine(e);
451			}
452			return null;
453		}
454
455		byte[] getSignature_dss(Session session, byte[] data)
456		{
457			/*
458				byte[] foo;
459				int i;
460				System.out.print("P ");
461				foo=P_array;
462				for(i=0;  i<foo.Length; i++){
463				System.out.print(Integer.toHexString(foo[i]&0xff)+":");
464				}
465				System.out.println("");
466				System.out.print("Q ");
467				foo=Q_array;
468				for(i=0;  i<foo.Length; i++){
469				System.out.print(Integer.toHexString(foo[i]&0xff)+":");
470				}
471				System.out.println("");
472				System.out.print("G ");
473				foo=G_array;
474				for(i=0;  i<foo.Length; i++){
475				System.out.print(Integer.toHexString(foo[i]&0xff)+":");
476				}
477				System.out.println("");
478			*/
479
480			try
481			{      
482				Type t=Type.GetType(jsch.getConfig("signature.dss"));
483				SignatureDSA dsa=(SignatureDSA)(Activator.CreateInstance(t));
484				dsa.init();
485				dsa.setPrvKey(prv_array, P_array, Q_array, G_array);
486
487				/*
488				byte[] goo=new byte[4];
489				goo[0]=(byte)(session.getSessionId().Length>>>24);
490				goo[1]=(byte)(session.getSessionId().Length>>>16);
491				goo[2]=(byte)(session.getSessionId().Length>>>8);
492				goo[3]=(byte)(session.getSessionId().Length);
493				dsa.update(goo);
494				dsa.update(session.getSessionId());
495				*/
496				dsa.update(data);
497				byte[] sig = dsa.sign();
498				Buffer buf=new Buffer("ssh-dss".Length+4+
499					sig.Length+4);
500				buf.putString( System.Text.Encoding.Default.GetBytes( "ssh-dss" ) );
501				buf.putString(sig);
502				return buf.buffer;
503			}
504			catch(System.Exception e)
505			{
506				Console.WriteLine("e "+e);
507			}
508			return null;
509		}
510
511		public bool decrypt()
512		{
513			if(type==RSA) return decrypt_rsa();
514			return decrypt_dss();
515		}
516
517		bool decrypt_rsa()
518		{
519//			byte[] p_array;
520//			byte[] q_array;
521//			byte[] dmp1_array;
522//			byte[] dmq1_array;
523//			byte[] iqmp_array;
524
525			try
526			{
527				byte[] plain;
528				if(encrypted)
529				{
530					if(keytype==OPENSSH)
531					{
532						cipher.init(Cipher.DECRYPT_MODE, key, iv);
533						plain=new byte[encoded_data.Length];
534						cipher.update(encoded_data, 0, encoded_data.Length, plain, 0);
535					}
536					else if(keytype==FSECURE)
537					{
538						for(int i=0; i<iv.Length; i++)iv[i]=0;
539						cipher.init(Cipher.DECRYPT_MODE, key, iv);
540						plain=new byte[encoded_data.Length];
541						cipher.update(encoded_data, 0, encoded_data.Length, plain, 0);
542					}
543					else
544					{
545						return false;
546					}
547				}
548				else
549				{
550					if(n_array!=null) return true;
551					plain=encoded_data;
552				}
553
554				if(keytype==FSECURE)
555				{              // FSecure   
556					Buffer buf=new Buffer(plain);
557					int foo=buf.getInt();
558					if(plain.Length!=foo+4)
559					{
560						return false;
561					}
562					e_array=buf.getMPIntBits();
563					d_array=buf.getMPIntBits();
564					n_array=buf.getMPIntBits();
565					byte[] u_array=buf.getMPIntBits();
566					p_array=buf.getMPIntBits();
567					q_array=buf.getMPIntBits();
568					return true;
569				}
570
571				int index=0;
572				int Length=0;
573
574				if(plain[index]!=0x30)return false;
575				index++; // SEQUENCE
576				Length=plain[index++]&0xff;
577				if((Length&0x80)!=0)
578				{
579					int foo=Length&0x7f; Length=0;
580					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
581				}
582
583				if(plain[index]!=0x02)return false;
584				index++; // INTEGER
585				Length=plain[index++]&0xff;
586				if((Length&0x80)!=0)
587				{
588					int foo=Length&0x7f; Length=0;
589					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
590				}
591				index+=Length;
592
593				//System.out.println("int: len="+Length);
594				//System.out.print(Integer.toHexString(plain[index-1]&0xff)+":");
595				//System.out.println("");
596
597				index++;
598				Length=plain[index++]&0xff;
599				if((Length&0x80)!=0)
600				{
601					int foo=Length&0x7f; Length=0;
602					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
603				}
604				n_array=new byte[Length];
605				Array.Copy(plain, index, n_array, 0, Length);
606				index+=Length;
607				/*
608				System.out.println("int: N len="+Length);
609				for(int i=0; i<n_array.Length; i++){
610				System.out.print(Integer.toHexString(n_array[i]&0xff)+":");
611				}
612				System.out.println("");
613				*/
614				index++;
615				Length=plain[index++]&0xff;
616				if((Length&0x80)!=0)
617				{
618					int foo=Length&0x7f; Length=0;
619					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
620				}
621				e_array=new byte[Length];
622				Array.Copy(plain, index, e_array, 0, Length);
623				index+=Length;
624				/*
625				System.out.println("int: E len="+Length);
626				for(int i=0; i<e_array.Length; i++){
627				System.out.print(Integer.toHexString(e_array[i]&0xff)+":");
628				}
629				System.out.println("");
630				*/
631				index++;
632				Length=plain[index++]&0xff;
633				if((Length&0x80)!=0)
634				{
635					int foo=Length&0x7f; Length=0;
636					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
637				}
638				d_array=new byte[Length];
639				Array.Copy(plain, index, d_array, 0, Length);
640				index+=Length;
641				/*
642				System.out.println("int: D len="+Length);
643				for(int i=0; i<d_array.Length; i++){
644				System.out.print(Integer.toHexString(d_array[i]&0xff)+":");
645				}
646				System.out.println("");
647				*/
648
649				index++;
650				Length=plain[index++]&0xff;
651				if((Length&0x80)!=0)
652				{
653					int foo=Length&0x7f; Length=0;
654					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
655				}
656				p_array=new byte[Length];
657				Array.Copy(plain, index, p_array, 0, Length);
658				index+=Length;
659				/*
660				System.out.println("int: P len="+Length);
661				for(int i=0; i<p_array.Length; i++){
662				System.out.print(Integer.toHexString(p_array[i]&0xff)+":");
663				}
664				System.out.println("");
665				*/
666				index++;
667				Length=plain[index++]&0xff;
668				if((Length&0x80)!=0)
669				{
670					int foo=Length&0x7f; Length=0;
671					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
672				}
673				q_array=new byte[Length];
674				Array.Copy(plain, index, q_array, 0, Length);
675				index+=Length;
676				/*
677				System.out.println("int: q len="+Length);
678				for(int i=0; i<q_array.Length; i++){
679				System.out.print(Integer.toHexString(q_array[i]&0xff)+":");
680				}
681				System.out.println("");
682				*/
683				index++;
684				Length=plain[index++]&0xff;
685				if((Length&0x80)!=0)
686				{
687					int foo=Length&0x7f; Length=0;
688					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
689				}
690				dmp1_array=new byte[Length];
691				Array.Copy(plain, index, dmp1_array, 0, Length);
692				index+=Length;
693				/*
694				System.out.println("int: dmp1 len="+Length);
695				for(int i=0; i<dmp1_array.Length; i++){
696				System.out.print(Integer.toHexString(dmp1_array[i]&0xff)+":");
697				}
698				System.out.println("");
699				*/
700				index++;
701				Length=plain[index++]&0xff;
702				if((Length&0x80)!=0)
703				{
704					int foo=Length&0x7f; Length=0;
705					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
706				}
707				dmq1_array=new byte[Length];
708				Array.Copy(plain, index, dmq1_array, 0, Length);
709				index+=Length;
710				/*
711				System.out.println("int: dmq1 len="+Length);
712				for(int i=0; i<dmq1_array.Length; i++){
713				System.out.print(Integer.toHexString(dmq1_array[i]&0xff)+":");
714				}
715				System.out.println("");
716				*/
717				index++;
718				Length=plain[index++]&0xff;
719				if((Length&0x80)!=0)
720				{
721					int foo=Length&0x7f; Length=0;
722					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
723				}
724				iqmp_array=new byte[Length];
725				Array.Copy(plain, index, iqmp_array, 0, Length);
726				index+=Length;
727				/*
728				System.out.println("int: iqmp len="+Length);
729				for(int i=0; i<iqmp_array.Length; i++){
730				System.out.print(Integer.toHexString(iqmp_array[i]&0xff)+":");
731				}
732				System.out.println("");
733				*/
734			}
735			catch
736			{
737				//System.out.println(e);
738				return false;
739			}
740			return true;
741		}
742
743		bool decrypt_dss()
744		{
745			try
746			{
747				byte[] plain;
748				if(encrypted)
749				{
750					if(keytype==OPENSSH)
751					{
752						cipher.init(Cipher.DECRYPT_MODE, key, iv);
753						plain=new byte[encoded_data.Length];
754						cipher.update(encoded_data, 0, encoded_data.Length, plain, 0);
755						/*
756						for(int i=0; i<plain.Length; i++){
757						System.out.print(Integer.toHexString(plain[i]&0xff)+":");
758						}
759						System.out.println("");
760						*/
761					}
762					else if(keytype==FSECURE)
763					{
764						for(int i=0; i<iv.Length; i++)iv[i]=0;
765						cipher.init(Cipher.DECRYPT_MODE, key, iv);
766						plain=new byte[encoded_data.Length];
767						cipher.update(encoded_data, 0, encoded_data.Length, plain, 0);
768					}
769					else
770					{
771						return false;
772					}
773				}
774				else
775				{
776					if(P_array!=null) return true;
777					plain=encoded_data;
778				}
779
780				if(keytype==FSECURE)
781				{              // FSecure   
782					Buffer buf=new Buffer(plain);
783					int foo=buf.getInt();
784					if(plain.Length!=foo+4)
785					{
786						return false;
787					}
788					P_array=buf.getMPIntBits();
789					G_array=buf.getMPIntBits();
790					Q_array=buf.getMPIntBits();
791					pub_array=buf.getMPIntBits();
792					prv_array=buf.getMPIntBits();
793					return true;
794				}
795
796				int index=0;
797				int Length=0;
798
799				if(plain[index]!=0x30)return false;
800				index++; // SEQUENCE
801				Length=plain[index++]&0xff;
802				if((Length&0x80)!=0)
803				{
804					int foo=Length&0x7f; Length=0;
805					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
806				}
807
808				if(plain[index]!=0x02)return false;
809				index++; // INTEGER
810				Length=plain[index++]&0xff;
811				if((Length&0x80)!=0)
812				{
813					int foo=Length&0x7f; Length=0;
814					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
815				}
816				index+=Length;
817
818				index++;
819				Length=plain[index++]&0xff;
820				if((Length&0x80)!=0)
821				{
822					int foo=Length&0x7f; Length=0;
823					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
824				}
825				P_array=new byte[Length];
826				Array.Copy(plain, index, P_array, 0, Length);
827				index+=Length;
828
829				index++;
830				Length=plain[index++]&0xff;
831				if((Length&0x80)!=0)
832				{
833					int foo=Length&0x7f; Length=0;
834					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
835				}
836				Q_array=new byte[Length];
837				Array.Copy(plain, index, Q_array, 0, Length);
838				index+=Length;
839
840				index++;
841				Length=plain[index++]&0xff;
842				if((Length&0x80)!=0)
843				{
844					int foo=Length&0x7f; Length=0;
845					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
846				}
847				G_array=new byte[Length];
848				Array.Copy(plain, index, G_array, 0, Length);
849				index+=Length;
850
851				index++;
852				Length=plain[index++]&0xff;
853				if((Length&0x80)!=0)
854				{
855					int foo=Length&0x7f; Length=0;
856					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
857				}
858				pub_array=new byte[Length];
859				Array.Copy(plain, index, pub_array, 0, Length);
860				index+=Length;
861
862				index++;
863				Length=plain[index++]&0xff;
864				if((Length&0x80)!=0)
865				{
866					int foo=Length&0x7f; Length=0;
867					while(foo-->0){ Length=(Length<<8)+(plain[index++]&0xff); }
868				}
869				prv_array=new byte[Length];
870				Array.Copy(plain, index, prv_array, 0, Length);
871				index+=Length;
872			}
873			catch
874			{
875				//System.out.println(e);
876				//e.printStackTrace();
877				return false;
878			}
879			return true;
880		}
881
882		public bool isEncrypted()
883		{
884			return encrypted;
885		}
886		public String getName(){return identity;}
887
888		private int writeSEQUENCE(byte[] buf, int index, int len)
889		{
890			buf[index++]=0x30;
891			index=writeLength(buf, index, len);
892			return index;
893		}
894		private int writeINTEGER(byte[] buf, int index, byte[] data)
895		{
896			buf[index++]=0x02;
897			index=writeLength(buf, index, data.Length);
898			Array.Copy(data, 0, buf, index, data.Length);
899			index+=data.Length;
900			return index;
901		}
902
903		private int countLength(int i_len)
904		{
905			uint len = (uint)i_len;
906			int i=1;
907			if(len<=0x7f) return i;
908			while(len>0)
909			{
910				len>>=8;
911				i++;
912			}
913			return i;
914		}
915
916		private int writeLength(byte[] data, int index, int i_len)
917		{
918			int len = (int)i_len;
919			int i=countLength(len)-1;
920			if(i==0)
921			{
922				data[index++]=(byte)len;
923				return index;
924			}
925			data[index++]=(byte)(0x80|i);
926			int j=index+i;
927			while(i>0)
928			{
929				data[index+i-1]=(byte)(len&0xff);
930				len>>=8;
931				i--;
932			}
933			return j;
934		}
935
936		private byte a2b(byte c)
937		{
938			if('0'<=c&&c<='9') return (byte)(c-'0');
939			if('a'<=c&&c<='z') return (byte)(c-'a'+10);
940			return (byte)(c-'A'+10);
941		}
942		private byte b2a(byte c)
943		{
944			if(0<=c&&c<=9) return (byte)(c+'0');
945			return (byte)(c-10+'A');
946		}
947	}
948
949}