/** * Returns a cipher object corresponding to a string * * @access public * @param string $algo * @return string * @throws \UnexpectedValueException if the encryption algorithm is unsupported */ static function getEncryptionObject($algo) { $modes = '(CBC|ECB|CFB|OFB|CTR)'; switch (true) { case preg_match("#^AES-(128|192|256)-{$modes}\$#", $algo, $matches): $cipher = new AES(self::getEncryptionMode($matches[2])); $cipher->setKeyLength($matches[1]); return $cipher; case preg_match("#^DES-EDE3-{$modes}\$#", $algo, $matches): return new TripleDES(self::getEncryptionMode($matches[1])); case preg_match("#^DES-{$modes}\$#", $algo, $matches): return new DES(self::getEncryptionMode($matches[1])); default: throw new \UnexpectedValueException('Unsupported encryption algorithmn'); } }
public static function getCipher($algo) { $cipher = NULL; switch ($algo) { case 2: $cipher = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); $key_bytes = 24; $key_block_bytes = 8; break; case 3: /* Horde change if(defined('MCRYPT_CAST_128')) { $cipher = new MCryptWrapper(MCRYPT_CAST_128); } */ $cipher = new Horde_Pgp_Crypt_Cast128(); /* End Horde Change */ break; /* Horde change */ /* Horde change */ case 4: $cipher = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CFB); $key_bytes = 16; break; /* End Horde Change */ /* End Horde Change */ case 7: $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(128); break; case 8: $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(192); break; case 9: $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(256); break; /* Horde change */ /* Horde change */ case 10: $cipher = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CFB); $key_bytes = 32; break; /* End Horde Change */ } if (!$cipher) { return array(NULL, NULL, NULL); } // Unsupported cipher if (!isset($key_bytes)) { $key_bytes = isset($cipher->key_size) ? $cipher->key_size : $cipher->key_length; } if (!isset($key_block_bytes)) { $key_block_bytes = $cipher->block_size; } return array($cipher, $key_bytes, $key_block_bytes); }
/** * Returns a SymmetricKey object baesd on a PBES2 $algo * * @access public * @param string $algo */ static function getPBES2EncryptionObject($algo) { switch ($algo) { case 'desCBC': $cipher = new TripleDES(BlockCipher::MODE_CBC); break; case 'des-EDE3-CBC': $cipher = new TripleDES(BlockCipher::MODE_CBC); break; case 'rc2CBC': $cipher = new RC2(BlockCipher::MODE_CBC); // in theory this can be changed $cipher->setKeyLength(128); break; case 'rc5-CBC-PAD': throw new UnsupportedAlgorithmException('rc5-CBC-PAD is not supported for PBES2 PKCS#8 keys'); case 'aes128-CBC-PAD': case 'aes192-CBC-PAD': case 'aes256-CBC-PAD': $cipher = new AES(BlockCipher::MODE_CBC); $cipher->setKeyLength(substr($algo, 3, 3)); break; default: throw new UnsupportedAlgorithmException("{$algo} is not supported"); } return $cipher; }
/** */ public function generateKey($opts) { $skey = $this->_generateSecretKeyPacket($opts['keylength'], 'OpenPGP_SecretKeyPacket'); $id = new Horde_Mail_Rfc822_Address($opts['email']); if (strlen($opts['comment'])) { $id->comment[] = $opts['comment']; } if (strlen($opts['name'])) { $id->personal = $opts['name']; } /* This is the private key we are creating. */ $key = new OpenPGP_Message(array($skey, new OpenPGP_UserIDPacket($id->writeAddress(array('comment' => true))))); $rsa = OpenPGP_Crypt_RSA::convert_private_key($skey); $rsa->setHash(Horde_String::lower($opts['hash'])); $rsa_sign_func = array('RSA' => array($opts['hash'] => function ($data) use($rsa) { return array($rsa->sign($data)); })); /* Create signature packet. */ $sig = new OpenPGP_SignaturePacket($key, 'RSA', $opts['hash']); /* "Generic certification of a User ID and Public-Key packet." */ $sig->signature_type = 0x10; /* Add subpacket information. */ $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0x3)); $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_PreferredSymmetricAlgorithmsPacket(array(0x9, 0x8, 0x7, 0x2)); $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_PreferredHashAlgorithmsPacket(array(0x8, 0x9, 0xa, 0xb, 0x2)); $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_PreferredCompressionAlgorithmsPacket(array(0x2, 0x1)); $ks_prefs = new OpenPGP_SignaturePacket_KeyServerPreferencesPacket(); $ks_prefs->no_modify = true; $sig->hashed_subpackets[] = $ks_prefs; $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_FeaturesPacket(array(0x1)); if (isset($opts['expire'])) { $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyExpirationTimePacket($opts['expire'] - time()); } $sig->unhashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket(substr($skey->fingerprint, -16)); $key[] = $sig; /* Create self-signature. */ $sig->sign_data($rsa_sign_func); /* OpenPGP currently (as of April 2015) encrypts passphrases w/ * AES-128 & SHA-1, so use this strategy. */ if (strlen($opts['passphrase'])) { $cipher = new Crypt\AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(128); $s2k = new OpenPGP_S2K(Crypt\Random::String(8), 2); $cipher->setKey($s2k->make_key($opts['passphrase'], 16)); $iv = Crypt\Random::String(16); $this->_encryptPrivateKey($skey, $cipher, $s2k, $iv); } /* Encryption subkey. See RFC 4880 [5.5.1.2] (by convention, top-level * key is used for signing and subkeys are used for encryption) */ $ekey = $this->_generateSecretKeyPacket($opts['keylength'], 'OpenPGP_SecretSubkeyPacket'); /* Computing signature: RFC 4880 [5.2.4] */ $sig = new OpenPGP_SignaturePacket(implode('', $skey->fingerprint_material()) . implode('', $ekey->fingerprint_material()), 'RSA', $opts['hash']); /* This is a "Subkey Binding Signature". */ $sig->signature_type = 0x18; $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0xc)); $sig->unhashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket(substr($skey->fingerprint, -16)); $sig->sign_data($rsa_sign_func); if (strlen($opts['passphrase'])) { $this->_encryptPrivateKey($ekey, $cipher, $s2k, $iv); } $key[] = $ekey; $key[] = $sig; return new Horde_Pgp_Element_PrivateKey($key); }