📄 keypair.cs
字号:
/*
hash is MD5
h(0) <- hash(passphrase, iv);
h(n) <- hash(h(n-1), passphrase, iv);
key <- (h(0),...,h(n))[0,..,key.Length];
*/
[MethodImpl(MethodImplOptions.Synchronized)]
internal byte[] genKey(byte[] passphrase, byte[] iv)
{
if(cipher==null) cipher=genCipher();
if(hash==null) hash=genHash();
byte[] key=new byte[cipher.getBlockSize()];
int hsize=hash.getBlockSize();
byte[] hn=new byte[key.Length/hsize*hsize+
(key.Length%hsize==0?0:hsize)];
try
{
byte[] tmp=null;
if(vendor==VENDOR_OPENSSH)
{
for(int index=0; index+hsize<=hn.Length;)
{
if(tmp!=null){ hash.update(tmp, 0, tmp.Length); }
hash.update(passphrase, 0, passphrase.Length);
hash.update(iv, 0, iv.Length);
tmp=hash.digest();
Array.Copy(tmp, 0, hn, index, tmp.Length);
index+=tmp.Length;
}
Array.Copy(hn, 0, key, 0, key.Length);
}
else if(vendor==VENDOR_FSECURE)
{
for(int index=0; index+hsize<=hn.Length;)
{
if(tmp!=null){ hash.update(tmp, 0, tmp.Length); }
hash.update(passphrase, 0, passphrase.Length);
tmp=hash.digest();
Array.Copy(tmp, 0, hn, index, tmp.Length);
index+=tmp.Length;
}
Array.Copy(hn, 0, key, 0, key.Length);
}
}
catch(Exception e)
{
Console.WriteLine(e);
}
return key;
}
public void setPassphrase(String passphrase)
{
if(passphrase==null || passphrase.Length==0)
{
setPassphrase((byte[])null);
}
else
{
setPassphrase(Util.getBytes( passphrase ));
}
}
public void setPassphrase(byte[] passphrase)
{
if(passphrase!=null && passphrase.Length==0)
passphrase=null;
this.passphrase=passphrase;
}
private bool encrypted=false;
private byte[] data=null;
private byte[] iv=null;
private byte[] publickeyblob=null;
public bool isEncrypted(){ return encrypted; }
public bool decrypt(String _passphrase)
{
byte[] passphrase= Util.getBytes( _passphrase );
byte[] foo=decrypt(data, passphrase, iv);
if(parse(foo))
{
encrypted=false;
}
return !encrypted;
}
public static KeyPair load(JSch jsch, String prvkey)
{
String pubkey=prvkey+".pub";
// if(!new File(pubkey).exists())
if(!File.Exists(pubkey))
{
pubkey=null;
}
return load(jsch, prvkey, pubkey);
}
public static KeyPair load(JSch jsch, String prvkey, String pubkey)
{
byte[] iv=new byte[8]; // 8
bool encrypted=true;
byte[] data=null;
byte[] publickeyblob=null;
int type=ERROR;
int vendor=VENDOR_OPENSSH;
try
{
//File file=new File(prvkey);
FileStream fis=File.OpenRead(prvkey);
byte[] buf=new byte[(int)(fis.Length)];
int len=fis.Read(buf, 0, buf.Length);
fis.Close();
int i=0;
while(i<len)
{
if(buf[i]=='B'&& buf[i+1]=='E'&& buf[i+2]=='G'&& buf[i+3]=='I')
{
i+=6;
if(buf[i]=='D'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=DSA; }
else if(buf[i]=='R'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=RSA; }
else if(buf[i]=='S'&& buf[i+1]=='S'&& buf[i+2]=='H')
{ // FSecure
type=UNKNOWN;
vendor=VENDOR_FSECURE;
}
else
{
//System.outs.println("invalid format: "+identity);
throw new JSchException("invaid privatekey: "+prvkey);
}
i+=3;
continue;
}
if(buf[i]=='C'&& buf[i+1]=='B'&& buf[i+2]=='C'&& buf[i+3]==',')
{
i+=4;
for(int ii=0; ii<iv.Length; ii++)
{
iv[ii]=(byte)(((a2b(buf[i++])<<4)&0xf0)+(a2b(buf[i++])&0xf));
}
continue;
}
if(buf[i]==0x0d &&
i+1<buf.Length && buf[i+1]==0x0a)
{
i++;
continue;
}
if(buf[i]==0x0a && i+1<buf.Length)
{
if(buf[i+1]==0x0a){ i+=2; break; }
if(buf[i+1]==0x0d &&
i+2<buf.Length && buf[i+2]==0x0a)
{
i+=3; break;
}
bool inheader=false;
for(int j=i+1; j<buf.Length; j++)
{
if(buf[j]==0x0a) break;
//if(buf[j]==0x0d) break;
if(buf[j]==':'){inheader=true; break;}
}
if(!inheader)
{
i++;
encrypted=false; // no passphrase
break;
}
}
i++;
}
if(type==ERROR)
{
throw new JSchException("invaid privatekey: "+prvkey);
}
int start=i;
while(i<len)
{
if(buf[i]==0x0a)
{
bool xd=(buf[i-1]==0x0d);
Array.Copy(buf, i+1,
buf,
i-(xd ? 1 : 0),
len-i-1-(xd ? 1 : 0)
);
if(xd)len--;
len--;
continue;
}
if(buf[i]=='-'){ break; }
i++;
}
data=Util.fromBase64(buf, start, i-start);
if(data.Length>4 && // FSecure
data[0]==(byte)0x3f &&
data[1]==(byte)0x6f &&
data[2]==(byte)0xf9 &&
data[3]==(byte)0xeb)
{
Buffer _buf=new Buffer(data);
_buf.getInt(); // 0x3f6ff9be
_buf.getInt();
byte[]_type=_buf.getString();
//System.outs.println("type: "+new String(_type));
byte[] _cipher=_buf.getString();
String cipher=Util.getString(_cipher);
//System.outs.println("cipher: "+cipher);
if(cipher.Equals("3des-cbc"))
{
_buf.getInt();
byte[] foo=new byte[data.Length-_buf.getOffSet()];
_buf.getByte(foo);
data=foo;
encrypted=true;
throw new JSchException("unknown privatekey format: "+prvkey);
}
else if(cipher.Equals("none"))
{
_buf.getInt();
_buf.getInt();
encrypted=false;
byte[] foo=new byte[data.Length-_buf.getOffSet()];
_buf.getByte(foo);
data=foo;
}
}
if(pubkey!=null)
{
try
{
//file=new File(pubkey);
fis=File.OpenRead(pubkey);
buf=new byte[(int)(fis.Length)];
len=fis.Read(buf, 0, buf.Length);
fis.Close();
if(buf.Length>4 && // FSecure's public key
buf[0]=='-' && buf[1]=='-' && buf[2]=='-' && buf[3]=='-')
{
bool valid=true;
i=0;
do{i++;}while(buf.Length>i && buf[i]!=0x0a);
if(buf.Length<=i) {valid=false;}
while(valid)
{
if(buf[i]==0x0a)
{
bool inheader=false;
for(int j=i+1; j<buf.Length; j++)
{
if(buf[j]==0x0a) break;
if(buf[j]==':'){inheader=true; break;}
}
if(!inheader)
{
i++;
break;
}
}
i++;
}
if(buf.Length<=i){valid=false;}
start=i;
while(valid && i<len)
{
if(buf[i]==0x0a)
{
Array.Copy(buf, i+1, buf, i, len-i-1);
len--;
continue;
}
if(buf[i]=='-'){ break; }
i++;
}
if(valid)
{
publickeyblob=Util.fromBase64(buf, start, i-start);
if(type==UNKNOWN)
{
if(publickeyblob[8]=='d'){ type=DSA; }
else if(publickeyblob[8]=='r'){ type=RSA; }
}
}
}
else
{
if(buf[0]=='s'&& buf[1]=='s'&& buf[2]=='h' && buf[3]=='-')
{
i=0;
while(i<len){ if(buf[i]==' ')break; i++;} i++;
if(i<len)
{
start=i;
while(i<len){ if(buf[i]==' ')break; i++;}
publickeyblob=Util.fromBase64(buf, start, i-start);
}
}
}
}
catch//(Exception ee)
{
}
}
}
catch(Exception e)
{
if(e is JSchException) throw (JSchException)e;
throw new JSchException(e.ToString());
}
KeyPair kpair=null;
if(type==DSA){ kpair=new KeyPairDSA(jsch); }
else if(type==RSA){ kpair=new KeyPairRSA(jsch); }
if(kpair!=null)
{
kpair.encrypted=encrypted;
kpair.publickeyblob=publickeyblob;
kpair.vendor=vendor;
if(encrypted)
{
kpair.iv=iv;
kpair.data=data;
}
else
{
if(kpair.parse(data))
{
return kpair;
}
else
{
throw new JSchException("invaid privatekey: "+prvkey);
}
}
}
return kpair;
}
static private byte a2b(byte c)
{
if('0'<=c&&c<='9') return (byte)(c-'0');
return (byte)(c-'a'+10);
}
static private byte b2a(byte c)
{
if(0<=c&&c<=9) return (byte)(c+'0');
return (byte)(c-10+'A');
}
public virtual void dispose()
{
passphrase=null;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -