-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServiceProvider
155 lines (129 loc) · 4.64 KB
/
ServiceProvider
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
<?php
//author: sgoettfert, bgoeschi
class ServiceProvider {
// the keys
private $idp_public_key = "";
private $sp_private_key = "";
// cryptographic attributes with default values
private $signature_mode = "RSA-SHA256";
private $encryption_mode = MCRYPT_RIJNDAEL_256;
private $block_mode = MCRYPT_MODE_CBC;
private $iv_start = 0;
private $iv_length = 32;
/**
* @summary
* method called by SP when user is not yet authenticated
* build nonce & return_url for redirect
* @param $return_url
* the url that should be called after the user has authenticated at the IDP
* @return array|bool
* 'nonce' => unencrypted nonce
* 'c_nonce' => encrypted nonce for passing
* 'c_return_url' => encrypted return url for passing
*
* return false on error
*/
function prepare_redirect($idp_public_key, $return_url) {
$this->set_public_key($idp_public_key);
$nonce = $this->build_nonce();
$c_url = $this->build_return_url($return_url);
if($nonce && $c_url) {
return array(
"nonce" => $nonce['nonce'],
"c_nonce" => $nonce['c_nonce'],
"c_return_url" => $c_url
);
} else {
return false;
}
}
/**
* @summary
* method called by SP after user has authenticated to IDP
* check authentication from IDP and get user infos
* @param $idp_public_key
* @param $sp_private_key
* @param $initial_nonce
* @param $c_nonce
* @param $c_user
* @param $signature
* @return bool|string
* json string which might contain user infos
* return false if authentication is not valid or error occurs
*/
function check_authentication($idp_public_key, $sp_private_key, $initial_nonce, $c_nonce, $c_user, $signature) {
$this->set_public_key($idp_public_key);
$this->set_private_key($sp_private_key);
$nonce = $this->set_nonce_from_cypher($c_nonce);
$return_value = false;
if($this->check_nonce($initial_nonce, $nonce)) {
$user_info = $this->set_user_from_cypher($c_user, $nonce);
if($this->check_user($user_info, $signature) == 1) {
$return_value = $user_info;
}
}
// return json string of user or false on error
return $return_value;
}
/*
* helper functions to set the cryptographic keys
*/
function set_private_key($key_stream) {
$this->sp_private_key = openssl_get_privatekey($key_stream);
}
function set_public_key($key_stream) {
$this->idp_public_key = openssl_get_publickey($key_stream);
}
/*
* helper functions for preparing the redirect to IDP
*/
function build_nonce() {
$nonce = bin2hex(openssl_random_pseudo_bytes(16));
openssl_public_encrypt($nonce, $c_nonce, $this->idp_public_key);
return array(
"nonce" => $nonce,
"c_nonce" => base64_encode($c_nonce)
);
}
function build_return_url($return_url) {
openssl_public_encrypt($return_url, $c_return_url, $this->idp_public_key);
return base64_encode($c_return_url);
}
/*
* helper functions to check authentication from IDP
*/
function set_nonce_from_cypher($c_nonce) {
openssl_private_decrypt(base64_decode($c_nonce), $nonce, $this->sp_private_key);
return $nonce;
}
function check_nonce($initial_nonce, $nonce) {
return $initial_nonce === $nonce;
}
function set_user_from_cypher($c_user, $nonce) {
$iv = substr(md5($nonce), $this->iv_start, $this->iv_length);
$user_info = mcrypt_decrypt($this->encryption_mode, $nonce, base64_decode($c_user), $this->block_mode, $iv);
// get rid of invisible characters
return preg_replace('/[\x00-\x1F]/', '', $user_info);
}
function check_user($user_info, $signature) {
return openssl_verify($user_info, base64_decode($signature), $this->idp_public_key, $this->signature_mode);
}
/*
* Setter for encryption configuration
*/
public function setSignatureMode($signature_mode) {
$this->signature_mode = $signature_mode;
}
public function setEncryptionMode($encryption_mode) {
$this->encryption_mode = $encryption_mode;
}
public function setBlockMode($block_mode) {
$this->block_mode = $block_mode;
}
public function setIvStart($iv_start) {
$this->iv_start = $iv_start;
}
public function setIvLength($iv_length) {
$this->iv_length = $iv_length;
}
}