PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/SpotSeclibToOpenSsl.php

http://github.com/spotweb/spotweb
PHP | 176 lines | 82 code | 18 blank | 76 comment | 10 complexity | c291d50487e343d9e380ee8006adeb29 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, Apache-2.0, LGPL-3.0
  1. <?php
  2. /*
  3. * Utility classe om RSA signatures te laten verifieeren door OpenSSL ipv
  4. * Crypt/RSA, dit is een keer of 100 sneller
  5. */
  6. class SpotSeclibToOpenSsl {
  7. /*
  8. * Geinitialiseerde public key cache gebruiken? Is enkel beschikbaar voor
  9. * de OpenSSL library
  10. */
  11. private $_pubKeyCache = array();
  12. function verify($rsaKey, $toCheck, $signature, $useCache) {
  13. if (isset($this->_pubKeyCache[$rsaKey['modulo'] . $rsaKey['exponent']])) {
  14. $openSslPubKey = $this->_pubKeyCache[$rsaKey['modulo'] . $rsaKey['exponent']];
  15. $verified = openssl_verify($toCheck, $signature, $openSslPubKey);
  16. } else {
  17. # Initialize the public key to verify with
  18. $pubKey['n'] = base64_decode($rsaKey['modulo']);
  19. $pubKey['e'] = base64_decode($rsaKey['exponent']);
  20. $openSslPubKey = openssl_get_publickey($this->seclibToOpenSsl($pubKey));
  21. $verified = openssl_verify($toCheck, $signature, $openSslPubKey);
  22. # Moeten we de resource cachen ipv vrijgeven?
  23. if ($useCache) {
  24. $this->_pubKeyCache[$rsaKey['modulo'] . $rsaKey['exponent']] = $openSslPubKey;
  25. } else {
  26. openssl_free_key($openSslPubKey);
  27. } # else
  28. } # else
  29. return $verified;
  30. } # verify
  31. function _getOidElementLength($component) {
  32. # Code copied from
  33. # http://chaosinmotion.com/wiki/index.php?title=ASN.1_Library
  34. if ($component < 0) return 10; // Full 64 bits takes 10*7 bits to encode
  35. $l = 1;
  36. for ($i = 1; $i < 9; ++$i) {
  37. $l <<= 7;
  38. if ($component < $l) break;
  39. }
  40. return $i;
  41. }
  42. function _encodeObjectId($vals) {
  43. $return = array();
  44. $return[] = 40 * $vals[0] + $vals[1];
  45. $valCount = count($vals);
  46. for($i = 2; $i < $valCount; $i++) {
  47. # Code copied from
  48. # http://chaosinmotion.com/wiki/index.php?title=ASN.1_Library
  49. $v = $vals[$i];
  50. $len = $this->_getOIDElementLength($v);
  51. for ($j = $len-1; $j > 0; --$j) {
  52. $m = 0x0080 | (0x007F & ($v >> ($j * 7)));
  53. $return[] = (int) $m;
  54. }
  55. $return[] = (int)(0x007F & $v);
  56. }
  57. return $return;
  58. } # _encodeObjectId
  59. function seclibToOpenSsl($pubKey) {
  60. /*
  61. * Structuur van de OpenSSL publickey is als volgt:
  62. *
  63. * - Sequence
  64. * +- Sequence
  65. * ++- Object identifier die de RSA key weergeeft (1.2.840.113549.1.1.1)
  66. * ++- NULL
  67. * +- Bit String
  68. * ++- Sequence
  69. * +++- Integer
  70. * +++- Integer
  71. *
  72. * Dit willen we nabootsen met deze encoding
  73. */
  74. $publicExponent = $pubKey['e'];
  75. $modulus = $pubKey['n'];
  76. $components = array(
  77. 'modulus' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus),
  78. 'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
  79. );
  80. /*
  81. * First encoden we de keys in een bitstring
  82. */
  83. $encodedKeys = pack('Ca*a*a*',
  84. CRYPT_RSA_ASN1_SEQUENCE, # Sequence
  85. $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
  86. $components['modulus'],
  87. $components['publicExponent']
  88. );
  89. $encodedKeys = pack('Ca*Ca*',
  90. 0x03, # 0x03 means BIT STRING
  91. $this->_encodeLength(strlen($encodedKeys) + 1), # add 1 voor de 0 unused bits
  92. 0,
  93. $encodedKeys
  94. );
  95. /*
  96. * Nu creeeren we de type header
  97. *
  98. * We kunnen de rsaIdentifier berekenen, maar omdat dat toch nooit verandert,
  99. * zetten we de berekening klaar.
  100. * Code om te berekenen:
  101. * $rsaIdentifier = $this->_encodeObjectId(array(1,2,840,113549,1,1,1)); // Magic value of RSA
  102. *
  103. * $encryptionType = pack('Ca*',
  104. * 0x06, # ASN.1 OBJECT IDENTIFIER
  105. * $this->_encodeLength(count($rsaIdentifier))
  106. * );
  107. * $rsaIdentifierCount = count($rsaIdentifier);
  108. * for($i = 0; $i < $rsaIdentifierCount; $i++) {
  109. * $encryptionType .= chr($rsaIdentifier[$i]);
  110. * } # foreach
  111. *
  112. *
  113. * # de encryption type header wordt geappend met een ASN.1 NULL
  114. * $encryptionType .= pack('CC',
  115. * 0x05, # ASN.1 NULL
  116. * 0
  117. * );
  118. *
  119. * # en de encryptiontype pakken we in in een sequence
  120. * $encryptionType = pack('Ca*a*',
  121. * CRYPT_RSA_ASN1_SEQUENCE, # Sequence
  122. * $this->_encodeLength(strlen($encryptionType)),
  123. * $encryptionType
  124. * );
  125. */
  126. $encryptionType = "\x30\xd\x6\x9\x2a\x86\x48\x86\xf7\xd\x1\x1\x1\x5\x0";
  127. # en ook dit alles pakken we in een sequence in
  128. $endResult = pack('Ca*a*',
  129. CRYPT_RSA_ASN1_SEQUENCE, # Sequence
  130. $this->_encodeLength(15 + strlen($encodedKeys)), # 15 == strlen($encryptionType)
  131. $encryptionType . $encodedKeys
  132. );
  133. return "-----BEGIN PUBLIC KEY-----\n" .
  134. chunk_split(base64_encode($endResult), 64) .
  135. "-----END PUBLIC KEY-----\n";
  136. } # seclibToOpenSsl
  137. /**
  138. *
  139. * From phpSeclib library
  140. *
  141. * DER-encode the length
  142. *
  143. * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
  144. * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 ?? 8.1.3} for more information.
  145. *
  146. * @access private
  147. * @param Integer $length
  148. * @return String
  149. */
  150. function _encodeLength($length)
  151. {
  152. if ($length <= 0x7F) {
  153. return chr($length);
  154. }
  155. $temp = ltrim(pack('N', $length), chr(0));
  156. return pack('Ca*', 0x80 | strlen($temp), $temp);
  157. }
  158. } # SpotSeclibToOpenSsl