PageRenderTime 121ms CodeModel.GetById 31ms app.highlight 52ms RepoModel.GetById 8ms app.codeStats 1ms

/SharpSSH/jsch/KeyPair.cs

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