Passed
Push — develop ( 22eefe...e65dcd )
by Pieter van der
06:04
created

OCRA_v1   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Test Coverage

Coverage 74.71%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 34
eloc 83
c 1
b 1
f 0
dl 0
loc 217
ccs 65
cts 87
cp 0.7471
rs 9.68

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 1 1
A _hexStr2Bytes() 0 2 1
A _oath_truncate() 0 19 2
F generateOCRA() 0 137 29
A _hmac_sha1() 0 6 1
1
<?php 
2
/**
3
 * This file is part of the tiqr project.
4
 * 
5
 * The tiqr project aims to provide an open implementation for 
6
 * authentication using mobile devices. It was initiated by 
7
 * SURFnet and developed by Egeniq.
8
 *
9
 * More information: http://www.tiqr.org
10
 *
11
 * @author Ivo Jansch <[email protected]>
12
 * 
13
 * @package tiqr
14
 *
15
 * @license New BSD License - See LICENSE file for details.
16
 *
17
 * @copyright (C) 2010-2011 SURFnet BV
18
 */
19
20
21
/**
22
 * This a PHP port of the example implementation of the 
23
 * OATH OCRA algorithm.
24
 * Visit www.openauthentication.org for more information.
25
 *
26
 * @author Johan Rydell, PortWise (original Java)
27
 * @author Ivo Jansch, Egeniq (PHP port)
28
 */
