/lib/SpotSeclibToOpenSsl.php
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
- <?php
- /*
- * Utility classe om RSA signatures te laten verifieeren door OpenSSL ipv
- * Crypt/RSA, dit is een keer of 100 sneller
- */
- class SpotSeclibToOpenSsl {
- /*
- * Geinitialiseerde public key cache gebruiken? Is enkel beschikbaar voor
- * de OpenSSL library
- */
- private $_pubKeyCache = array();
-
- function verify($rsaKey, $toCheck, $signature, $useCache) {
- if (isset($this->_pubKeyCache[$rsaKey['modulo'] . $rsaKey['exponent']])) {
- $openSslPubKey = $this->_pubKeyCache[$rsaKey['modulo'] . $rsaKey['exponent']];
- $verified = openssl_verify($toCheck, $signature, $openSslPubKey);
- } else {
- # Initialize the public key to verify with
- $pubKey['n'] = base64_decode($rsaKey['modulo']);
- $pubKey['e'] = base64_decode($rsaKey['exponent']);
-
- $openSslPubKey = openssl_get_publickey($this->seclibToOpenSsl($pubKey));
- $verified = openssl_verify($toCheck, $signature, $openSslPubKey);
-
- # Moeten we de resource cachen ipv vrijgeven?
- if ($useCache) {
- $this->_pubKeyCache[$rsaKey['modulo'] . $rsaKey['exponent']] = $openSslPubKey;
- } else {
- openssl_free_key($openSslPubKey);
- } # else
- } # else
-
- return $verified;
- } # verify
-
- function _getOidElementLength($component) {
- # Code copied from
- # http://chaosinmotion.com/wiki/index.php?title=ASN.1_Library
- if ($component < 0) return 10; // Full 64 bits takes 10*7 bits to encode
- $l = 1;
- for ($i = 1; $i < 9; ++$i) {
- $l <<= 7;
- if ($component < $l) break;
- }
- return $i;
- }
-
- function _encodeObjectId($vals) {
- $return = array();
-
- $return[] = 40 * $vals[0] + $vals[1];
- $valCount = count($vals);
- for($i = 2; $i < $valCount; $i++) {
- # Code copied from
- # http://chaosinmotion.com/wiki/index.php?title=ASN.1_Library
- $v = $vals[$i];
- $len = $this->_getOIDElementLength($v);
-
- for ($j = $len-1; $j > 0; --$j) {
- $m = 0x0080 | (0x007F & ($v >> ($j * 7)));
- $return[] = (int) $m;
- }
- $return[] = (int)(0x007F & $v);
- }
-
- return $return;
- } # _encodeObjectId
-
-
- function seclibToOpenSsl($pubKey) {
- /*
- * Structuur van de OpenSSL publickey is als volgt:
- *
- * - Sequence
- * +- Sequence
- * ++- Object identifier die de RSA key weergeeft (1.2.840.113549.1.1.1)
- * ++- NULL
- * +- Bit String
- * ++- Sequence
- * +++- Integer
- * +++- Integer
- *
- * Dit willen we nabootsen met deze encoding
- */
- $publicExponent = $pubKey['e'];
- $modulus = $pubKey['n'];
- $components = array(
- 'modulus' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus),
- 'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
- );
-
- /*
- * First encoden we de keys in een bitstring
- */
- $encodedKeys = pack('Ca*a*a*',
- CRYPT_RSA_ASN1_SEQUENCE, # Sequence
- $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
- $components['modulus'],
- $components['publicExponent']
- );
- $encodedKeys = pack('Ca*Ca*',
- 0x03, # 0x03 means BIT STRING
- $this->_encodeLength(strlen($encodedKeys) + 1), # add 1 voor de 0 unused bits
- 0,
- $encodedKeys
- );
-
- /*
- * Nu creeeren we de type header
- *
- * We kunnen de rsaIdentifier berekenen, maar omdat dat toch nooit verandert,
- * zetten we de berekening klaar.
- * Code om te berekenen:
- * $rsaIdentifier = $this->_encodeObjectId(array(1,2,840,113549,1,1,1)); // Magic value of RSA
- *
- * $encryptionType = pack('Ca*',
- * 0x06, # ASN.1 OBJECT IDENTIFIER
- * $this->_encodeLength(count($rsaIdentifier))
- * );
- * $rsaIdentifierCount = count($rsaIdentifier);
- * for($i = 0; $i < $rsaIdentifierCount; $i++) {
- * $encryptionType .= chr($rsaIdentifier[$i]);
- * } # foreach
- *
- *
- * # de encryption type header wordt geappend met een ASN.1 NULL
- * $encryptionType .= pack('CC',
- * 0x05, # ASN.1 NULL
- * 0
- * );
- *
- * # en de encryptiontype pakken we in in een sequence
- * $encryptionType = pack('Ca*a*',
- * CRYPT_RSA_ASN1_SEQUENCE, # Sequence
- * $this->_encodeLength(strlen($encryptionType)),
- * $encryptionType
- * );
- */
- $encryptionType = "\x30\xd\x6\x9\x2a\x86\x48\x86\xf7\xd\x1\x1\x1\x5\x0";
-
- # en ook dit alles pakken we in een sequence in
- $endResult = pack('Ca*a*',
- CRYPT_RSA_ASN1_SEQUENCE, # Sequence
- $this->_encodeLength(15 + strlen($encodedKeys)), # 15 == strlen($encryptionType)
- $encryptionType . $encodedKeys
- );
-
- return "-----BEGIN PUBLIC KEY-----\n" .
- chunk_split(base64_encode($endResult), 64) .
- "-----END PUBLIC KEY-----\n";
- } # seclibToOpenSsl
-
- /**
- *
- * From phpSeclib library
- *
- * DER-encode the length
- *
- * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
- * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 ?? 8.1.3} for more information.
- *
- * @access private
- * @param Integer $length
- * @return String
- */
- function _encodeLength($length)
- {
- if ($length <= 0x7F) {
- return chr($length);
- }
-
- $temp = ltrim(pack('N', $length), chr(0));
- return pack('Ca*', 0x80 | strlen($temp), $temp);
- }
-
- } # SpotSeclibToOpenSsl