Using PKs C# to PHP

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

PHP
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

PHP
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 (40)

Leave a Reply