29
class OCRA_v1 {
30
31
    private function __construct() {
32
        
33
    }
34
35
    /**
36
     * This method uses the hmac_hash function to provide the crypto
37
     * algorithm.
38
     * HMAC computes a Hashed Message Authentication Code with the
39
     * crypto hash algorithm as a parameter.
40
     *
41
     * @param String crypto     the crypto algorithm (sha1, sha256 or sha512)
42
     * @param String keyBytes   the bytes to use for the HMAC key
43
     * @param String text       the message or text to be authenticated.
44
     */
45 2
    private static function _hmac_sha1($crypto,
46
            $keyBytes,
47
            $text)
48
    {
49 2
         $hash = hash_hmac ($crypto, $text, $keyBytes);
50 2
         return $hash;
51
    }
52
53
    /**
54
     * This method converts HEX string to Byte[]
55
     *
56
     * @param String hex   the HEX string
0 ignored issues
show
Bug introduced by
The type hex was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
57
     *
58
     * @return String a string with raw bytes
59
     */
60 2
    private static function _hexStr2Bytes($hex){
61 2
        return pack("H*", $hex);
62
    }
63
64
65
    /**
66
     * This method generates an OCRA HOTP value for the given
67
     * set of parameters.
68
     *
69
     * @param ocraSuite    the OCRA Suite
70
     * @param key          the shared secret, HEX encoded
71
     * @param counter      the counter that changes
72
     *                     on a per use basis,
73
     *                     HEX encoded
74
     * @param question     the challenge question, HEX encoded
75
     * @param password     a password that can be used,
76
     *                     HEX encoded
77
     * @param sessionInformation
78
     *                     Static information that identifies the
79
     *                     current session, Hex encoded
80
     * @param timeStamp    a value that reflects a time
81
     *
82
     * @return A numeric String in base 10 that includes
83
     * {@link truncationDigits} digits
84
     */
85 2
    static function generateOCRA($ocraSuite,
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
86
                                 $key,
87
                                 $counter,
88
                                 $question,
89
                                 $password,
90
                                 $sessionInformation,
91
                                 $timeStamp)
92
    {
93 2
        $codeDigits = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $codeDigits is dead and can be removed.
Loading history...
94 2
        $crypto = "";
95 2
        $result = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
96 2
        $ocraSuiteLength = strlen($ocraSuite);
97 2
        $counterLength = 0;
98 2
        $questionLength = 0;
99 2
        $passwordLength = 0;
100
101 2
        $sessionInformationLength = 0;
102 2
        $timeStampLength = 0;
103
104 2
        if(stripos($ocraSuite, "sha1")!==false)
105 2
            $crypto = "sha1";
106 2
        if(stripos($ocraSuite, "sha256")!==false)
107
            $crypto = "sha256";
108 2
        if(stripos($ocraSuite, "sha512")!==false)
109
            $crypto = "sha512";
110
111
        // How many digits should we return
112 2
        $oS = substr($ocraSuite, strpos($ocraSuite, ":")+1, strpos($ocraSuite, ":", strpos($ocraSuite, ":")+1) -strpos($ocraSuite, ":")-1);
113 2
        $codeDigits = substr($oS, strrpos($oS, "-")+1);
114
        
115
        // The size of the byte array message to be encrypted
116
        // Counter
117 2
        if(stripos($ocraSuite, ":c") !==false) {
118
            // Fix the length of the HEX string
119
            while(strlen($counter) < 16)
120
                $counter = "0" . $counter;
121
            $counterLength=8;
122
        }
123
        // Question
124 2
        if(stripos($ocraSuite, ":q")!==false ||
125 2
                stripos($ocraSuite, "-q")!==false) {
126 2
            while(strlen($question) < 256)
127 2
                $question = $question . "0";
128 2
            $questionLength=128;
129
        }
130
131
        // Password
132 2
        if(stripos($ocraSuite, ":p")!==false ||
133 2
                stripos($ocraSuite, "-p") !==false) {
134
            while(strlen($password) < 40)
135
                $password = "0" . $password;
136
            $passwordLength=20;
137
        }
138
139
        // sessionInformation
140 2
        if(stripos($ocraSuite, ":s") !==false ||
141 2
                stripos($ocraSuite, "-s", strpos($ocraSuite, ":", strpos($ocraSuite, ":")+1)) !== false) {
142 2
            while(strlen($sessionInformation) < 128)
143 2
                $sessionInformation = "0" . $sessionInformation;
144
145 2
            $sessionInformationLength=64;
146
        }
147
             
148
        // TimeStamp
149 2
        if(stripos($ocraSuite, ":t") !==false ||
150 2
                stripos($ocraSuite, "-t") !== false) {
151
            while(strlen($timeStamp) < 16)
152
                $timeStamp = "0" . $timeStamp;
153
            $timeStampLength=8;
154
        }
155
156
        // Put the bytes of "ocraSuite" parameters into the message
157
        
158 2
        $msg = array_fill(0,$ocraSuiteLength+$counterLength+$questionLength+$passwordLength+$sessionInformationLength+$timeStampLength+1, 0);
159
                
160 2
        for($i=0;$i<strlen($ocraSuite);$i++) {
161 2
            $msg[$i] = $ocraSuite[$i];
162
        }
163
        
164
        // Delimiter
165 2
        $msg[strlen($ocraSuite)] = self::_hexStr2Bytes("0");
166
167
        // Put the bytes of "Counter" to the message
168
        // Input is HEX encoded
169 2
        if($counterLength > 0 ) {
170
            $bArray = self::_hexStr2Bytes($counter);
171
            for ($i=0;$i<strlen($bArray);$i++) {
172
                $msg [$i + $ocraSuiteLength + 1] = $bArray[$i];
173
            }
174
        }
175
176
177
        // Put the bytes of "question" to the message
178
        // Input is text encoded
179 2
        if($questionLength > 0 ) {
180 2
            $bArray = self::_hexStr2Bytes($question);
181 2
            for ($i=0;$i<strlen($bArray);$i++) {
182 2
                $msg [$i + $ocraSuiteLength + 1 + $counterLength] = $bArray[$i];
183
            }
184
        }
185
186
        // Put the bytes of "password" to the message
187
        // Input is HEX encoded
188 2
        if($passwordLength > 0){
189
            $bArray = self::_hexStr2Bytes($password);
190
            for ($i=0;$i<strlen($bArray);$i++) {
191
                $msg [$i + $ocraSuiteLength + 1 + $counterLength + $questionLength] = $bArray[$i];
192
            }
193
        }
194
195
        // Put the bytes of "sessionInformation" to the message
196
        // Input is text encoded
197 2
        if($sessionInformationLength > 0 ){
198 2
            $bArray = self::_hexStr2Bytes($sessionInformation);
199 2
            for ($i=0;$i<strlen($bArray);$i++) {
200 2
                $msg [$i + $ocraSuiteLength + 1 + $counterLength + $questionLength + $passwordLength] = $bArray[$i];
201
            }
202
        }
203
204
        // Put the bytes of "time" to the message
205
        // Input is text value of minutes
206 2
        if($timeStampLength > 0){
207
            $bArray = self::_hexStr2Bytes($timestamp);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $timestamp does not exist. Did you maybe mean $timeStamp?
Loading history...
208
            for ($i=0;$i<strlen($bArray);$i++) {
209
                $msg [$i + $ocraSuiteLength + 1 + $counterLength + $questionLength + $passwordLength + $sessionInformationLength] = $bArray[$i];
210
            }
211
        }
212
        
213 2
        $byteKey = self::_hexStr2Bytes($key);
214
              
215 2
        $msg = implode("", $msg);
216
        
217 2
        $hash = self::_hmac_sha1($crypto, $byteKey, $msg);
218
        
219 2
        $result = self::_oath_truncate($hash, $codeDigits);
220
             
221 2
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type integer which is incompatible with the documented return type A.
Loading history...
222
    }
223
224
    /**
225
     * Truncate a result to a certain length
226
     */    
227 2
    static function _oath_truncate($hash, $length = 6)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
228
    {
229
        // Convert to dec
230 2
        foreach(str_split($hash,2) as $hex)
231
        {
232 2
            $hmac_result[]=hexdec($hex);
233
        }
234
    
235
        // Find offset
236 2
        $offset = $hmac_result[19] & 0xf;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hmac_result seems to be defined by a foreach iteration on line 230. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
237
    
238
        // Algorithm from RFC
239
        return
240
        (
241 2
            (($hmac_result[$offset+0] & 0x7f) << 24 ) |
242 2
            (($hmac_result[$offset+1] & 0xff) << 16 ) |
243 2
            (($hmac_result[$offset+2] & 0xff) << 8 ) |
244 2
            ($hmac_result[$offset+3] & 0xff)
245 2
        ) % pow(10,$length);
246
    }
247
    
248
}
249