1OpenSSL extension for PHP 2 3$Id$ 4 5The functions implemented so far make it possible to seal and open data, and 6also create and verify signatures. 7 8NEW: support for S/MIME encrypt/decrypt/sign/verify, as well as more 9flexibility for specifying certificates/keys. 10 11To enable the extension, configure PHP with --with-openssl. 12 13Specifying keys/certificates 14---------------------------- 15 16Most of the functions require a key or a certificate as a parameter; to make 17things easy for you to use openssl, this extension allows you 18to specify certificates in the following way: 19 201. As an X.509 resource returned from openssl_x509_read 212. As a string in the format file://filename, where filename is the path to the 22 certificate file (it will be opened and read automatically) 233. As a string containing the data from the certificate file 24 25Similarly, you can use the following methods of specifying a public key: 26 271. As a key resource returned from openssl_get_publickey 282. An X509 resource - public key only 293. As a string in the format file://filename 304. As a string containing the data from the key file 31 32Additionally, for a private key, when the openssl extension function does not 33allow you to enter the passphrase as a parameter you may use the syntax 34array($key, "passphrase") where $key can be a key specified using one of the 35methods listed above. 36 37Certificate Verification 38------------------------ 39When calling a function that will verify a signature/certificate, the cainfo 40parameter is an array containing file and directory names that specifiy the 41locations of trusted CA files. If a directory is specified, then it must be a 42correctly hashed directory. 43 44Misc: 45----- 46 47mixed openssl_error_string() 48 49returns the message from the last error that the OpenSSL library encountered 50and moves it's internal error pointer to the next message. If there are no 51more error messages, returns false. 52 53General Key/Cert Functions: 54--------------------------- 55 56resource openssl_get_privatekey(mixed key [, string passphrase]) 57 58Parses the key data and returns a key resource identifier. If the key is 59encrypted a passphrase is needed. This can be supplied as second argument. 60 61 62resource openssl_get_publickey(mixed cert) 63 64Extracts the public key from the given certificate or public key and returns 65a key resource identifier. 66 67 68void openssl_free_key(resource key) 69 70Frees the resource given by the key resource identifier. 71Note that this function does not accept the extended key specification 72syntax mentioned above, as it doesn't make sense in this case! 73 74array openssl_x509_parse(mixed x509[, bool shortnames=true]) 75 76Parses the certificate data and returns an array containing information 77about the certificate, it's intended purposes, subject, issuer, validity 78etc. etc. If shortnames is true (the default) then the fields will be 79keyed by the shortname forms eg: CN as opposed to commonName (shortnames 80= false). 81 82 83bool openssl_x509_checkpurpose(mixed x509cert, int purpose, 84 array cainfo[, string untrustedfile]) 85 86Verifies if the certificate can be used for a specific purpose. 87Purpose can be one of the following values: 88 X509_PURPOSE_SSL_CLIENT 89 X509_PURPOSE_SSL_SERVER 90 X509_PURPOSE_NS_SSL_SERVER 91 X509_PURPOSE_SMIME_SIGN 92 X509_PURPOSE_SMIME_ENCRYPT 93 X509_PURPOSE_CRL_SIGN 94 X509_PURPOSE_ANY 95 96cainfo is an array of CA information (as mentioned above). 97untrusted file specifies a file containing a bunch of certs that 98are not trusted but may be useful in validating the certificate. 99 100 101resource openssl_read_x509(mixed cert) 102 103Parses the cert and returns a resource that can be used with the 104other openssl functions 105 106 107void openssl_free_x509(resource x509) 108 109Frees the resource given by the x509 resource identifier. 110Note that this function does not accept the extended cert specification 111syntax mentioned above, as it doesn't make sense in this case! 112 113 114PKCS7 (S/MIME) Sign/Verify/Encrypt/Decrypt Functions: 115----------------------------------------------------- 116 117These functions allow you to manipulate S/MIME messages! 118 119They are based on apps/smime.c from the openssl dist, so for information, 120see the documentation for openssl. 121 122You may pass in some flags that affect how these functions work using 123and array containing the following values: 124"detached", "nodetached", "text", "nointern", "noverify", "nochain", 125"nocerts", "noattr", "binary", "nosigs". 126The options correspond to the options of the same name for the 127"openssl smime" command (smime(1)). 128 129 130bool openssl_pkcs7_verify(string filename, array flags[, string signerscerts][, 131 array cainfo]) 132 133Verifies that the signature on the MIME message contained in the file 134named by filename is valid. If signerscerts is passed in, it holds the 135name of a file into which the certificates of those that signed the 136message will be stored. 137cainfo and flags are CA information and flag information as described 138above. 139 140 141bool openssl_pkcs7_encrypt(string infile, string outfile, array recipcerts, 142 array headers[, array flags]) 143 144Encrypts the MIME message contained in the file named by infile using 145the certificates held in recipcerts. The result is place in the file 146named outfile. 147recipcerts is an array of certificate identifiers representing the certs 148of the intended recipients of the message. 149headers is an array of headers to prepend to the message: they will 150not be included in the encoded section. 151flags is flag information as described above. 152Hint: you will want to put "To", "From", and "Subject" headers in headers. 153Headers can be either an assoc array keyed by header named, or can be 154and indexed array containing a single header line per value. 155The message will be encoded using a RC2-40 bit cipher. 156TODO: allow user to specify cipher. 157 158bool openssl_pkcs7_sign(string infile, string outfile, mixed signcert, mixed 159 signkey, array headers[, array flags][, string extracertsfilename]) 160 161Signs the MIME message contained in the file named by infile using the 162certificate and key pair identified by signcert/signkey. 163Signkey must be the private key corresponding to signcert. 164The result is placed in the file named by outfile. 165Headers and flags have the same effects as mentioned above. 166extracertsfilename names a file containing a bunch of additional certificates 167to include in the signature, in order to aid the recipient in verifying the 168message. 169 170 171bool openssl_pkcs7_decrypt(string infilename, string outfilename, mixed 172 recipcert, mixed recipkey) 173 174Decrypts the MIME message contained in the file named by infilename 175using the certificate and private key pair recipcert/recipkey. 176The descrypted result is placed in outfilename. 177TODO: add flags parameter, if needed? 178 179 180EVP Sign/Verify/Encrypt/Decrypt Functions: 181------------------------------------------ 182 183bool openssl_sign(string data, &string signature, mixed key) 184 185Uses key to create signature for data, returns true on success and false 186on failure. signature is passed by reference and contains the newly created 187signature on success. 188 189 190int openssl_verify(string data, string signature, mixed key) 191 192Uses key to verify that the signature is correct for the given data. 193Returns 1 if correct, 0 if incorrect, and -1 on error. 194 195 196int openssl_seal(string data, &string sealdata, &array ekeys, array pubkeys) 197 198Encrypts data using pubkeys, so that only owners of the respective private 199keys and ekeys can decrypt and read the data. Returns the length of the 200sealed data on success, else false. On success, sealdata and ekeys hold 201the sealed data and envelope keys. 202 203 204bool openssl_open(string data, &string opendata, string ekey, int privkey) 205 206Opens (decrypts) sealed data using a private key and the corresponding 207envelope key. Returns true on success and false on failure. On success, 208opendata will hold the descypted data. 209 210 211See below for more details on usage. Also feel free to mail me at 212venaas@php.net if you have questions. The OpenSSL documentation, 213especially the EVP documentation at 214http://www.openssl.org/docs/crypto/evp.html, might also be of help. 215 216 217HOWTO: 218 219To do anything you need a private key and a certificate containing the 220corresponding public key. This is similar to what you have using say an 221Apache webserver with OpenSSL. For testing you could try keys that come 222with OpenSSL, that's what the sample scripts below do. You can also get 223keys from some CA, or you can create them yourself. 224 225 226Creating private key 227 228To generate an unprotected 1024 bit RSA private key you can do 229 230 openssl genrsa -out /tmp/test.key 1024 231 232Private keys should be protected by a passphrase though. 233 234 235Creating a self signed certificate 236 237To generate a self signed certificate from the key that is valid for 238365 days, do 239 240 openssl req -new -key /tmp/test.key -out /tmp/test.crt -days 365 -x509 241 242 243Example usage 244 245These examples use keys that come with OpenSSL, you should perhaps test with 246those first. 247 248 249Seal and open 250 251 <?php 252 $data = "Follow the white rabbit"; 253 254 // Get certificate into a string 255 // this file comes with OpenSSL 0.9.6 256 $fp = fopen("/src/openssl-0.9.6/demos/maurice/cert.pem", "r"); 257 $cert = fread($fp, 8192); 258 fclose($fp); 259 // get public key from certificate 260 $pk1 = openssl_get_publickey($cert); 261 // $pk1 is an encryption key resource id if success, else false 262 // Repeat if want public keys for multiple parties 263 264 $fp = fopen("/src/openssl-0.9.6/demos/sign/cert.pem", "r"); 265 $cert = fread($fp, 8192); 266 fclose($fp); 267 $pk2 = openssl_get_publickey($cert); 268 269 // seal data, only owners of $pk1 and $pk2 can decrypt $sealed with keys 270 // $ekeys[0] and $ekeys[1] respectively. 271 openssl_seal($data, $sealed, $ekeys, array($pk1,$pk2)); 272 openssl_free_key($pk1); 273 openssl_free_key($pk2); 274 275 // now we try to decrypt data for one of the recipients 276 $fp = fopen("/src/openssl-0.9.6/demos/sign/key.pem", "r"); 277 // Get PEM coded key into $pkey 278 $pkey = fread($fp, 8192); 279 fclose($fp); 280 // $key will be resource id for unpacked $pkey 281 $key = openssl_get_privatekey($pkey); 282 283 openssl_open($sealed, $open, $ekeys[1], $key); 284 openssl_free_key($key); 285 echo "$open\n"; 286 ?> 287 288 289Sign and verify 290 291 <?php 292 $data = "Follow the white rabbit"; 293 294 // First we need to have a string containing the private key in PEM format 295 // this file comes with OpenSSL 0.9.6 296 $fp = fopen("/src/openssl-0.9.6/demos/sign/key.pem", "r"); 297 $pkey = fread($fp, 8192); 298 fclose($fp); 299 300 // get private key from the PEM format 301 // $key is an encr key resource id if success, else false 302 $key = openssl_get_privatekey($pkey); 303 304 // calculate signature 305 openssl_sign($data, $signature, $key); 306 openssl_free_key($key); 307 308 // recipient verifies signature 309 // read certificate 310 $fp = fopen("/src/openssl-0.9.6/demos/sign/cert.pem", "r"); 311 $cert = fread($fp, 8192); 312 fclose($fp); 313 314 // Get public key from the certificate 315 $pubkey = openssl_get_publickey($cert); 316 317 // state whether signature is okay or not 318 echo openssl_verify($data, $signature, $pubkey) == 1 ? "ok\n" : "bad\n"; 319 320 // free key 321 openssl_free_key($pubkey); 322 ?> 323