001: /*
002: * SSHTools - Java SSH2 API
003: *
004: * Copyright (C) 2002-2003 Lee David Painter and Contributors.
005: *
006: * Contributions made by:
007: *
008: * Brett Smith
009: * Richard Pernavas
010: * Erwin Bolwidt
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
025: */
026: package com.sshtools.j2ssh.transport.publickey;
027:
028: import com.sshtools.j2ssh.io.ByteArrayReader;
029: import com.sshtools.j2ssh.transport.AlgorithmNotSupportedException;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033:
034: import java.io.File;
035: import java.io.FileInputStream;
036: import java.io.IOException;
037:
038: import java.util.Iterator;
039:
040: /**
041: *
042: *
043: * @author $author$
044: * @version $Revision: 1.21 $
045: */
046: public class SshPrivateKeyFile {
047: private static Log log = LogFactory.getLog(SshPrivateKeyFile.class);
048: private SshPrivateKeyFormat format;
049: private byte[] keyblob;
050:
051: /**
052: * Creates a new SshPrivateKeyFile object.
053: *
054: * @param keyblob
055: * @param format
056: */
057: protected SshPrivateKeyFile(byte[] keyblob,
058: SshPrivateKeyFormat format) {
059: this .keyblob = keyblob;
060: this .format = format;
061: }
062:
063: /**
064: *
065: *
066: * @return
067: */
068: public byte[] getBytes() {
069: return keyblob;
070: }
071:
072: /**
073: *
074: *
075: * @param passphrase
076: *
077: * @return
078: *
079: * @throws InvalidSshKeyException
080: */
081: public byte[] getKeyBlob(String passphrase)
082: throws InvalidSshKeyException {
083: return format.decryptKeyblob(keyblob, passphrase);
084: }
085:
086: /**
087: *
088: *
089: * @param oldPassphrase
090: * @param newPassphrase
091: *
092: * @throws InvalidSshKeyException
093: */
094: public void changePassphrase(String oldPassphrase,
095: String newPassphrase) throws InvalidSshKeyException {
096: byte[] raw = format.decryptKeyblob(keyblob, oldPassphrase);
097: keyblob = format.encryptKeyblob(raw, newPassphrase);
098: }
099:
100: /**
101: *
102: *
103: * @param formattedKey
104: *
105: * @return
106: *
107: * @throws InvalidSshKeyException
108: */
109: public static SshPrivateKeyFile parse(byte[] formattedKey)
110: throws InvalidSshKeyException {
111: if (formattedKey == null) {
112: throw new InvalidSshKeyException("Key data is null");
113: }
114:
115: log.info("Parsing private key file");
116:
117: // Try the default private key format
118: SshPrivateKeyFormat format;
119: format = SshPrivateKeyFormatFactory
120: .newInstance(SshPrivateKeyFormatFactory
121: .getDefaultFormatType());
122:
123: boolean valid = format.isFormatted(formattedKey);
124:
125: if (!valid) {
126: log
127: .info("Private key is not in the default format, attempting parse with other supported formats");
128:
129: Iterator it = SshPrivateKeyFormatFactory
130: .getSupportedFormats().iterator();
131: String ft;
132:
133: while (it.hasNext() && !valid) {
134: ft = (String) it.next();
135: log.debug("Attempting " + ft);
136: format = SshPrivateKeyFormatFactory.newInstance(ft);
137: valid = format.isFormatted(formattedKey);
138: }
139: }
140:
141: if (valid) {
142: return new SshPrivateKeyFile(formattedKey, format);
143: } else {
144: throw new InvalidSshKeyException(
145: "The key format is not a supported format");
146: }
147: }
148:
149: /**
150: *
151: *
152: * @param keyfile
153: *
154: * @return
155: *
156: * @throws InvalidSshKeyException
157: * @throws IOException
158: */
159: public static SshPrivateKeyFile parse(File keyfile)
160: throws InvalidSshKeyException, IOException {
161: FileInputStream in = new FileInputStream(keyfile);
162: byte[] data = null;
163:
164: try {
165: data = new byte[in.available()];
166: in.read(data);
167: } finally {
168: try {
169: if (in != null) {
170: in.close();
171: }
172: } catch (IOException ex) {
173: }
174: }
175:
176: return parse(data);
177: }
178:
179: /**
180: *
181: *
182: * @return
183: */
184: public boolean isPassphraseProtected() {
185: return format.isPassphraseProtected(keyblob);
186: }
187:
188: /*public void changePassphrase(String oldPassphrase, String newPassphrase)
189: throws InvalidSshKeyException {
190: keyblob = format.changePassphrase(keyblob, oldPassphrase, newPassphrase);
191: }*/
192: public static SshPrivateKeyFile create(SshPrivateKey key,
193: String passphrase, SshPrivateKeyFormat format)
194: throws InvalidSshKeyException {
195: byte[] keyblob = format.encryptKeyblob(key.getEncoded(),
196: passphrase);
197:
198: return new SshPrivateKeyFile(keyblob, format);
199: }
200:
201: /**
202: *
203: *
204: * @param newFormat
205: * @param passphrase
206: *
207: * @throws InvalidSshKeyException
208: */
209: public void setFormat(SshPrivateKeyFormat newFormat,
210: String passphrase) throws InvalidSshKeyException {
211: byte[] raw = this .format.decryptKeyblob(keyblob, passphrase);
212: format = newFormat;
213: keyblob = format.encryptKeyblob(raw, passphrase);
214: }
215:
216: /**
217: *
218: *
219: * @return
220: */
221: public SshPrivateKeyFormat getFormat() {
222: return format;
223: }
224:
225: /**
226: *
227: *
228: * @param passphrase
229: *
230: * @return
231: *
232: * @throws InvalidSshKeyException
233: */
234: public SshPrivateKey toPrivateKey(String passphrase)
235: throws InvalidSshKeyException {
236: try {
237: byte[] raw = format.decryptKeyblob(keyblob, passphrase);
238: SshKeyPair pair = SshKeyPairFactory
239: .newInstance(getAlgorithm(raw));
240:
241: return pair.decodePrivateKey(raw);
242: } catch (AlgorithmNotSupportedException anse) {
243: throw new InvalidSshKeyException(
244: "The public key algorithm for this private key is not supported");
245: }
246: }
247:
248: /**
249: *
250: *
251: * @return
252: */
253: public String toString() {
254: return new String(keyblob);
255: }
256:
257: private String getAlgorithm(byte[] raw) {
258: return ByteArrayReader.readString(raw, 0);
259: }
260: }
|