### RSACrypt   A last analyzed 2019-10-31 23:09 UTC

#### Complexity

 Total Complexity 37

#### Size/Duplication

 Total Lines 232 Duplicated Lines 0 %

#### Coupling/Cohesion

 Components 1 Dependencies 3

#### Importance

 Changes 0
Metric Value
wmc 37
lcom 1
cbo 3
dl 0
loc 232
rs 9.44
c 0
b 0
f 0

#### 13 Methods

Rating   Name   Duplication   Size   Complexity
A encrypt() 0 11 3
A decrypt() 0 11 3
A encryptWithRSA15() 0 22 3
A decryptWithRSA15() 0 19 5
A encryptWithRSAOAEP() 0 19 4
A decryptWithRSAOAEP() 0 19 4
A convertIntegerToOctetString() 0 9 2
A convertOctetStringToInteger() 0 4 1
A getRSAEP() 0 8 3
A getRSADP() 0 8 3
A getMGF1() 0 11 2
A encryptRSAESOAEP() 0 18 1
A getRSAESOAEP() 0 24 3
 1 ` \$key->getModulusLength() - 11) {` 65 ` throw new InvalidArgumentException('Message too long');` 66 ` }` 67 68 ` \$psLen = \$key->getModulusLength() - \$mLen - 3;` 69 ` \$ps = '';` 70 ` while (mb_strlen(\$ps, '8bit') !== \$psLen) {` 71 ` \$temp = random_bytes(\$psLen - mb_strlen(\$ps, '8bit'));` 72 ` \$temp = str_replace("\x00", '', \$temp);` 73 ` \$ps .= \$temp;` 74 ` }` 75 ` \$type = 2;` 76 ` \$data = \chr(0).\chr(\$type).\$ps.\chr(0).\$data;` 77 78 ` \$data = BigInteger::createFromBinaryString(\$data);` 79 ` \$c = self::getRSAEP(\$key, \$data);` 80 81 ` return self::convertIntegerToOctetString(\$c, \$key->getModulusLength());` 82 ` }` 83 84 ` public static function decryptWithRSA15(RSAKey \$key, string \$c): string` 85 ` {` 86 ` if (mb_strlen(\$c, '8bit') !== \$key->getModulusLength()) {` 87 ` throw new InvalidArgumentException('Unable to decrypt');` 88 ` }` 89 ` \$c = BigInteger::createFromBinaryString(\$c);` 90 ` \$m = self::getRSADP(\$key, \$c);` 91 ` \$em = self::convertIntegerToOctetString(\$m, \$key->getModulusLength());` 92 ` if (0 !== \ord(\$em[0]) || \ord(\$em[1]) > 2) {` 93 ` throw new InvalidArgumentException('Unable to decrypt');` 94 ` }` 95 ` \$ps = mb_substr(\$em, 2, (int) mb_strpos(\$em, \chr(0), 2, '8bit') - 2, '8bit');` 96 ` \$m = mb_substr(\$em, mb_strlen(\$ps, '8bit') + 3, null, '8bit');` 97 ` if (mb_strlen(\$ps, '8bit') < 8) {` 98 ` throw new InvalidArgumentException('Unable to decrypt');` 99 ` }` 100 101 ` return \$m;` 102 ` }` 103 104 ` /**` 105 ` * Encryption.` 106 ` */` 107 ` public static function encryptWithRSAOAEP(RSAKey \$key, string \$plaintext, string \$hash_algorithm): string` 108 ` {` 109 ` /** @var Hash \$hash */` 110 ` \$hash = Hash::\$hash_algorithm();` 111 ` \$length = \$key->getModulusLength() - 2 * \$hash->getLength() - 2;` 112 ` if (0 >= \$length) {` 113 ` throw new RuntimeException();` 114 ` }` 115 ` \$plaintext = mb_str_split(\$plaintext, \$length, '8bit');` 116 ` if (!\is_array(\$plaintext)) {` 117 ` throw new RuntimeException('Invalid payload');` 118 ` }` 119 ` \$ciphertext = '';` 120 ` foreach (\$plaintext as \$m) {` 121 ` \$ciphertext .= self::encryptRSAESOAEP(\$key, \$m, \$hash);` 122 ` }` 123 124 ` return \$ciphertext;` 125 ` }` 126 127 ` /**` 128 ` * Decryption.` 129 ` */` 130 ` public static function decryptWithRSAOAEP(RSAKey \$key, string \$ciphertext, string \$hash_algorithm): string` 131 ` {` 132 ` if (0 >= \$key->getModulusLength()) {` 133 ` throw new RuntimeException('Invalid modulus length');` 134 ` }` 135 ` \$hash = Hash::\$hash_algorithm();` 136 ` \$ciphertext = mb_str_split(\$ciphertext, \$key->getModulusLength(), '8bit');` 137 ` if (!\is_array(\$ciphertext)) {` 138 ` throw new RuntimeException('Invalid ciphertext');` 139 ` }` 140 ` \$ciphertext[\count(\$ciphertext) - 1] = str_pad(\$ciphertext[\count(\$ciphertext) - 1], \$key->getModulusLength(), \chr(0), STR_PAD_LEFT);` 141 ` \$plaintext = '';` 142 ` foreach (\$ciphertext as \$c) {` 143 ` \$temp = self::getRSAESOAEP(\$key, \$c, \$hash);` 144 ` \$plaintext .= \$temp;` 145 ` }` 146 147 ` return \$plaintext;` 148 ` }` 149 150 ` private static function convertIntegerToOctetString(BigInteger \$x, int \$xLen): string` 151 ` {` 152 ` \$x = \$x->toBytes();` 153 ` if (mb_strlen(\$x, '8bit') > \$xLen) {` 154 ` throw new RuntimeException('Invalid length.');` 155 ` }` 156 157 ` return str_pad(\$x, \$xLen, \chr(0), STR_PAD_LEFT);` 158 ` }` 159 160 ` /**` 161 ` * Octet-String-to-Integer primitive.` 162 ` */` 163 ` private static function convertOctetStringToInteger(string \$x): BigInteger` 164 ` {` 165 ` return BigInteger::createFromBinaryString(\$x);` 166 ` }` 167 168 ` /**` 169 ` * RSA EP.` 170 ` */` 171 ` private static function getRSAEP(RSAKey \$key, BigInteger \$m): BigInteger` 172 ` {` 173 ` if (\$m->compare(BigInteger::createFromDecimal(0)) < 0 || \$m->compare(\$key->getModulus()) > 0) {` 0 ignored issues – show Documentation introduced 2017-11-13 20:39 UTC by `\$key->getModulus()` is of type `object`, but the function expects a `object`. It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: ```function acceptsInteger(\$int) { } \$x = '123'; // string "123" // Instead of acceptsInteger(\$x); // we recommend to use acceptsInteger((integer) \$x); ``` Loading history... 174 ` throw new RuntimeException();` 175 ` }` 176 177 ` return RSAKey::exponentiate(\$key, \$m);` 0 ignored issues – show Documentation introduced 2017-11-25 22:04 UTC by `\$key` is of type `object`, but the function expects a `object`. It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: ```function acceptsInteger(\$int) { } \$x = '123'; // string "123" // Instead of acceptsInteger(\$x); // we recommend to use acceptsInteger((integer) \$x); ``` Loading history... 178 ` }` 179 180 ` /**` 181 ` * RSA DP.` 182 ` */` 183 ` private static function getRSADP(RSAKey \$key, BigInteger \$c): BigInteger` 184 ` {` 185 ` if (\$c->compare(BigInteger::createFromDecimal(0)) < 0 || \$c->compare(\$key->getModulus()) > 0) {` 0 ignored issues – show Documentation introduced 2017-11-13 20:39 UTC by `\$key->getModulus()` is of type `object`, but the function expects a `object`. It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: ```function acceptsInteger(\$int) { } \$x = '123'; // string "123" // Instead of acceptsInteger(\$x); // we recommend to use acceptsInteger((integer) \$x); ``` Loading history... 186 ` throw new RuntimeException();` 187 ` }` 188 189 ` return RSAKey::exponentiate(\$key, \$c);` 0 ignored issues – show Documentation introduced 2017-11-25 22:04 UTC by `\$key` is of type `object`, but the function expects a `object`. It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: ```function acceptsInteger(\$int) { } \$x = '123'; // string "123" // Instead of acceptsInteger(\$x); // we recommend to use acceptsInteger((integer) \$x); ``` Loading history... 190 ` }` 191 192 ` /**` 193 ` * MGF1.` 194 ` */` 195 ` private static function getMGF1(string \$mgfSeed, int \$maskLen, Hash \$mgfHash): string` 196 ` {` 197 ` \$t = '';` 198 ` \$count = ceil(\$maskLen / \$mgfHash->getLength());` 199 ` for (\$i = 0; \$i < \$count; ++\$i) {` 200 ` \$c = pack('N', \$i);` 201 ` \$t .= \$mgfHash->hash(\$mgfSeed.\$c);` 202 ` }` 203 204 ` return mb_substr(\$t, 0, \$maskLen, '8bit');` 205 ` }` 206 207 ` /**` 208 ` * RSAES-OAEP-ENCRYPT.` 209 ` */` 210 ` private static function encryptRSAESOAEP(RSAKey \$key, string \$m, Hash \$hash): string` 211 ` {` 212 ` \$mLen = mb_strlen(\$m, '8bit');` 213 ` \$lHash = \$hash->hash('');` 214 ` \$ps = str_repeat(\chr(0), \$key->getModulusLength() - \$mLen - 2 * \$hash->getLength() - 2);` 215 ` \$db = \$lHash.\$ps.\chr(1).\$m;` 216 ` \$seed = random_bytes(\$hash->getLength());` 217 ` \$dbMask = self::getMGF1(\$seed, \$key->getModulusLength() - \$hash->getLength() - 1, \$hash/*MGF*/);` 218 ` \$maskedDB = (string) (\$db ^ \$dbMask);` 219 ` \$seedMask = self::getMGF1(\$maskedDB, \$hash->getLength(), \$hash/*MGF*/);` 220 ` \$maskedSeed = \$seed ^ \$seedMask;` 221 ` \$em = \chr(0).\$maskedSeed.\$maskedDB;` 222 223 ` \$m = self::convertOctetStringToInteger(\$em);` 224 ` \$c = self::getRSAEP(\$key, \$m);` 225 226 ` return self::convertIntegerToOctetString(\$c, \$key->getModulusLength());` 227 ` }` 228 229 ` /**` 230 ` * RSAES-OAEP-DECRYPT.` 231 ` */` 232 ` private static function getRSAESOAEP(RSAKey \$key, string \$c, Hash \$hash): string` 233 ` {` 234 ` \$c = self::convertOctetStringToInteger(\$c);` 235 ` \$m = self::getRSADP(\$key, \$c);` 236 ` \$em = self::convertIntegerToOctetString(\$m, \$key->getModulusLength());` 237 ` \$lHash = \$hash->hash('');` 238 ` \$maskedSeed = mb_substr(\$em, 1, \$hash->getLength(), '8bit');` 239 ` \$maskedDB = mb_substr(\$em, \$hash->getLength() + 1, null, '8bit');` 240 ` \$seedMask = self::getMGF1(\$maskedDB, \$hash->getLength(), \$hash/*MGF*/);` 241 ` \$seed = (string) (\$maskedSeed ^ \$seedMask);` 242 ` \$dbMask = self::getMGF1(\$seed, \$key->getModulusLength() - \$hash->getLength() - 1, \$hash/*MGF*/);` 243 ` \$db = \$maskedDB ^ \$dbMask;` 244 ` \$lHash2 = mb_substr(\$db, 0, \$hash->getLength(), '8bit');` 245 ` \$m = mb_substr(\$db, \$hash->getLength(), null, '8bit');` 246 ` if (!hash_equals(\$lHash, \$lHash2)) {` 247 ` throw new RuntimeException();` 248 ` }` 249 ` \$m = ltrim(\$m, \chr(0));` 250 ` if (1 !== \ord(\$m[0])) {` 251 ` throw new RuntimeException();` 252 ` }` 253 254 ` return mb_substr(\$m, 1, null, '8bit');` 255 ` }` 256 `}` 257