\r\n" .
' ' . base64_encode($raw['modulus']) . "\r\n" .
' ' . base64_encode($raw['publicExponent']) . "\r\n" .
' ' . base64_encode($raw['prime1']) . "
\r\n" .
' ' . base64_encode($raw['prime2']) . "
\r\n" .
' ' . base64_encode($raw['exponent1']) . "\r\n" .
' ' . base64_encode($raw['exponent2']) . "\r\n" .
' ' . base64_encode($raw['coefficient']) . "\r\n" .
' ' . base64_encode($raw['privateExponent']) . "\r\n" .
'';
break;
case CRYPT_RSA_PRIVATE_FORMAT_PUTTY:
if ($num_primes != 2) {
return false;
}
$key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: ";
$encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
$key.= $encryption;
$key.= "\r\nComment: " . $this->comment . "\r\n";
$public = pack('Na*Na*Na*',
strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus']
);
$source = pack('Na*Na*Na*Na*',
strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption,
strlen($this->comment), $this->comment, strlen($public), $public
);
$public = base64_encode($public);
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
$key.= chunk_split($public, 64);
$private = pack('Na*Na*Na*Na*',
strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'],
strlen($raw['prime2']), $raw['prime2'], strlen($raw['coefficient']), $raw['coefficient']
);
if (empty($this->password) && !is_string($this->password)) {
$source.= pack('Na*', strlen($private), $private);
$hashkey = 'putty-private-key-file-mac-key';
} else {
$private.= crypt_random_string(16 - (strlen($private) & 15));
$source.= pack('Na*', strlen($private), $private);
if (!class_exists('Crypt_AES')) {
include_once 'Crypt/AES.php';
}
$sequence = 0;
$symkey = '';
while (strlen($symkey) < 32) {
$temp = pack('Na*', $sequence++, $this->password);
$symkey.= pack('H*', sha1($temp));
}
$symkey = substr($symkey, 0, 32);
$crypto = new Crypt_AES();
$crypto->setKey($symkey);
$crypto->disablePadding();
$private = $crypto->encrypt($private);
$hashkey = 'putty-private-key-file-mac-key' . $this->password;
}
$private = base64_encode($private);
$key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n";
$key.= chunk_split($private, 64);
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$hash = new Crypt_Hash('sha1');
$hash->setKey(pack('H*', sha1($hashkey)));
$key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n";
return $key;
default: // eg. CRYPT_RSA_PRIVATE_FORMAT_PKCS1
$components = array();
foreach ($raw as $name => $value) {
$components[$name] = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value);
}
$RSAPrivateKey = implode('', $components);
if ($num_primes > 2) {
$OtherPrimeInfos = '';
for ($i = 3; $i <= $num_primes; $i++) {
// OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
//
// OtherPrimeInfo ::= SEQUENCE {
// prime INTEGER, -- ri
// exponent INTEGER, -- di
// coefficient INTEGER -- ti
// }
$OtherPrimeInfo = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
$OtherPrimeInfos.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
}
$RSAPrivateKey.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
}
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) {
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPrivateKey = pack('Ca*a*Ca*a*',
CRYPT_RSA_ASN1_INTEGER, "\01\00", $rsaOID, 4, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" .
chunk_split(base64_encode($RSAPrivateKey), 64) .
'-----END PRIVATE KEY-----';
return $RSAPrivateKey;
}
if (!empty($this->password) || is_string($this->password)) {
$iv = crypt_random_string(8);
$symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
$symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$des = new Crypt_TripleDES();
$des->setKey($symkey);
$des->setIV($iv);
$iv = strtoupper(bin2hex($iv));
$RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
"Proc-Type: 4,ENCRYPTED\r\n" .
"DEK-Info: DES-EDE3-CBC,$iv\r\n" .
"\r\n" .
chunk_split(base64_encode($des->encrypt($RSAPrivateKey)), 64) .
'-----END RSA PRIVATE KEY-----';
} else {
$RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
chunk_split(base64_encode($RSAPrivateKey), 64) .
'-----END RSA PRIVATE KEY-----';
}
return $RSAPrivateKey;
}
}
/**
* Convert a public key to the appropriate format
*
* @access private
* @see setPublicKeyFormat()
* @param String $RSAPrivateKey
* @return String
*/
function _convertPublicKey($n, $e)
{
$modulus = $n->toBytes(true);
$publicExponent = $e->toBytes(true);
switch ($this->publicKeyFormat) {
case CRYPT_RSA_PUBLIC_FORMAT_RAW:
return array('e' => $e->copy(), 'n' => $n->copy());
case CRYPT_RSA_PUBLIC_FORMAT_XML:
return "