So lately I’ve been seeing more and more C# application talking to the web, web interaction and applications is something that can be beneficial to both the end user and the developer making a plethora of things simpler and streamlined. However while talking two and from you application one needs to make sure the information is secure at all times.
There are several methods to doing this, and one way is using public, private key-pair cryptography. In the example below I’ve shown a PHP script that is able to talk to a C# application using an openssl public, private key-pair.
In this post I’ve included the source to everything in a .rar file listed for download at the bottom.
Openssl Class
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
<?php
/**
******************************************************************************************
* OpenSSL * synmuffin *
******************************************************************************************
*
* OpenSSL class that was designed to work with C/C++/C# applications. This class allows
* users who want to build a secure API to Rx/Tx data from the web (website or server)
* through to their end users application.
*
*
* author: synmuffin
* email: synmuffin@savelab.net
* version: 1.0
* date:
*
*/
class OpenSSL {
/*
|================================================================================
| PUBLIC VARS
|================================================================================
*/
/*
|================================================================================
| PRIVATE VARS
|================================================================================
*/
/**
* $publicKey
* Public key instance used throughout the class. This must be initialized via the
* LoadPublicKey() function.
*/
private $publicKey = NULL;
/**
* $privateKey
* Private key instance used throughout the class. This must be initialized via the
* LoadPrivateKey() function.
*/
private $privateKey = NULL;
/**
* $padding
* Padding, currently not in use as it seems to not work.
*/
private $padding = NULL; // OPENSSL_PKCS1_PADDING, OPENSSL_SSLV23_PADDING, OPENSSL_PKCS1_OAEP_PADDING, OPENSSL_NO_PADDING.
/**
* Class constructor, currently no paramaters are needed.
*/
public function __construct($params = FALSE)
{
if (!$params)
return;
if (array_key_exists('public_key', $params))
{
if (file_exists($params['public_key']))
$this->LoadPublicKey($params['public_key']);
else
trigger_error("Unable to find Public key file {$params['public_key']}.", E_USER_ERROR);
}
if (array_key_exists('private_key', $params))
{
if (file_exists($params['private_key']))
$this->LoadPrivateKey($params['private_key']);
else
trigger_error("Unable to find Private key file {$params['private_key']}.", E_USER_ERROR);
}
}
// ---------------------------------------------------------------------
/*
|================================================================================
| PUBLIC FUNCTIONS
|================================================================================
*/
/**
* public LoadPrivateKey(string $privkey_path [, string $privkey_pass])
*
* Function will load a private key via the passed string file location of $privkey_path. This fucntion also
* takes and optional second paramter that will allow for private keys locked with a DES passphrase to be used.
*
* @param string $privkey_path - Path to the private key file.
* @param string $privkey_pass - Private key passphrase.
*
* @return none
*/
public function LoadPrivateKey($privkey_path, $privkey_pass = FALSE)
{
if (!$privkey_pass || $privkey_pass == NULL)
{
if (!($this->privateKey = openssl_get_privatekey('file://' . $privkey_path)))
trigger_error("Unable to load private key from file {$privkey_path}.", E_USER_ERROR);
}
else
{
if (!($this->privateKey = openssl_get_privatekey('file://' . $privkey_path, $privkey_pass)))
trigger_error("Unable to load private key from file {$privkey_path}.", E_USER_ERROR);
}
}
// ---------------------------------------------------------------------
/**
* public LoadPublicKey(string $pubkey_path)
*
* Function will load a public key via the passed string file location of $pubkey_path.
*
* @param string $pubkey_path - Path to public key file.
*
* @return none
*/
public function LoadPublicKey($pubkey_path)
{
if (!($this->publicKey = openssl_get_publickey('file://' . $pubkey_path)))
trigger_error("Unable to load public key from file {$pubkey_path}.", E_USER_ERROR);
}
// ---------------------------------------------------------------------
/**
* public PrivateKeyEncrypt(string $raw_data [, bool $base64 = TRUE])
*
* Function will try and encrypte the passed string $raw_data using the loaded (hopefully) $this->privateKey
* resource. This function also takes an optional second paramter allowing the user to spepcified if they wish
* to have the encrypted data returned base64 encoded, be default this is set to true.
*
* @param string $raw_data - Raw data to be encrypted.
* @param bool $base64 - Bool value to return data base64 encoded.
*
* @return string $encrypted_data
*/
public function PrivateKeyEncrypt($raw_data, $base64 = TRUE)
{
if ($this->privateKey == NULL)
trigger_error("Private key has not been sepcified.", E_USER_ERROR);
if (!openssl_private_encrypt($raw_data, $encrypted_data, $this->privateKey))
trigger_error("Unable to encrypt data.", E_USER_ERROR);
return ($base64) ? base64_encode($encrypted_data) : $encrypted_data;
}
// ---------------------------------------------------------------------
/**
* public PrivateKeyDecrypt(string $raw_data [, bool $base64 = TRUE])
*
* Function will try and decrypt the passed $raw_data using the loaded (hopefully) $this->privateKey resource. This
* function, much like it's counter-part, takes an optional second paramter specifiing whether or not the $raw_data
* is base64 encoded. By default is assumes it is.
*
* @param string $raw_data - Raw data to be decrypted.
* @param bool $base64 - Bool value to assume $raw_data is base64 encoded.
*
* @return string $decrypted_data
*/
public function PrivateKeyDecrypt($raw_data, $base64 = TRUE)
{
if ($this->privateKey == NULL)
trigger_error("Private key has not been specified.", E_USER_ERROR);
if (!openssl_private_decrypt(($base64) ? base64_decode($raw_data) : $raw_data, $decrypted_data, $this->privateKey, $this->padding))
trigger_error("Unable to decrypt data.", E_USER_ERROR);
return $decrypted_data;
}
// ---------------------------------------------------------------------
/**
* public PublicKeyEncrypt(string $raw_data [, bool $base64 = TRUE])
*
* Function will try and encrypte the passed string $raw_data using the loaded (hopefully) $this->publicKey
* resource. This function also takes an optional second paramter allowing the user to spepcified if they wish
* to have the encrypted data returned base64 encoded, be default this is set to true.
*
* @param string $raw_data - Raw data to be encrypted.
* @param bool $base64 - Bool value to return data base64 encoded.
*
* @return string $encrypted_data
*/
public function PublicKeyEncrypt($raw_data, $base64 = TRUE)
{
if ($this->publicKey == NULL)
trigger_error("Public key has not been specified.", E_USER_ERROR);
if (!openssl_public_encrypt($raw_data, $encrypted_data, $this->publicKey))
trigger_error("Unable to encrypt data.", E_USER_ERROR);
return ($base64) ? base64_encode($encrypted_data) : $encrypted_data;
}
// ---------------------------------------------------------------------
/**
* public PublicKeyDecrypt(string $raw_data [, bool $base64 = TRUE])
*
* Function will try and decrypt the passed $raw_data using the loaded (hopefully) $this->privateKey resource. This
* function, much like it's counter-part, takes an optional second paramter specifiing whether or not the $raw_data
* is base64 encoded. By default is assumes it is.
*
* @param string $raw_data - Raw data to be decrypted.
* @param bool $base64 - Bool value to assume $raw_data is base64 encoded.
*
* @return string $decrypted_data
*/
public function PublicKeyDecrypt($raw_data, $base64 = TRUE)
{
if ($this->publicKey == NULL)
trigger_error("Public key has not been specified.", E_USER_ERROR);
if (!openssl_public_decrypt(($base64) ? base64_decode($raw_data) : $raw_data, $decrypted_data, $this->publicKey))
trigger_error("Unable to decrypt data.", E_USER_ERROR);
return $decrypted_data;
}
// ---------------------------------------------------------------------
/*
|================================================================================
| PRIVATE FUNCTIONS
|================================================================================
*/
}
?> |
Web usage example
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php
// include the lib
require_once('../lib/OpenSSL.php');
// now to keep this nice and secure this should always be done and called
// over a a HTTPS layer for added security. However in this example I've provided
// a way to turn this check off just in case you want to run soem quick http tests.
//
// Simply comment out the next two lines if you wish to run http NOT https.
if ($_SERVER['HTTPS'] != 'on')
exit("You should use HTTPS not HTTP.");
// in this example I'm going to use the $raw_data variable and just stick some text data in it,
// however in a RWS this would be sensitive data that I've returned via a call or check from
// a database or something along those lines.
//
// More to the point I want to pass something back to my application here, as encrypted data.
$raw_data = "This is my data that I want to keep a secret!";
// next we init our class
$ssl = new OpenSSL();
// load our private key
$ssl->LoadPrivateKey('/home/your/path/to/privatekey.key');
// now we can encrypt our data (provided the key was valid)
// note: with default optiosn like this it will return the data base64 encoded
$encrypted_data = $ssl->PrivateKeyEncrypt($raw_data);
// now we are just going to print this data (assuming this was our C# app that made this call)
// we print the data right to output buffer, so we can use things like HTTP_GET requests.
print $encrypted_data;
?> |
Using the above example in conjunction with the C# application you can demo how this would work. Download the attached file to get a copy of all .php files as well as a full C# application.
PHP to C# Example (238)