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