Passed
Push — master ( 1c7137...b5ef5e )
by Pieter van der
03:26 queued 14s
created

OCRA_v1::_oath_truncate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 9
c 1
b 1
f 0
dl 0
loc 19
rs 9.9666
cc 2
nc 2
nop 2
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.
0 ignored issues
show
Bug introduced by
The type text 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...
44
     */
45
    private static function _hmac_sha1($crypto,
46
            $keyBytes,
47
            $text)
48
    {
49
         $hash = hash_hmac ($crypto, $text, $keyBytes);
50
         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
    private static function _hexStr2Bytes($hex){
61
        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
0 ignored issues
show
Bug introduced by
The type the 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...
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
    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
        $codeDigits = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $codeDigits is dead and can be removed.
Loading history...
94
        $crypto = "";
95
        $result = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
96
        $ocraSuiteLength = strlen($ocraSuite);
97
        $counterLength = 0;
98
        $questionLength = 0;
99
        $passwordLength = 0;
100
101
        $sessionInformationLength = 0;
102
        $timeStampLength = 0;
103
104
        if(stripos($ocraSuite, "sha1")!==false)
105
            $crypto = "sha1";
106
        if(stripos($ocraSuite, "sha256")!==false)
107
            $crypto = "sha256";
108
        if(stripos($ocraSuite, "sha512")!==false)
109
            $crypto = "sha512";
110
111
        // How many digits should we return
112
        $oS = substr($ocraSuite, strpos($ocraSuite, ":")+1, strpos($ocraSuite, ":", strpos($ocraSuite, ":")+1) -strpos($ocraSuite, ":")-1);
113
        $codeDigits = substr($oS, strrpos($oS, "-")+1);
114
        
115
        // The size of the byte array message to be encrypted
116
        // Counter
117
        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
        if(stripos($ocraSuite, ":q")!==false ||
125
                stripos($ocraSuite, "-q")!==false) {
126
            while(strlen($question) < 256)
127
                $question = $question . "0";
128
            $questionLength=128;
129
        }
130
131
        // Password
132
        if(stripos($ocraSuite, ":p")!==false ||
133
                stripos($ocraSuite, "-p") !==false) {
134
            while(strlen($password) < 40)
135
                $password = "0" . $password;
136
            $passwordLength=20;
137
        }
138
139
        // sessionInformation
140
        if(stripos($ocraSuite, ":s") !==false ||
141
                stripos($ocraSuite, "-s", strpos($ocraSuite, ":", strpos($ocraSuite, ":")+1)) !== false) {
142
            while(strlen($sessionInformation) < 128)
143
                $sessionInformation = "0" . $sessionInformation;
144
145
            $sessionInformationLength=64;
146
        }
147
             
148
        // TimeStamp
149
        if(stripos($ocraSuite, ":t") !==false ||
150
                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
        $msg = array_fill(0,$ocraSuiteLength+$counterLength+$questionLength+$passwordLength+$sessionInformationLength+$timeStampLength+1, 0);
159
                
160
        for($i=0;$i<strlen($ocraSuite);$i++) {
161
            $msg[$i] = $ocraSuite[$i];
162
        }
163
        
164
        // Delimiter
165
        $msg[strlen($ocraSuite)] = self::_hexStr2Bytes("0");
166
167
        // Put the bytes of "Counter" to the message
168
        // Input is HEX encoded
169
        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
        if($questionLength > 0 ) {
180
            $bArray = self::_hexStr2Bytes($question);
181
            for ($i=0;$i<strlen($bArray);$i++) {
182
                $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
        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
        if($sessionInformationLength > 0 ){
198
            $bArray = self::_hexStr2Bytes($sessionInformation);
199
            for ($i=0;$i<strlen($bArray);$i++) {
200
                $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
        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
        $byteKey = self::_hexStr2Bytes($key);
214
              
215
        $msg = implode("", $msg);
216
        
217
        $hash = self::_hmac_sha1($crypto, $byteKey, $msg);
218
        
219
        $result = self::_oath_truncate($hash, $codeDigits);
0 ignored issues
show
Bug Best Practice introduced by
The method OCRA_v1::_oath_truncate() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

219
        /** @scrutinizer ignore-call */ 
220
        $result = self::_oath_truncate($hash, $codeDigits);
Loading history...
220
             
221
        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
    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
        foreach(str_split($hash,2) as $hex)
231
        {
232
            $hmac_result[]=hexdec($hex);
233
        }
234
    
235
        // Find offset
236
        $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
            (($hmac_result[$offset+0] & 0x7f) << 24 ) |
242
            (($hmac_result[$offset+1] & 0xff) << 16 ) |
243
            (($hmac_result[$offset+2] & 0xff) << 8 ) |
244
            ($hmac_result[$offset+3] & 0xff)
245
        ) % pow(10,$length);
246
    }
247
    
248
}
249