From 9495614038b65ca1272d5be2d2bea80b8a5b5d75 Mon Sep 17 00:00:00 2001 From: Yagami Date: Wed, 24 Oct 2018 09:52:56 +0800 Subject: [PATCH] * Delete xuanxuan file. --- config/ext/xuanxuan.php | 43 - db/xuanxuan.sql | 76 - framework/xuanxuan.class.php | 353 -- lib/phpaes/phpaes.class.php | 47 - .../phpseclib/Common/Functions/Objects.php | 75 - .../phpseclib/Common/Functions/Strings.php | 228 - lib/phpaes/phpseclib/Crypt/AES.php | 135 - lib/phpaes/phpseclib/Crypt/Blowfish.php | 559 --- .../phpseclib/Crypt/Common/AsymmetricKey.php | 660 --- .../phpseclib/Crypt/Common/BlockCipher.php | 28 - .../phpseclib/Crypt/Common/Keys/OpenSSH.php | 139 - .../phpseclib/Crypt/Common/Keys/PKCS.php | 80 - .../phpseclib/Crypt/Common/Keys/PKCS1.php | 224 - .../phpseclib/Crypt/Common/Keys/PKCS8.php | 609 --- .../phpseclib/Crypt/Common/Keys/PuTTY.php | 230 - .../phpseclib/Crypt/Common/Signature/Raw.php | 67 - .../phpseclib/Crypt/Common/StreamCipher.php | 27 - .../phpseclib/Crypt/Common/SymmetricKey.php | 2588 ---------- lib/phpaes/phpseclib/Crypt/DES.php | 1408 ------ lib/phpaes/phpseclib/Crypt/DSA.php | 500 -- .../phpseclib/Crypt/DSA/Keys/OpenSSH.php | 92 - lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS1.php | 149 - lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS8.php | 169 - lib/phpaes/phpseclib/Crypt/DSA/Keys/PuTTY.php | 129 - lib/phpaes/phpseclib/Crypt/DSA/Keys/Raw.php | 95 - lib/phpaes/phpseclib/Crypt/DSA/Keys/XML.php | 129 - .../phpseclib/Crypt/DSA/Signature/PKCS.php | 68 - .../phpseclib/Crypt/DSA/Signature/Raw.php | 29 - .../phpseclib/Crypt/DSA/Signature/SSH2.php | 75 - lib/phpaes/phpseclib/Crypt/Hash.php | 483 -- lib/phpaes/phpseclib/Crypt/RC2.php | 665 --- lib/phpaes/phpseclib/Crypt/RC4.php | 332 -- lib/phpaes/phpseclib/Crypt/RSA.php | 1765 ------- .../phpseclib/Crypt/RSA/Keys/MSBLOB.php | 213 - .../phpseclib/Crypt/RSA/Keys/OpenSSH.php | 83 - lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS1.php | 151 - lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS8.php | 133 - lib/phpaes/phpseclib/Crypt/RSA/Keys/PuTTY.php | 129 - lib/phpaes/phpseclib/Crypt/RSA/Keys/Raw.php | 104 - lib/phpaes/phpseclib/Crypt/RSA/Keys/XML.php | 148 - lib/phpaes/phpseclib/Crypt/Random.php | 222 - lib/phpaes/phpseclib/Crypt/Rijndael.php | 938 ---- lib/phpaes/phpseclib/Crypt/TripleDES.php | 459 -- lib/phpaes/phpseclib/Crypt/Twofish.php | 817 --- .../Exception/BadConfigurationException.php | 26 - .../Exception/FileNotFoundException.php | 26 - .../NoSupportedAlgorithmsException.php | 26 - .../UnsupportedAlgorithmException.php | 26 - lib/phpaes/phpseclib/File/ANSI.php | 574 --- lib/phpaes/phpseclib/File/ASN1.php | 1414 ------ lib/phpaes/phpseclib/File/ASN1/Element.php | 49 - .../File/ASN1/Maps/AccessDescription.php | 36 - .../ASN1/Maps/AdministrationDomainName.php | 40 - .../File/ASN1/Maps/AlgorithmIdentifier.php | 39 - .../phpseclib/File/ASN1/Maps/AnotherName.php | 41 - .../phpseclib/File/ASN1/Maps/Attribute.php | 41 - .../File/ASN1/Maps/AttributeType.php | 30 - .../File/ASN1/Maps/AttributeTypeAndValue.php | 36 - .../File/ASN1/Maps/AttributeValue.php | 30 - .../phpseclib/File/ASN1/Maps/Attributes.php | 35 - .../ASN1/Maps/AuthorityInfoAccessSyntax.php | 35 - .../File/ASN1/Maps/AuthorityKeyIdentifier.php | 49 - .../phpseclib/File/ASN1/Maps/BaseDistance.php | 30 - .../File/ASN1/Maps/BasicConstraints.php | 43 - .../Maps/BuiltInDomainDefinedAttribute.php | 36 - .../Maps/BuiltInDomainDefinedAttributes.php | 35 - .../ASN1/Maps/BuiltInStandardAttributes.php | 71 - .../phpseclib/File/ASN1/Maps/CPSuri.php | 30 - .../File/ASN1/Maps/CRLDistributionPoints.php | 35 - .../phpseclib/File/ASN1/Maps/CRLNumber.php | 30 - .../phpseclib/File/ASN1/Maps/CRLReason.php | 45 - .../phpseclib/File/ASN1/Maps/CertPolicyId.php | 30 - .../phpseclib/File/ASN1/Maps/Certificate.php | 37 - .../File/ASN1/Maps/CertificateIssuer.php | 30 - .../File/ASN1/Maps/CertificateList.php | 37 - .../File/ASN1/Maps/CertificatePolicies.php | 35 - .../ASN1/Maps/CertificateSerialNumber.php | 30 - .../File/ASN1/Maps/CertificationRequest.php | 37 - .../ASN1/Maps/CertificationRequestInfo.php | 45 - .../phpseclib/File/ASN1/Maps/CountryName.php | 40 - .../phpseclib/File/ASN1/Maps/DSAParams.php | 37 - .../File/ASN1/Maps/DSAPrivateKey.php | 40 - .../phpseclib/File/ASN1/Maps/DSAPublicKey.php | 30 - .../phpseclib/File/ASN1/Maps/DigestInfo.php | 38 - .../File/ASN1/Maps/DirectoryString.php | 39 - .../phpseclib/File/ASN1/Maps/DisplayText.php | 38 - .../File/ASN1/Maps/DistributionPoint.php | 49 - .../File/ASN1/Maps/DistributionPointName.php | 44 - .../phpseclib/File/ASN1/Maps/DssSigValue.php | 36 - .../phpseclib/File/ASN1/Maps/EDIPartyName.php | 46 - .../File/ASN1/Maps/EncryptedData.php | 30 - .../ASN1/Maps/EncryptedPrivateKeyInfo.php | 36 - .../File/ASN1/Maps/ExtKeyUsageSyntax.php | 35 - .../phpseclib/File/ASN1/Maps/Extension.php | 47 - .../File/ASN1/Maps/ExtensionAttribute.php | 46 - .../File/ASN1/Maps/ExtensionAttributes.php | 35 - .../phpseclib/File/ASN1/Maps/Extensions.php | 37 - .../phpseclib/File/ASN1/Maps/GeneralName.php | 84 - .../phpseclib/File/ASN1/Maps/GeneralNames.php | 35 - .../File/ASN1/Maps/GeneralSubtree.php | 46 - .../File/ASN1/Maps/GeneralSubtrees.php | 35 - .../File/ASN1/Maps/HoldInstructionCode.php | 30 - .../File/ASN1/Maps/InvalidityDate.php | 30 - .../File/ASN1/Maps/IssuerAltName.php | 30 - .../ASN1/Maps/IssuingDistributionPoint.php | 72 - .../File/ASN1/Maps/KeyIdentifier.php | 30 - .../phpseclib/File/ASN1/Maps/KeyPurposeId.php | 30 - .../phpseclib/File/ASN1/Maps/KeyUsage.php | 43 - lib/phpaes/phpseclib/File/ASN1/Maps/Name.php | 35 - .../File/ASN1/Maps/NameConstraints.php | 44 - .../File/ASN1/Maps/NetworkAddress.php | 30 - .../File/ASN1/Maps/NoticeReference.php | 41 - .../File/ASN1/Maps/NumericUserIdentifier.php | 30 - .../phpseclib/File/ASN1/Maps/ORAddress.php | 37 - .../File/ASN1/Maps/OrganizationName.php | 30 - .../ASN1/Maps/OrganizationalUnitNames.php | 35 - .../File/ASN1/Maps/OtherPrimeInfo.php | 38 - .../File/ASN1/Maps/OtherPrimeInfos.php | 36 - .../phpseclib/File/ASN1/Maps/PBEParameter.php | 38 - .../phpseclib/File/ASN1/Maps/PBES2params.php | 38 - .../phpseclib/File/ASN1/Maps/PBKDF2params.php | 45 - .../phpseclib/File/ASN1/Maps/PBMAC1params.php | 38 - .../phpseclib/File/ASN1/Maps/PKCS9String.php | 36 - .../phpseclib/File/ASN1/Maps/PersonalName.php | 58 - .../File/ASN1/Maps/PolicyInformation.php | 42 - .../File/ASN1/Maps/PolicyMappings.php | 41 - .../File/ASN1/Maps/PolicyQualifierId.php | 30 - .../File/ASN1/Maps/PolicyQualifierInfo.php | 36 - .../File/ASN1/Maps/PostalAddress.php | 36 - .../File/ASN1/Maps/PrivateDomainName.php | 36 - .../phpseclib/File/ASN1/Maps/PrivateKey.php | 30 - .../File/ASN1/Maps/PrivateKeyInfo.php | 45 - .../File/ASN1/Maps/PrivateKeyUsagePeriod.php | 44 - .../File/ASN1/Maps/PublicKeyAndChallenge.php | 36 - .../File/ASN1/Maps/PublicKeyInfo.php | 39 - .../File/ASN1/Maps/RC2CBCParameter.php | 41 - .../phpseclib/File/ASN1/Maps/RDNSequence.php | 42 - .../File/ASN1/Maps/RSAPrivateKey.php | 48 - .../phpseclib/File/ASN1/Maps/RSAPublicKey.php | 36 - .../phpseclib/File/ASN1/Maps/ReasonFlags.php | 43 - .../ASN1/Maps/RelativeDistinguishedName.php | 41 - .../File/ASN1/Maps/RevokedCertificate.php | 39 - .../ASN1/Maps/SignedPublicKeyAndChallenge.php | 37 - .../File/ASN1/Maps/SubjectAltName.php | 30 - .../ASN1/Maps/SubjectDirectoryAttributes.php | 35 - .../File/ASN1/Maps/SubjectPublicKeyInfo.php | 36 - .../phpseclib/File/ASN1/Maps/TBSCertList.php | 58 - .../File/ASN1/Maps/TBSCertificate.php | 69 - .../File/ASN1/Maps/TerminalIdentifier.php | 30 - lib/phpaes/phpseclib/File/ASN1/Maps/Time.php | 36 - .../File/ASN1/Maps/UniqueIdentifier.php | 30 - .../phpseclib/File/ASN1/Maps/UserNotice.php | 42 - .../phpseclib/File/ASN1/Maps/Validity.php | 36 - .../File/ASN1/Maps/netscape_ca_policy_url.php | 30 - .../File/ASN1/Maps/netscape_cert_type.php | 44 - .../File/ASN1/Maps/netscape_comment.php | 30 - lib/phpaes/phpseclib/File/X509.php | 3719 -------------- lib/phpaes/phpseclib/Math/BigInteger.php | 3886 --------------- lib/phpaes/phpseclib/Net/SCP.php | 341 -- lib/phpaes/phpseclib/Net/SFTP.php | 3046 ----------- lib/phpaes/phpseclib/Net/SFTP/Stream.php | 795 --- lib/phpaes/phpseclib/Net/SSH1.php | 1619 ------ lib/phpaes/phpseclib/Net/SSH2.php | 4441 ----------------- lib/phpaes/phpseclib/System/SSH/Agent.php | 340 -- .../phpseclib/System/SSH/Agent/Identity.php | 171 - lib/phpaes/phpseclib/bootstrap.php | 20 - lib/phpaes/phpseclib/openssl.cnf | 6 - www/js/all.js | 91 - www/theme/default/en.blackberry.css | 21 - www/theme/default/en.classic.css | 21 - www/theme/default/en.default.css | 16 - www/theme/default/en.green.css | 21 - www/theme/default/en.pink.css | 21 - www/theme/default/en.purple.css | 21 - www/theme/default/en.red.css | 21 - www/theme/default/zh-cn.blackberry.css | 21 - www/theme/default/zh-cn.classic.css | 21 - www/theme/default/zh-cn.default.css | 16 - www/theme/default/zh-cn.green.css | 21 - www/theme/default/zh-cn.pink.css | 21 - www/theme/default/zh-cn.purple.css | 21 - www/theme/default/zh-cn.red.css | 21 - www/theme/default/zh-tw.blackberry.css | 21 - www/theme/default/zh-tw.classic.css | 21 - www/theme/default/zh-tw.default.css | 16 - www/theme/default/zh-tw.green.css | 21 - www/theme/default/zh-tw.pink.css | 21 - www/theme/default/zh-tw.purple.css | 21 - www/theme/default/zh-tw.red.css | 21 - www/upgradexuanxuan.php | 27 - www/xuanxuan.php | 29 - 191 files changed, 40824 deletions(-) delete mode 100644 config/ext/xuanxuan.php delete mode 100644 db/xuanxuan.sql delete mode 100644 framework/xuanxuan.class.php delete mode 100644 lib/phpaes/phpaes.class.php delete mode 100644 lib/phpaes/phpseclib/Common/Functions/Objects.php delete mode 100644 lib/phpaes/phpseclib/Common/Functions/Strings.php delete mode 100644 lib/phpaes/phpseclib/Crypt/AES.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Blowfish.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/AsymmetricKey.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/BlockCipher.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/Keys/OpenSSH.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS1.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS8.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/Keys/PuTTY.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/Signature/Raw.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/StreamCipher.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Common/SymmetricKey.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DES.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Keys/OpenSSH.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS1.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS8.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Keys/PuTTY.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Keys/Raw.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Keys/XML.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Signature/PKCS.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Signature/Raw.php delete mode 100644 lib/phpaes/phpseclib/Crypt/DSA/Signature/SSH2.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Hash.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RC2.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RC4.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA/Keys/MSBLOB.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA/Keys/OpenSSH.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS1.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS8.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA/Keys/PuTTY.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA/Keys/Raw.php delete mode 100644 lib/phpaes/phpseclib/Crypt/RSA/Keys/XML.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Random.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Rijndael.php delete mode 100644 lib/phpaes/phpseclib/Crypt/TripleDES.php delete mode 100644 lib/phpaes/phpseclib/Crypt/Twofish.php delete mode 100644 lib/phpaes/phpseclib/Exception/BadConfigurationException.php delete mode 100644 lib/phpaes/phpseclib/Exception/FileNotFoundException.php delete mode 100644 lib/phpaes/phpseclib/Exception/NoSupportedAlgorithmsException.php delete mode 100644 lib/phpaes/phpseclib/Exception/UnsupportedAlgorithmException.php delete mode 100644 lib/phpaes/phpseclib/File/ANSI.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Element.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AccessDescription.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AdministrationDomainName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AnotherName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Attribute.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AttributeType.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AttributeValue.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Attributes.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/BaseDistance.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/BasicConstraints.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CPSuri.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CRLNumber.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CRLReason.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CertPolicyId.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Certificate.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CertificateIssuer.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CertificateList.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CertificatePolicies.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequest.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/CountryName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DSAParams.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DSAPrivateKey.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DSAPublicKey.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DigestInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DirectoryString.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DisplayText.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPoint.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPointName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/DssSigValue.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/EDIPartyName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedData.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Extension.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttribute.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttributes.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Extensions.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/GeneralName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/GeneralNames.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtree.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtrees.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/HoldInstructionCode.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/InvalidityDate.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/IssuerAltName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/KeyIdentifier.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/KeyPurposeId.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/KeyUsage.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Name.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/NameConstraints.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/NetworkAddress.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/NoticeReference.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/ORAddress.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PBEParameter.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PBES2params.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PBKDF2params.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PBMAC1params.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PKCS9String.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PersonalName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PolicyInformation.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PolicyMappings.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierId.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PostalAddress.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PrivateDomainName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKey.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/RC2CBCParameter.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/RDNSequence.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/RSAPrivateKey.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/RSAPublicKey.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/ReasonFlags.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/RevokedCertificate.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/SubjectAltName.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertList.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertificate.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/TerminalIdentifier.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Time.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/UniqueIdentifier.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/UserNotice.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/Validity.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/netscape_cert_type.php delete mode 100644 lib/phpaes/phpseclib/File/ASN1/Maps/netscape_comment.php delete mode 100644 lib/phpaes/phpseclib/File/X509.php delete mode 100644 lib/phpaes/phpseclib/Math/BigInteger.php delete mode 100644 lib/phpaes/phpseclib/Net/SCP.php delete mode 100644 lib/phpaes/phpseclib/Net/SFTP.php delete mode 100644 lib/phpaes/phpseclib/Net/SFTP/Stream.php delete mode 100644 lib/phpaes/phpseclib/Net/SSH1.php delete mode 100644 lib/phpaes/phpseclib/Net/SSH2.php delete mode 100644 lib/phpaes/phpseclib/System/SSH/Agent.php delete mode 100644 lib/phpaes/phpseclib/System/SSH/Agent/Identity.php delete mode 100644 lib/phpaes/phpseclib/bootstrap.php delete mode 100644 lib/phpaes/phpseclib/openssl.cnf delete mode 100644 www/js/all.js delete mode 100644 www/theme/default/en.blackberry.css delete mode 100644 www/theme/default/en.classic.css delete mode 100644 www/theme/default/en.default.css delete mode 100644 www/theme/default/en.green.css delete mode 100644 www/theme/default/en.pink.css delete mode 100644 www/theme/default/en.purple.css delete mode 100644 www/theme/default/en.red.css delete mode 100644 www/theme/default/zh-cn.blackberry.css delete mode 100644 www/theme/default/zh-cn.classic.css delete mode 100644 www/theme/default/zh-cn.default.css delete mode 100644 www/theme/default/zh-cn.green.css delete mode 100644 www/theme/default/zh-cn.pink.css delete mode 100644 www/theme/default/zh-cn.purple.css delete mode 100644 www/theme/default/zh-cn.red.css delete mode 100644 www/theme/default/zh-tw.blackberry.css delete mode 100644 www/theme/default/zh-tw.classic.css delete mode 100644 www/theme/default/zh-tw.default.css delete mode 100644 www/theme/default/zh-tw.green.css delete mode 100644 www/theme/default/zh-tw.pink.css delete mode 100644 www/theme/default/zh-tw.purple.css delete mode 100644 www/theme/default/zh-tw.red.css delete mode 100644 www/upgradexuanxuan.php delete mode 100644 www/xuanxuan.php diff --git a/config/ext/xuanxuan.php b/config/ext/xuanxuan.php deleted file mode 100644 index 0d261878c5..0000000000 --- a/config/ext/xuanxuan.php +++ /dev/null @@ -1,43 +0,0 @@ -xuanxuan = new stdclass(); -$config->xuanxuan->version = '2.0.0'; -$config->xuanxuan->key = '88888888888888888888888888888888'; //Set a 32 byte string as your key. - -if(!defined('TABLE_IM_CHAT')) define('TABLE_IM_CHAT', '`' . $config->db->prefix . 'im_chat`'); -if(!defined('TABLE_IM_MESSAGE')) define('TABLE_IM_MESSAGE', '`' . $config->db->prefix . 'im_message`'); -if(!defined('TABLE_IM_CHATUSER')) define('TABLE_IM_CHATUSER', '`' . $config->db->prefix . 'im_chatuser`'); -if(!defined('TABLE_IM_MESSAGESTATUS')) define('TABLE_IM_MESSAGESTATUS', '`' . $config->db->prefix . 'im_messagestatus`'); - -$config->xuanxuan->enabledMethods['chat']['serverstart'] = 'serverStart'; -$config->xuanxuan->enabledMethods['chat']['login'] = 'login'; -$config->xuanxuan->enabledMethods['chat']['logout'] = 'logout'; -$config->xuanxuan->enabledMethods['chat']['usergetlist'] = 'userGetList'; -$config->xuanxuan->enabledMethods['chat']['userchange'] = 'userChange'; -$config->xuanxuan->enabledMethods['chat']['ping'] = 'ping'; -$config->xuanxuan->enabledMethods['chat']['getpubliclist'] = 'getPublicList'; -$config->xuanxuan->enabledMethods['chat']['getlist'] = 'getList'; -$config->xuanxuan->enabledMethods['chat']['members'] = 'members'; -$config->xuanxuan->enabledMethods['chat']['getofflinemessages'] = 'getOfflineMessages'; -$config->xuanxuan->enabledMethods['chat']['create'] = 'create'; -$config->xuanxuan->enabledMethods['chat']['setadmin'] = 'setAdmin'; -$config->xuanxuan->enabledMethods['chat']['joinchat'] = 'joinChat'; -$config->xuanxuan->enabledMethods['chat']['changename'] = 'changeName'; -$config->xuanxuan->enabledMethods['chat']['dismiss'] = 'dismiss'; -$config->xuanxuan->enabledMethods['chat']['setcommitters'] = 'setCommitters'; -$config->xuanxuan->enabledMethods['chat']['changepublic'] = 'changePublic'; -$config->xuanxuan->enabledMethods['chat']['star'] = 'star'; -$config->xuanxuan->enabledMethods['chat']['hide'] = 'hide'; -$config->xuanxuan->enabledMethods['chat']['mute'] = 'mute'; -$config->xuanxuan->enabledMethods['chat']['category'] = 'category'; -$config->xuanxuan->enabledMethods['chat']['addmember'] = 'addMember'; -$config->xuanxuan->enabledMethods['chat']['message'] = 'message'; -$config->xuanxuan->enabledMethods['chat']['history'] = 'history'; -$config->xuanxuan->enabledMethods['chat']['settings'] = 'settings'; -$config->xuanxuan->enabledMethods['chat']['uploadfile'] = 'uploadFile'; -$config->xuanxuan->enabledMethods['chat']['getofflinenotify'] = 'getofflinenotify'; -$config->xuanxuan->enabledMethods['chat']['notify'] = 'notify'; -$config->xuanxuan->enabledMethods['chat']['upserttodo'] = 'upsertTodo'; -$config->xuanxuan->enabledMethods['chat']['gettodoes'] = 'getTodoes'; -$config->xuanxuan->enabledMethods['chat']['checkuserchange'] = 'checkUserChange'; -$config->xuanxuan->enabledMethods['chat']['extensions'] = 'extensions'; -$config->xuanxuan->enabledMethods['entry']['visit'] = 'visit'; diff --git a/db/xuanxuan.sql b/db/xuanxuan.sql deleted file mode 100644 index 0f8b4614d8..0000000000 --- a/db/xuanxuan.sql +++ /dev/null @@ -1,76 +0,0 @@ --- DROP TABLE IF EXISTS `zt_im_chat`; -CREATE TABLE IF NOT EXISTS `zt_im_chat` ( - `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, - `gid` char(40) NOT NULL DEFAULT '', - `name` varchar(60) NOT NULL DEFAULT '', - `type` varchar(20) NOT NULL DEFAULT 'group', - `admins` varchar(255) NOT NULL DEFAULT '', - `committers` varchar(255) NOT NULL DEFAULT '', - `subject` mediumint(8) unsigned NOT NULL DEFAULT 0, - `public` enum('0', '1') NOT NULL DEFAULT '0', - `createdBy` varchar(30) NOT NULL DEFAULT '', - `createdDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `editedBy` varchar(30) NOT NULL DEFAULT '', - `editedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `lastActiveTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `dismissDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - PRIMARY KEY (`id`), - KEY `gid` (`gid`), - KEY `name` (`name`), - KEY `type` (`type`), - KEY `public` (`public`), - KEY `createdBy` (`createdBy`), - KEY `editedBy` (`editedBy`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- DROP TABLE IF EXISTS `zt_im_message`; -CREATE TABLE IF NOT EXISTS `zt_im_message` ( - `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, - `gid` char(40) NOT NULL DEFAULT '', - `cgid` char(40) NOT NULL DEFAULT '', - `user` varchar(30) NOT NULL DEFAULT '', - `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `order` bigint(8) unsigned NOT NULL, - `type` enum('normal', 'broadcast', 'notify') NOT NULL DEFAULT 'normal', - `content` text NOT NULL DEFAULT '', - `contentType` enum('text', 'plain', 'emotion', 'image', 'file', 'object') NOT NULL DEFAULT 'text', - `data` text NOT NULL DEFAULT '', - PRIMARY KEY (`id`), - KEY `mgid` (`gid`), - KEY `mcgid` (`cgid`), - KEY `muser` (`user`), - KEY `mtype` (`type`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- DROP TABLE IF EXISTS `zt_im_chatuser`; -CREATE TABLE IF NOT EXISTS `zt_im_chatuser`( - `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, - `cgid` char(40) NOT NULL DEFAULT '', - `user` mediumint(8) NOT NULL DEFAULT 0, - `order` smallint(5) NOT NULL DEFAULT 0, - `star` enum('0', '1') NOT NULL DEFAULT '0', - `hide` enum('0', '1') NOT NULL DEFAULT '0', - `mute` enum('0', '1') NOT NULL DEFAULT '0', - `join` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `quit` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `category` varchar(40) NOT NULL DEFAULT '', - PRIMARY KEY (`id`), - KEY `cgid` (`cgid`), - KEY `user` (`user`), - KEY `order` (`order`), - KEY `star` (`star`), - KEY `hide` (`hide`), - UNIQUE KEY `chatuser` (`cgid`, `user`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- DROP TABLE IF EXISTS `zt_im_messagestatus`; -CREATE TABLE `zt_im_messagestatus` ( - `user` mediumint(8) NOT NULL DEFAULT 0, - `gid` char(40) NOT NULL DEFAULT '', - `status` enum('waiting','sent','readed','deleted') NOT NULL DEFAULT 'waiting', - UNIQUE KEY `user` (`user`,`gid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -ALTER TABLE `zt_user` ADD `status` enum('online', 'away', 'busy', 'offline') NOT NULL DEFAULT 'offline'; -ALTER TABLE `zt_file` CHANGE `pathname` `pathname` char(100) NOT NULL; - diff --git a/framework/xuanxuan.class.php b/framework/xuanxuan.class.php deleted file mode 100644 index 056420dd27..0000000000 --- a/framework/xuanxuan.class.php +++ /dev/null @@ -1,353 +0,0 @@ -setViewType(); - $this->setClientLang('zh-cn'); - } - - /** - * Set view type. - * - * @access public - * @return void - */ - public function setViewType() - { - $this->viewType = 'json'; - } - - /** - * 加载common模块。 - * - * common模块比较特别,它会执行几乎每次请求都需要执行的操作,例如: - * 打开session,检查权限等等。 - * 加载完$lang, $config, $dbh后,需要在入口文件(www/index.php)中手动调用该方法。 - * - * Load the common module - * - * The common module is a special module, which can be used to do some common things. For examle: - * start session, check priviledge and so on. - * This method should called manually in the router file(www/index.php) after the $lang, $config, $dbh loaded. - * - * @access public - * @return object|bool the common model object or false if not exits. - */ - public function loadCommon() - { - $result = parent::loadCommon(); - - $this->initAES(); - - return $result; - } - - /** - * Init aes object. - * - * @access public - * @return void - */ - public function initAES() - { - $key = $this->config->xuanxuan->key; - $iv = substr($key, 0, 16); - $this->aes = $this->loadClass('phpaes'); - $this->aes->init($key, $iv); - if($this->config->debug) - { - $this->log("engine: " . $this->aes->getEngine()); - } - } - - /** - * Set params. - * - * @param array $params - * @access public - * @return void - */ - public function setParams($params = array()) - { - $this->params = $params; - } - - /** - * 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。 - * The entrance of parseing request. According to the requestType, call related methods. - * - * @access public - * @return void - */ - public function parseRequest() - { - $input = file_get_contents("php://input"); - $input = $this->decrypt($input); - $version = !empty($input->v) ? $input->v : ''; - $userID = !empty($input->userID) ? $input->userID : ''; - $client = !empty($input->client) ? $input->client : ''; - $module = !empty($input->module) ? $input->module : ''; - $method = !empty($input->method) ? $input->method : ''; - $params = !empty($input->params) ? $input->params : array(); - - $module = strtolower($module); - $method = strtolower($method); - - if(!isset($this->config->xuanxuan->enabledMethods[$module][$method])) - { - $data = new stdclass(); - $data->module = 'chat'; - $data->method = 'kickoff'; - $data->data = 'Illegal Requset.'; - die($this->encrypt($data)); - } - - if($module == 'chat' && $method == 'login' && is_array($params)) - { - /* params[0] is the server name. */ - unset($params[0]); - } - if(is_array($params)) - { - $params[] = $userID; - $params[] = $version; - } - - $this->session->set('userID', $userID); - $this->session->set('clientIP', $client); - - $this->setModuleName($module); - $this->setMethodName($method); - $this->setParams($params); - $this->setControlFile(); - } - - /** - * 加载一个模块: - * 1. 引入控制器文件或扩展的方法文件; - * 2. 创建control对象; - * 3. 解析url,得到请求的参数; - * 4. 使用call_user_function_array调用相应的方法。 - * - * Load a module. - * 1. include the control file or the extension action file. - * 2. create the control object. - * 3. set the params passed in through url. - * 4. call the method by call_user_function_array - * - * @access public - * @return bool|object if the module object of die. - */ - public function loadModule() - { - $appName = $this->appName; - $moduleName = $this->moduleName; - $methodName = $this->methodName; - - /* - * 引入该模块的control文件。 - * Include the control file of the module. - **/ - $file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile; - chdir(dirname($file2Included)); - helper::import($file2Included); - - /* - * 设置control的类名。 - * Set the class name of the control. - **/ - $className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName; - if(!class_exists($className)) - { - $this->triggerError("the control $className not found", __FILE__, __LINE__); - return false; - } - - /* - * 创建control类的实例。 - * Create a instance of the control. - **/ - $module = new $className(); - if(!method_exists($module, $methodName)) - { - $this->triggerError("the module $moduleName has no $methodName method", __FILE__, __LINE__); - return false; - } - /* If the db server restarted, must reset dbh. */ - $this->control = $module; - - /* include default value for module*/ - $defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php"); - if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file; - - /* - * 使用反射机制获取函数参数的默认值。 - * Get the default settings of the method to be called using the reflecting. - * - * */ - $defaultParams = array(); - $methodReflect = new reflectionMethod($className, $methodName); - foreach($methodReflect->getParameters() as $param) - { - $name = $param->getName(); - - $default = '_NOT_SET'; - if(isset($paramDefaultValue[$appName][$className][$methodName][$name])) - { - $default = $paramDefaultValue[$appName][$className][$methodName][$name]; - } - elseif(isset($paramDefaultValue[$className][$methodName][$name])) - { - $default = $paramDefaultValue[$className][$methodName][$name]; - } - elseif($param->isDefaultValueAvailable()) - { - $default = $param->getDefaultValue(); - } - - $defaultParams[$name] = $default; - } - - /* Merge params. */ - $params = array(); - if(isset($this->params)) - { - $params = $this->mergeParams($defaultParams, (array)$this->params); - } - else - { - $this->triggerError("param error: {$this->request->raw}", __FILE__, __LINE__); - return false; - } - - /* Call the method. */ - $this->response = call_user_func_array(array($module, $methodName), $params); - return true; - } - - /** - * 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。 - * Merge the params passed in and the default params. Thus the params which have default values needn't pass value, just like a function. - * - * @param array $defaultParams the default params defined by the method. - * @param array $passedParams the params passed in through url. - * @access public - * @return array the merged params. - */ - public function mergeParams($defaultParams, $passedParams) - { - /* Remove these two params. */ - unset($passedParams['onlybody']); - unset($passedParams['HTTP_X_REQUESTED_WITH']); - - /* Check params from URL. */ - foreach($passedParams as $param => $value) - { - if(preg_match('/[^a-zA-Z0-9_\.]/', $param)) die('Bad Request!'); - } - - $passedParams = array_values($passedParams); - $i = 0; - foreach($defaultParams as $key => $defaultValue) - { - if(isset($passedParams[$i])) - { - $defaultParams[$key] = $passedParams[$i]; - } - else - { - if($defaultValue === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, $exit = true); - } - $i ++; - } - - return $defaultParams; - } - - /** - * Decrypt an input string. - * - * @param string $input - * @access public - * @return object - */ - public function decrypt($input = '') - { - $input = $this->aes->decrypt($input); - if($this->config->debug) - { - $this->log("decrypt: " . $input); - } - $input = json_decode($input); - return $input; - } - - /** - * Encrypt an output object. - * - * @param int $output - * @access public - * @return string - */ - public function encrypt($output = null) - { - if(is_object($output)) $output->v = $this->config->xuanxuan->version; - - $output = helper::jsonEncode($output); - if($this->config->debug) - { - $this->log("encrypt: " . $output); - } - $output = $this->aes->encrypt($output); - return helper::removeUTF8Bom($output); - } - - /** - * Save a log. - * - * @param string $log - * @param string $file - * @param string $line - * @access public - * @return void - */ - public function log($message, $file = '', $line = '') - { - $log = "\n" . date('H:i:s') . " $message"; - if($file) $log .= " in $file"; - if($line) $log .= " on line $line "; - $file = $this->getLogRoot() . 'xuanxuan.log.php'; - if(!is_file($file)) file_put_contents($file, "\n"); - - $fh = @fopen($file, 'a'); - if($fh) fwrite($fh, $log) && fclose($fh); - } -} diff --git a/lib/phpaes/phpaes.class.php b/lib/phpaes/phpaes.class.php deleted file mode 100644 index 0902a0dd51..0000000000 --- a/lib/phpaes/phpaes.class.php +++ /dev/null @@ -1,47 +0,0 @@ -aes = new AES(self::MODE_CBC); - $this->aes->setKey($key); - $this->aes->setIV($iv); - } - - public function encrypt($output) - { - return $this->aes->encrypt($output); - } - - public function decrypt($input) - { - return $this->aes->decrypt($input); - } - - public function getEngine() - { - switch($this->aes->getEngine()) - { - case self::ENGINE_INTERNAL : return 'ENGINE_INTERNAL'; - case self::ENGINE_EVAL : return 'ENGINE_EVAL'; - case self::ENGINE_MCRYPT : return 'ENGINE_MCRYPT'; - case self::ENGINE_OPENSSL : return 'ENGINE_OPENSSL'; - default: return 'error'; - } - } -} diff --git a/lib/phpaes/phpseclib/Common/Functions/Objects.php b/lib/phpaes/phpseclib/Common/Functions/Objects.php deleted file mode 100644 index cb87b1a71d..0000000000 --- a/lib/phpaes/phpseclib/Common/Functions/Objects.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Common\Functions; - -/** - * Common Object Functions - * - * @package Functions\Objects - * @author Jim Wigginton - */ -abstract class Objects -{ - /** - * Accesses a private variable from an object - * - * @param Object $obj - * @param string $var - * @return mixed - * @access public - */ - public static function getVar($obj, $var) - { - $reflection = new \ReflectionClass(get_class($obj)); - $prop = $reflection->getProperty($var); - $prop->setAccessible(true); - return $prop->getValue($obj); - } - - /** - * Sets the value of a private variable in an object - * - * @param Object $obj - * @param string $var - * @param mixed $val - * @return mixed - * @access public - */ - public static function setVar($obj, $var, $val) - { - $reflection = new \ReflectionClass(get_class($obj)); - $prop = $reflection->getProperty($var); - $prop->setAccessible(true); - return $prop->setValue($obj, $val); - } - - /** - * Accesses a private method from an object - * - * @param Object $obj - * @param string $func - * @param array $params - * @return mixed - * @access public - */ - public static function callFunc($obj, $func, $params = array()) - { - $reflection = new \ReflectionClass(get_class($obj)); - $method = $reflection->getMethod($func); - $method->setAccessible(true); - return $method->invokeArgs($obj, $params); - } -} diff --git a/lib/phpaes/phpseclib/Common/Functions/Strings.php b/lib/phpaes/phpseclib/Common/Functions/Strings.php deleted file mode 100644 index 2e6f486582..0000000000 --- a/lib/phpaes/phpseclib/Common/Functions/Strings.php +++ /dev/null @@ -1,228 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Common\Functions; - -use phpseclib\Math\BigInteger; - -/** - * Common String Functions - * - * @package Functions\Strings - * @author Jim Wigginton - */ -abstract class Strings -{ - /** - * String Shift - * - * Inspired by array_shift - * - * @param string $string - * @param int $index - * @access public - * @return string - */ - public static function shift(&$string, $index = 1) - { - $substr = substr($string, 0, $index); - $string = substr($string, $index); - return $substr; - } - - /** - * String Pop - * - * Inspired by array_pop - * - * @param string $string - * @param int $index - * @access public - * @return string - */ - public static function pop(&$string, $index = 1) - { - $substr = substr($string, -$index); - $string = substr($string, 0, -$index); - return $substr; - } - - /** - * Performs blinded equality testing on strings - * - * Protects against a particular type of timing attack described. - * - * See {@link http://codahale.com/a-lesson-in-timing-attacks/ A Lesson In Timing Attacks (or, Don't use MessageDigest.isEquals)} - * - * Thanks for the heads up singpolyma! - * - * @access public - * @param string $x - * @param string $y - * @return bool - */ - public static function equals($x, $y) - { - if (strlen($x) != strlen($y)) { - return false; - } - - $result = 0; - for ($i = 0; $i < strlen($x); $i++) { - $result |= ord($x[$i]) ^ ord($y[$i]); - } - - return $result == 0; - } - - /** - * Parse SSH2-style string - * - * Returns either an array or a boolean if $data is malformed. - * - * Valid characters for $format are as follows: - * - * C = byte - * b = boolean (true/false) - * N = uint32 - * s = string - * i = mpint - * l = name-list - * - * uint64 is not supported. - * - * @param string $string - * @param int $index - * @access public - * @return mixed - */ - public static function unpackSSH2($format, $data) - { - $result = array(); - for ($i = 0; $i < strlen($format); $i++) { - switch ($format[$i]) { - case 'C': - case 'b': - if (!strlen($data)) { - return false; - } - break; - case 'N': - case 'i': - case 's': - case 'l': - if (strlen($data) < 4) { - return false; - } - break; - default: - throw new \InvalidArgumentException('$format contains an invalid character'); - } - switch ($format[$i]) { - case 'C': - $result[] = ord(self::shift($data)); - continue 2; - case 'b': - $result[] = ord(self::shift($data)) != 0; - continue 2; - case 'N': - list(, $temp) = unpack('N', self::shift($data, 4)); - $result[] = $temp; - continue 2; - } - list(, $length) = unpack('N', self::shift($data, 4)); - if (strlen($data) < $length) { - return false; - } - $temp = self::shift($data, $length); - switch ($format[$i]) { - case 'i': - $result[] = new BigInteger($temp, -256); - break; - case 's': - $result[] = $temp; - break; - case 'l': - $result[] = explode(',', $temp); - } - } - - return $result; - } - - /** - * Create SSH2-style string - * - * @param mixed $input.. - * @access public - * @return mixed - */ - public static function packSSH2() - { - $elements = func_get_args(); - $format = $elements[0]; - array_shift($elements); - if (strlen($format) != count($elements)) { - throw new \InvalidArgumentException('There must be as many arguments as there are characters in the $format string'); - } - $result = ''; - for ($i = 0; $i < strlen($format); $i++) { - $element = $elements[$i]; - switch ($format[$i]) { - case 'C': - if (!is_int($element)) { - throw new \InvalidArgumentException('Bytes must be represented as an integer between 0 and 255, inclusive.'); - } - $result.= pack('C', $element); - break; - case 'b': - if (!is_bool($element)) { - throw new \InvalidArgumentException('A boolean parameter was expected.'); - } - $result.= $element ? "\1" : "\0"; - break; - case 'N': - if (!is_int($element)) { - throw new \InvalidArgumentException('An integer was expected.'); - } - $result.= pack('N', $element); - break; - case 's': - if (!is_string($element)) { - throw new \InvalidArgumentException('A string was expected.'); - } - $result.= pack('Na*', strlen($element), $element); - break; - case 'i': - if (!$element instanceof BigInteger) { - throw new \InvalidArgumentException('A phpseclib\Math\BigInteger object was expected.'); - } - $element = $element->toBytes(true); - $result.= pack('Na*', strlen($element), $element); - break; - case 'l': - if (!is_array($element)) { - throw new \InvalidArgumentException('An array was expected.'); - } - $element = implode(',', $element); - $result.= pack('Na*', strlen($element), $element); - break; - default: - throw new \InvalidArgumentException('$format contains an invalid character'); - } - } - return $result; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/AES.php b/lib/phpaes/phpseclib/Crypt/AES.php deleted file mode 100644 index e7e8aad3e7..0000000000 --- a/lib/phpaes/phpseclib/Crypt/AES.php +++ /dev/null @@ -1,135 +0,0 @@ - - * setKey('abcdefghijklmnop'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $aes->decrypt($aes->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package AES - * @author Jim Wigginton - * @copyright 2008 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -//namespace phpseclib\Crypt; -include PHPAES_ROOT . '/phpseclib/Crypt/Rijndael.php'; - -/** - * Pure-PHP implementation of AES. - * - * @package AES - * @author Jim Wigginton - * @access public - */ -class AES extends Rijndael -{ - /** - * Dummy function - * - * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything. - * - * @see \phpseclib\Crypt\Rijndael::setBlockLength() - * @access public - * @param int $length - * @throws \BadMethodCallException anytime it's called - */ - public function setBlockLength($length) - { - throw new \BadMethodCallException('The block length cannot be set for AES.'); - } - - /** - * Sets the key length - * - * Valid key lengths are 128, 192, and 256. Set the link to bool(false) to disable a fixed key length - * - * @see \phpseclib\Crypt\Rijndael:setKeyLength() - * @access public - * @param int $length - * @throws \LengthException if the key length isn't supported - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 192: - case 256: - break; - default: - throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported'); - } - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Rijndael supports five different key lengths, AES only supports three. - * - * @see \phpseclib\Crypt\Rijndael:setKey() - * @see setKeyLength() - * @access public - * @param string $key - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key) - { - switch (strlen($key)) { - case 16: - case 24: - case 32: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); - } - - parent::setKey($key); - } - - /** - * Returns the class that defines the private methods - * - * @access private - * @return string - */ - protected function getClassContext() - { - return 'phpseclib\Crypt\Rijndael'; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Blowfish.php b/lib/phpaes/phpseclib/Crypt/Blowfish.php deleted file mode 100644 index ab79f2204d..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Blowfish.php +++ /dev/null @@ -1,559 +0,0 @@ - - * setKey('12345678901234567890123456789012'); - * - * $plaintext = str_repeat('a', 1024); - * - * echo $blowfish->decrypt($blowfish->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package Blowfish - * @author Jim Wigginton - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use phpseclib\Crypt\Common\BlockCipher; - -/** - * Pure-PHP implementation of Blowfish. - * - * @package Blowfish - * @author Jim Wigginton - * @author Hans-Juergen Petrich - * @access public - */ -class Blowfish extends BlockCipher -{ - /** - * Block Length of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::block_size - * @var int - * @access private - */ - protected $block_size = 8; - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - * @access private - */ - protected $cipher_name_mcrypt = 'blowfish'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - * @access private - */ - protected $cfb_init_len = 500; - - /** - * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each - * - * S-Box 0 - * - * @access private - * @var array - */ - private $sbox0 = [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, - 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, - 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, - 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, - 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, - 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, - 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, - 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, - 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, - 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, - 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, - 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, - 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, - 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, - 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, - 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, - 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, - 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a - ]; - - /** - * S-Box 1 - * - * @access private - * @var array - */ - private $sbox1 = [ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, - 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, - 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, - 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, - 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, - 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, - 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, - 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, - 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, - 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, - 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, - 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, - 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, - 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, - 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, - 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, - 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, - 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 - ]; - - /** - * S-Box 2 - * - * @access private - * @var array - */ - private $sbox2 = [ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, - 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, - 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, - 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, - 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, - 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, - 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, - 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, - 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, - 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, - 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, - 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, - 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, - 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, - 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, - 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, - 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 - ]; - - /** - * S-Box 3 - * - * @access private - * @var array - */ - private $sbox3 = [ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, - 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, - 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, - 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, - 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, - 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, - 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, - 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, - 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, - 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, - 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, - 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, - 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, - 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, - 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, - 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, - 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, - 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - ]; - - /** - * P-Array consists of 18 32-bit subkeys - * - * @var array - * @access private - */ - private $parray = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b - ]; - - /** - * The BCTX-working Array - * - * Holds the expanded key [p] and the key-depended s-boxes [sb] - * - * @var array - * @access private - */ - private $bctx; - - /** - * Holds the last used key - * - * @var array - * @access private - */ - private $kl; - - /** - * The Key Length (in bytes) - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setKeyLength() - * @var int - * @access private - * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk - * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could - * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once. - */ - protected $key_length = 16; - - /** - * Default Constructor. - * - * @param int $mode - * @access public - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - if ($mode == self::MODE_STREAM) { - throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode'); - } - - parent::__construct($mode); - } - - /** - * Sets the key length. - * - * Key lengths can be between 32 and 448 bits. - * - * @access public - * @param int $length - */ - public function setKeyLength($length) - { - if ($length < 32 || $length > 448) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes between 32 and 448 bits are supported'); - } - - $this->key_length = $length >> 3; - - parent::setKeyLength($length); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * @param int $engine - * @access public - * @return bool - */ - public function isValidEngine($engine) - { - if ($engine == self::ENGINE_OPENSSL) { - if ($this->key_length < 16) { - return false; - } - $this->cipher_name_openssl_ecb = 'bf-ecb'; - $this->cipher_name_openssl = 'bf-' . $this->openssl_translate_mode(); - } - - return parent::isValidEngine($engine); - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib\Crypt\Common\SymmetricKey::_setupKey() - * @access private - */ - protected function setupKey() - { - if (isset($this->kl['key']) && $this->key === $this->kl['key']) { - // already expanded - return; - } - $this->kl = ['key' => $this->key]; - - /* key-expanding p[] and S-Box building sb[] */ - $this->bctx = [ - 'p' => [], - 'sb' => [ - $this->sbox0, - $this->sbox1, - $this->sbox2, - $this->sbox3 - ] - ]; - - // unpack binary string in unsigned chars - $key = array_values(unpack('C*', $this->key)); - $keyl = count($key); - for ($j = 0, $i = 0; $i < 18; ++$i) { - // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ... - for ($data = 0, $k = 0; $k < 4; ++$k) { - $data = ($data << 8) | $key[$j]; - if (++$j >= $keyl) { - $j = 0; - } - } - $this->bctx['p'][] = $this->parray[$i] ^ $data; - } - - // encrypt the zero-string, replace P1 and P2 with the encrypted data, - // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys - $data = "\0\0\0\0\0\0\0\0"; - for ($i = 0; $i < 18; $i += 2) { - list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data))); - $this->bctx['p'][$i ] = $l; - $this->bctx['p'][$i + 1] = $r; - } - for ($i = 0; $i < 4; ++$i) { - for ($j = 0; $j < 256; $j += 2) { - list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data))); - $this->bctx['sb'][$i][$j ] = $l; - $this->bctx['sb'][$i][$j + 1] = $r; - } - } - } - - /** - * Encrypts a block - * - * @access private - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - $p = $this->bctx["p"]; - // extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower - $sb_0 = $this->bctx["sb"][0]; - $sb_1 = $this->bctx["sb"][1]; - $sb_2 = $this->bctx["sb"][2]; - $sb_3 = $this->bctx["sb"][3]; - - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - - for ($i = 0; $i < 16; $i+= 2) { - $l^= $p[$i]; - $r^= ($sb_0[$l >> 24 & 0xff] + - $sb_1[$l >> 16 & 0xff] ^ - $sb_2[$l >> 8 & 0xff]) + - $sb_3[$l & 0xff]; - - $r^= $p[$i + 1]; - $l^= ($sb_0[$r >> 24 & 0xff] + - $sb_1[$r >> 16 & 0xff] ^ - $sb_2[$r >> 8 & 0xff]) + - $sb_3[$r & 0xff]; - } - return pack("N*", $r ^ $p[17], $l ^ $p[16]); - } - - /** - * Decrypts a block - * - * @access private - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - $p = $this->bctx["p"]; - $sb_0 = $this->bctx["sb"][0]; - $sb_1 = $this->bctx["sb"][1]; - $sb_2 = $this->bctx["sb"][2]; - $sb_3 = $this->bctx["sb"][3]; - - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - - for ($i = 17; $i > 2; $i-= 2) { - $l^= $p[$i]; - $r^= ($sb_0[$l >> 24 & 0xff] + - $sb_1[$l >> 16 & 0xff] ^ - $sb_2[$l >> 8 & 0xff]) + - $sb_3[$l & 0xff]; - - $r^= $p[$i - 1]; - $l^= ($sb_0[$r >> 24 & 0xff] + - $sb_1[$r >> 16 & 0xff] ^ - $sb_2[$r >> 8 & 0xff]) + - $sb_3[$r & 0xff]; - } - return pack("N*", $r ^ $p[0], $l ^ $p[1]); - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::_setupInlineCrypt() - * @access private - */ - protected function setupInlineCrypt() - { - $p = $this->bctx['p']; - $init_crypt = ' - static $sb_0, $sb_1, $sb_2, $sb_3; - if (!$sb_0) { - $sb_0 = $this->bctx["sb"][0]; - $sb_1 = $this->bctx["sb"][1]; - $sb_2 = $this->bctx["sb"][2]; - $sb_3 = $this->bctx["sb"][3]; - } - '; - - // Generating encrypt code: - $encrypt_block = ' - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - '; - for ($i = 0; $i < 16; $i+= 2) { - $encrypt_block.= ' - $l^= ' . $p[$i] . '; - $r^= ($sb_0[$l >> 24 & 0xff] + - $sb_1[$l >> 16 & 0xff] ^ - $sb_2[$l >> 8 & 0xff]) + - $sb_3[$l & 0xff]; - - $r^= ' . $p[$i + 1] . '; - $l^= ($sb_0[$r >> 24 & 0xff] + - $sb_1[$r >> 16 & 0xff] ^ - $sb_2[$r >> 8 & 0xff]) + - $sb_3[$r & 0xff]; - '; - } - $encrypt_block.= ' - $in = pack("N*", - $r ^ ' . $p[17] . ', - $l ^ ' . $p[16] . ' - ); - '; - // Generating decrypt code: - $decrypt_block = ' - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - '; - - for ($i = 17; $i > 2; $i-= 2) { - $decrypt_block.= ' - $l^= ' . $p[$i] . '; - $r^= ($sb_0[$l >> 24 & 0xff] + - $sb_1[$l >> 16 & 0xff] ^ - $sb_2[$l >> 8 & 0xff]) + - $sb_3[$l & 0xff]; - - $r^= ' . $p[$i - 1] . '; - $l^= ($sb_0[$r >> 24 & 0xff] + - $sb_1[$r >> 16 & 0xff] ^ - $sb_2[$r >> 8 & 0xff]) + - $sb_3[$r & 0xff]; - '; - } - - $decrypt_block.= ' - $in = pack("N*", - $r ^ ' . $p[0] . ', - $l ^ ' . $p[1] . ' - ); - '; - - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'init_encrypt' => '', - 'init_decrypt' => '', - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ] - ); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/AsymmetricKey.php b/lib/phpaes/phpseclib/Crypt/Common/AsymmetricKey.php deleted file mode 100644 index 08124730ef..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/AsymmetricKey.php +++ /dev/null @@ -1,660 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common; - -use phpseclib\Math\BigInteger; -use phpseclib\Crypt\Hash; -use ParagonIE\ConstantTime\Base64; - -/** - * Base Class for all stream cipher classes - * - * @package AsymmetricKey - * @author Jim Wigginton - */ -abstract class AsymmetricKey -{ - /** - * Precomputed Zero - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - protected static $zero; - - /** - * Precomputed One - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - protected static $one; - - /** - * Engine - * - * This is only used for key generation. Valid values are RSA::ENGINE_INTERNAL and RSA::ENGINE_OPENSSL - * - * @var int - * @access private - */ - protected static $engine = NULL; - - /** - * OpenSSL configuration file name. - * - * Set to null to use system configuration file. - * - * @see self::createKey() - * @var mixed - * @access public - */ - protected static $configFile; - - /** - * Supported plugins (lower case) - * - * @see self::initialize_static_variables() - * @var array - * @access private - */ - private static $plugins = []; - - /** - * Supported plugins (original case) - * - * @see self::initialize_static_variables() - * @var array - * @access private - */ - private static $origPlugins = []; - - /** - * Supported signature formats (lower case) - * - * @see self::initialize_static_variables() - * @var array - * @access private - */ - private static $signatureFormats = []; - - /** - * Supported signature formats (original case) - * - * @see self::initialize_static_variables() - * @var array - * @access private - */ - private static $signatureFileFormats = []; - - /** - * Password - * - * @var string - * @access private - */ - protected $password = false; - - /** - * Loaded File Format - * - * @var string - * @access private - */ - protected $format = false; - - /** - * Private Key Format - * - * @var string - * @access private - */ - protected $privateKeyFormat = 'PKCS8'; - - /** - * Public Key Format - * - * @var string - * @access private - */ - protected $publicKeyFormat = 'PKCS8'; - - /** - * Hash function - * - * @var \phpseclib\Crypt\Hash - * @access private - */ - protected $hash; - - /** - * HMAC function - * - * @var \phpseclib\Crypt\Hash - * @access private - */ - private $hmac; - - /**#@+ - * @access private - * @see self::__construct() - */ - /** - * To use the pure-PHP implementation - */ - const ENGINE_INTERNAL = 1; - /** - * To use the OpenSSL library - * - * (if enabled; otherwise, the internal implementation will be used) - */ - const ENGINE_OPENSSL = 2; - /**#@-*/ - - /** - * The constructor - * - * @access public - */ - public function __construct() - { - self::initialize_static_variables(); - - $this->hash = new Hash('sha256'); - $this->hmac = new Hash('sha256'); - } - - /** - * Tests engine validity - * - * @access public - * @param int $val - */ - public static function isValidEngine($val) - { - switch ($val) { - case self::ENGINE_OPENSSL: - return extension_loaded('openssl') && file_exists(self::$configFile); - case self::ENGINE_INTERNAL: - return true; - } - - return false; - } - - /** - * Sets the engine - * - * Only used in RSA::createKey. Valid values are RSA::ENGINE_OPENSSL and RSA::ENGINE_INTERNAL - * - * @access public - * @param int $val - */ - public static function setPreferredEngine($val) - { - static::$engine = null; - $candidateEngines = [ - $val, - self::ENGINE_OPENSSL - ]; - foreach ($candidateEngines as $engine) { - if (static::isValidEngine($engine)) { - static::$engine = $engine; - break; - } - } - if (!isset(static::$engine)) { - static::$engine = self::ENGINE_INTERNAL; - } - } - - /** - * Returns the engine - * - * @access public - * @return int - */ - public static function getEngine() - { - return self::$engine; - } - - /** - * Initialize static variables - * - * @access private - */ - protected static function initialize_static_variables() - { - if (!isset(self::$zero)) { - self::$zero= new BigInteger(0); - self::$one = new BigInteger(1); - self::$configFile = __DIR__ . '/../openssl.cnf'; - } - - self::loadPlugins('Keys'); - if (static::ALGORITHM != 'RSA') { - self::loadPlugins('Signature'); - } - } - - /** - * Load Plugins - * - * @params $format - * @access private - */ - private static function loadPlugins($format) - { - if (!isset(self::$plugins[static::ALGORITHM][$format])) { - self::$plugins[static::ALGORITHM][$format] = []; - foreach (glob(__DIR__ . '/../' . static::ALGORITHM . '/' . $format . '/*.php') as $file) { - $name = pathinfo($file, PATHINFO_FILENAME); - $type = 'phpseclib\Crypt\\' . static::ALGORITHM . '\\' . $format . '\\' . $name; - self::$plugins[static::ALGORITHM][$format][strtolower($name)] = $type; - self::$origPlugins[static::ALGORITHM][$format][] = $name; - } - } - } - - /** - * Validate Plugin - * - * @access private - * @param string $format - * @param string $type - * @param string $method optional - * @return mixed - */ - protected static function validatePlugin($format, $type, $method = NULL) - { - $type = strtolower($type); - if (!isset(self::$plugins[static::ALGORITHM][$format][$type])) { - return false; - } - $type = self::$plugins[static::ALGORITHM][$format][$type]; - if (isset($method) && !method_exists($type, $method)) { - return false; - } - - return $type; - } - - /** - * Load the key - * - * @access private - * @param string $key - * @param string $type - * @return array - */ - protected function load($key, $type) - { - $components = false; - if ($type === false) { - foreach (self::$plugins[static::ALGORITHM]['Keys'] as $format) { - try { - $components = $format::load($key, $this->password); - } catch (\Exception $e) { - $components = false; - } - if ($components !== false) { - break; - } - } - } else { - $format = strtolower($type); - if (isset(self::$plugins[static::ALGORITHM]['Keys'][$format])) { - $format = self::$plugins[static::ALGORITHM]['Keys'][$format]; - $components = $format::load($key, $this->password); - } - } - - if ($components === false) { - $this->format = false; - return false; - } - - $this->format = $format; - - return $components; - } - - /** - * Load the public key - * - * @access private - * @param string $key - * @param string $type - * @return array - */ - protected function setPublicKey($key, $type) - { - $components = false; - if ($type === false) { - foreach (self::$plugins[static::ALGORITHM]['Keys'] as $format) { - if (!method_exists($format, 'savePublicKey')) { - continue; - } - try { - $components = $format::load($key, $this->password); - } catch (\Exception $e) { - $components = false; - } - if ($components !== false) { - break; - } - } - } else { - $format = strtolower($type); - if (isset(self::$plugins[static::ALGORITHM]['Keys'][$format])) { - $format = self::$plugins[static::ALGORITHM]['Keys'][$format]; - $components = $format::load($key, $this->password); - } - } - - if ($components === false) { - $this->format = false; - return false; - } - - $this->format = $format; - - return $components; - } - - /** - * Returns a list of supported formats. - * - * @access public - * @return array - */ - public static function getSupportedKeyFormats() - { - self::initialize_static_variables(); - - return self::$plugins[static::ALGORITHM]['Keys']; - } - - /** - * Add a fileformat plugin - * - * The plugin needs to either already be loaded or be auto-loadable. - * Loading a plugin whose shortname overwrite an existing shortname will overwrite the old plugin. - * - * @see self::load() - * @param string $fullname - * @access public - * @return bool - */ - public static function addFileFormat($fullname) - { - self::initialize_static_variables(); - - if (class_exists($fullname)) { - $meta = new \ReflectionClass($path); - $shortname = $meta->getShortName(); - self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname; - self::$origPlugins[static::ALGORITHM]['Keys'][] = $shortname; - } - } - - /** - * Returns the public key's fingerprint - * - * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is - * no public key currently loaded, false is returned. - * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716) - * - * @access public - * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned - * for invalid values. - * @return mixed - */ - public function getPublicKeyFingerprint($algorithm = 'md5') - { - $type = self::validatePlugin('Keys', 'OpenSSH', 'getBinaryOutput'); - if ($type === false) { - return false; - } - - $status = $type::getBinaryOutput(); - $type::setBinaryOutput(true); - - $key = $this->getPublicKey('OpenSSH'); - if ($key === false) { - return false; - } - - $type::setBinaryOutput($status); - - switch ($algorithm) { - case 'sha256': - $hash = new Hash('sha256'); - $base = Base64::encode($hash->hash($key)); - return substr($base, 0, strlen($base) - 1); - case 'md5': - return substr(chunk_split(md5($key), 2, ':'), 0, -1); - default: - return false; - } - } - - /** - * __toString() magic method - * - * @access public - * @return string - */ - public function __toString() - { - try { - $key = $this->getPrivateKey($this->privateKeyFormat); - if (is_string($key)) { - return $key; - } - $key = $this->getPublicKey($this->publicKeyFormat); - return is_string($key) ? $key : ''; - } catch (\Exception $e) { - return ''; - } - } - - /** - * __clone() magic method - * - * @access public - * @return static - */ - public function __clone() - { - $key = new static(); - $key->load($this); - return $key; - } - - /** - * Determines the private key format - * - * @see self::__toString() - * @access public - * @param string $format - */ - public function setPrivateKeyFormat($format) - { - $this->privateKeyFormat = $format; - } - - /** - * Determines the public key format - * - * @see self::__toString() - * @access public - * @param string $format - */ - public function setPublicKeyFormat($format) - { - $this->publicKeyFormat = $format; - } - - /** - * Returns the format of the loaded key. - * - * If the key that was loaded wasn't in a valid or if the key was auto-generated - * with RSA::createKey() then this will return false. - * - * @see self::load() - * @access public - * @return mixed - */ - public function getLoadedFormat() - { - if ($this->format === false) { - return false; - } - - $meta = new \ReflectionClass($this->format); - return $meta->getShortName(); - } - - /** - * Sets the password - * - * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false. - * Or rather, pass in $password such that empty($password) && !is_string($password) is true. - * - * @see self::createKey() - * @see self::load() - * @access public - * @param string $password - */ - public function setPassword($password = false) - { - $this->password = $password; - } - - /** - * Determines which hashing function should be used - * - * @access public - * @param string $hash - */ - public function setHash($hash) - { - $this->hash = new Hash($hash); - $this->hmac = new Hash($hash); - } - - /** - * Compute the pseudorandom k for signature generation, - * using the process specified for deterministic DSA. - * - * @access public - * @param string $h1 - * @return string - */ - protected function computek($h1) - { - $v = str_repeat("\1", strlen($h1)); - - $k = str_repeat("\0", strlen($h1)); - - $x = $this->int2octets($this->x); - $h1 = $this->bits2octets($h1); - - $this->hmac->setKey($k); - $k = $this->hmac->hash($v . "\0" . $x . $h1); - $this->hmac->setKey($k); - $v = $this->hmac->hash($v); - $k = $this->hmac->hash($v . "\1" . $x . $h1); - $this->hmac->setKey($k); - $v = $this->hmac->hash($v); - - $qlen = $this->q->getLengthInBytes(); - - while (true) { - $t = ''; - while (strlen($t) < $qlen) { - $v = $this->hmac->hash($v); - $t = $t . $v; - } - $k = $this->bits2int($t); - - if (!$k->equals(self::$zero) && $k->compare($this->q) < 0) { - break; - } - $k = $this->hmac->hash($v . "\0"); - $this->hmac->setKey($k); - $v = $this->hmac->hash($v); - } - - return $k; - } - - /** - * Integer to Octet String - * - * @access private - * @param \phpseclib\Math\BigInteger $v - * @return string - */ - private function int2octets($v) - { - $out = $v->toBytes(); - $rolen = $this->q->getLengthInBytes(); - if (strlen($out) < $rolen) { - return str_pad($out, $rolen, "\0", STR_PAD_LEFT); - } else if (strlen($out) > $rolen) { - return substr($out, -$rolen); - } else { - return $out; - } - } - - /** - * Bit String to Integer - * - * @access private - * @param string $in - * @return \phpseclib\Math\BigInteger - */ - protected function bits2int($in) - { - $v = new BigInteger($in, 256); - $vlen = strlen($in) << 3; - $qlen = $this->q->getLength(); - if ($vlen > $qlen) { - return $v->bitwise_rightShift($vlen - $qlen); - } - return $v; - } - - /** - * Bit String to Octet String - * - * @access private - * @param string $in - * @return string - */ - private function bits2octets($in) - { - $z1 = $this->bits2int($in); - $z2 = $z1->subtract($this->q); - return $z2->compare(self::$zero) < 0 ? - $this->int2octets($z1) : - $this->int2octets($z2); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/BlockCipher.php b/lib/phpaes/phpseclib/Crypt/Common/BlockCipher.php deleted file mode 100644 index 614a4430e3..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/BlockCipher.php +++ /dev/null @@ -1,28 +0,0 @@ - - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -//namespace phpseclib\Crypt\Common; -include PHPAES_ROOT . '/phpseclib/Crypt/Common/SymmetricKey.php'; - -/** - * Base Class for all block cipher classes - * - * @package BlockCipher - * @author Jim Wigginton - */ -abstract class BlockCipher extends SymmetricKey -{ -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/Keys/OpenSSH.php b/lib/phpaes/phpseclib/Crypt/Common/Keys/OpenSSH.php deleted file mode 100644 index eb1ba7a39e..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/Keys/OpenSSH.php +++ /dev/null @@ -1,139 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common\Keys; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Common\Functions\Strings; - -/** - * OpenSSH Formatted RSA Key Handler - * - * @package Common - * @author Jim Wigginton - * @access public - */ -abstract class OpenSSH -{ - /** - * Default comment - * - * @var string - * @access private - */ - protected static $comment = 'phpseclib-generated-key'; - - /** - * Binary key flag - * - * @var bool - * @access private - */ - protected static $binary = false; - - /** - * Sets the default comment - * - * @access public - * @param string $comment - */ - public static function setComment($comment) - { - self::$comment = str_replace(["\r", "\n"], '', $comment); - } - - /** - * Break a public or private key down into its constituent components - * - * $type can be either ssh-dss or ssh-rsa - * - * @access public - * @param string $key - * @param string $type - * @return array - */ - public static function load($key, $type) - { - if (!is_string($key)) { - return false; - } - - $parts = explode(' ', $key, 3); - - if (!isset($parts[1])) { - $key = Base64::decode($parts[0]); - $comment = isset($parts[1]) ? $parts[1] : false; - } else { - if ($parts[0] != $type) { - return false; - } - $key = Base64::decode($parts[1]); - $comment = isset($parts[2]) ? $parts[2] : false; - } - if ($key === false) { - return false; - } - - if (substr($key, 0, 11) != "\0\0\0\7$type") { - return false; - } - Strings::shift($key, 11); - if (strlen($key) <= 4) { - return false; - } - - return $key; - } - - /** - * Returns the comment for the key - * - * @access public - * @return mixed - */ - public static function getComment($key) - { - $parts = explode(' ', $key, 3); - - return isset($parts[2]) ? $parts[2] : false; - } - - /** - * Toggle between binary and printable keys - * - * Printable keys are what are generated by default. These are the ones that go in - * $HOME/.ssh/authorized_key. - * - * @access public - * @param bool $enabled - */ - public static function setBinaryOutput($enabled) - { - self::$binary = $enabled; - } - - /** - * Returns the current binary output value - * - * @access public - * @return bool - */ - public static function getBinaryOutput() - { - return (bool) self::$binary; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS.php b/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS.php deleted file mode 100644 index 7b54b16640..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common\Keys; - -/** - * PKCS1 Formatted Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PKCS -{ - /** - * Auto-detect the format - */ - const MODE_ANY = 0; - /** - * Require base64-encoded PEM's be supplied - */ - const MODE_PEM = 1; - /** - * Require raw DER's be supplied - */ - const MODE_DER = 2; - /**#@-*/ - - /** - * Is the key a base-64 encoded PEM, DER or should it be auto-detected? - * - * @access private - * @param int - */ - protected static $format = self::MODE_ANY; - - /** - * Require base64-encoded PEM's be supplied - * - * @access public - */ - public static function requirePEM() - { - self::$format = self::MODE_PEM; - } - - /** - * Require raw DER's be supplied - * - * @access public - */ - public static function requireDER() - { - self::$format = self::MODE_DER; - } - - /** - * Accept any format and auto detect the format - * - * This is the default setting - * - * @access public - */ - public static function requireAny() - { - self::$format = self::MODE_ANY; - } -} \ No newline at end of file diff --git a/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS1.php b/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS1.php deleted file mode 100644 index 1f6729757d..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS1.php +++ /dev/null @@ -1,224 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common\Keys; - -use ParagonIE\ConstantTime\Base64; -use ParagonIE\ConstantTime\Hex; -use phpseclib\Crypt\Common\BlockCipher; -use phpseclib\Crypt\Random; -use phpseclib\Crypt\AES; -use phpseclib\Crypt\Base; -use phpseclib\Crypt\DES; -use phpseclib\Crypt\TripleDES; -use phpseclib\File\ASN1; - -/** - * PKCS1 Formatted Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PKCS1 extends PKCS -{ - /** - * Default encryption algorithm - * - * @var string - * @access private - */ - private static $defaultEncryptionAlgorithm = 'AES-128-CBC'; - - /** - * Sets the default encryption algorithm - * - * @access public - * @param string $algo - */ - public static function setEncryptionAlgorithm($algo) - { - self::$defaultEncryptionAlgorithm = $algo; - } - - /** - * Returns the mode constant corresponding to the mode string - * - * @access public - * @param string $mode - * @return int - * @throws \UnexpectedValueException if the block cipher mode is unsupported - */ - private static function getEncryptionMode($mode) - { - switch ($mode) { - case 'CBC': - return BlockCipher::MODE_CBC; - case 'ECB': - return BlockCipher::MODE_ECB; - case 'CFB': - return BlockCipher::MODE_CFB; - case 'OFB': - return BlockCipher::MODE_OFB; - case 'CTR': - return BlockCipher::MODE_CTR; - } - throw new \UnexpectedValueException('Unsupported block cipher mode of operation'); - } - - /** - * Returns a cipher object corresponding to a string - * - * @access public - * @param string $algo - * @return string - * @throws \UnexpectedValueException if the encryption algorithm is unsupported - */ - private static function getEncryptionObject($algo) - { - $modes = '(CBC|ECB|CFB|OFB|CTR)'; - switch (true) { - case preg_match("#^AES-(128|192|256)-$modes$#", $algo, $matches): - $cipher = new AES(self::getEncryptionMode($matches[2])); - $cipher->setKeyLength($matches[1]); - return $cipher; - case preg_match("#^DES-EDE3-$modes$#", $algo, $matches): - return new TripleDES(self::getEncryptionMode($matches[1])); - case preg_match("#^DES-$modes$#", $algo, $matches): - return new DES(self::getEncryptionMode($matches[1])); - default: - throw new \UnexpectedValueException('Unsupported encryption algorithmn'); - } - } - - /** - * Generate a symmetric key for PKCS#1 keys - * - * @access private - * @param string $password - * @param string $iv - * @param int $length - * @return string - */ - private static function generateSymmetricKey($password, $iv, $length) - { - $symkey = ''; - $iv = substr($iv, 0, 8); - while (strlen($symkey) < $length) { - $symkey.= md5($symkey . $password . $iv, true); - } - return substr($symkey, 0, $length); - } - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - protected static function load($key, $password) - { - if (!is_string($key)) { - return false; - } - - /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is - "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to - protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding - two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here: - - http://tools.ietf.org/html/rfc1421#section-4.6.1.1 - http://tools.ietf.org/html/rfc1421#section-4.6.1.3 - - DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell. - DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation - function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's - own implementation. ie. the implementation *is* the standard and any bugs that may exist in that - implementation are part of the standard, as well. - - * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ - if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { - $iv = Hex::decode(trim($matches[2])); - // remove the Proc-Type / DEK-Info sections as they're no longer needed - $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); - $ciphertext = ASN1::extractBER($key); - if ($ciphertext === false) { - $ciphertext = $key; - } - $crypto = self::getEncryptionObject($matches[1]); - $crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3)); - $crypto->setIV($iv); - $key = $crypto->decrypt($ciphertext); - } else { - if (self::$format != self::MODE_DER) { - $decoded = ASN1::extractBER($key); - if ($decoded !== false) { - $key = $decoded; - } elseif (self::$format == self::MODE_PEM) { - return false; - } - } - } - - return $key; - } - - /** - * Wrap a private key appropriately - * - * @access public - * @param string $key - * @param string $type - * @param string $password - * @return string - */ - protected static function wrapPrivateKey($key, $type, $password) - { - if (empty($password) || !is_string($password)) { - return "-----BEGIN $type PRIVATE KEY-----\r\n" . - chunk_split(Base64::encode($key), 64) . - "-----END $type PRIVATE KEY-----"; - } - - $cipher = self::getEncryptionObject(self::$defaultEncryptionAlgorithm); - $iv = Random::string($cipher->getBlockLength() >> 3); - $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3)); - $cipher->setIV($iv); - $iv = strtoupper(Hex::encode($iv)); - return "-----BEGIN $type PRIVATE KEY-----\r\n" . - "Proc-Type: 4,ENCRYPTED\r\n" . - "DEK-Info: " . self::$defaultEncryptionAlgorithm . ",$iv\r\n" . - "\r\n" . - chunk_split(Base64::encode($cipher->encrypt($key)), 64) . - "-----END $type PRIVATE KEY-----"; - } - - /** - * Wrap a public key appropriately - * - * @access public - * @param string $key - * @param string $type - * @return string - */ - protected static function wrapPublicKey($key, $type) - { - return "-----BEGIN $type PUBLIC KEY-----\r\n" . - chunk_split(Base64::encode($key), 64) . - "-----END $type PUBLIC KEY-----"; - } -} \ No newline at end of file diff --git a/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS8.php b/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS8.php deleted file mode 100644 index ee1859cd33..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/Keys/PKCS8.php +++ /dev/null @@ -1,609 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common\Keys; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Crypt\DES; -use phpseclib\Crypt\RC2; -use phpseclib\Crypt\RC4; -use phpseclib\Crypt\AES; -use phpseclib\Crypt\TripleDES; -use phpseclib\Crypt\Common\BlockCipher; -use phpseclib\Crypt\Random; -use phpseclib\Math\BigInteger; -use phpseclib\File\ASN1; -use phpseclib\File\ASN1\Maps; -use phpseclib\Exception\UnsupportedAlgorithmException; - -/** - * PKCS#8 Formatted Key Handler - * - * @package Common - * @author Jim Wigginton - * @access public - */ -abstract class PKCS8 extends PKCS -{ - /** - * Default encryption algorithm - * - * @var string - * @access private - */ - private static $defaultEncryptionAlgorithm = 'id-PBES2'; - - /** - * Default encryption scheme - * - * Only used when defaultEncryptionAlgorithm is id-PBES2 - * - * @var string - * @access private - */ - private static $defaultEncryptionScheme = 'aes128-CBC-PAD'; - - /** - * Default PRF - * - * Only used when defaultEncryptionAlgorithm is id-PBES2 - * - * @var string - * @access private - */ - private static $defaultPRF = 'id-hmacWithSHA256'; - - /** - * Default Iteration Count - * - * @var int - * @access private - */ - private static $defaultIterationCount = 2048; - - /** - * OIDs loaded - * - * @var bool - * @access private - */ - private static $oidsLoaded = false; - - /** - * Sets the default encryption algorithm - * - * @access public - * @param string $algo - */ - public static function setEncryptionAlgorithm($algo) - { - self::$defaultEncryptionAlgorithm = $algo; - } - - /** - * Sets the default encryption algorithm for PBES2 - * - * @access public - * @param string $algo - */ - public static function setEncryptionScheme($algo) - { - self::$defaultEncryptionScheme = $algo; - } - - /** - * Sets the iteration count - * - * @access public - * @param int $count - */ - public static function setIterationCount($count) - { - self::$defaultIterationCount = $count; - } - - /** - * Sets the PRF for PBES2 - * - * @access public - * @param string $algo - */ - public static function setPRF($algo) - { - self::$defaultPRF = $algo; - } - - /** - * Returns a SymmetricKey object based on a PBES1 $algo - * - * @access public - * @param string $algo - */ - private static function getPBES1EncryptionObject($algo) - { - $algo = preg_match('#^pbeWith(?:MD2|MD5|SHA1|SHA)And(.*?)-CBC$#', $algo, $matches) ? - $matches[1] : - substr($algo, 13); // strlen('pbeWithSHAAnd') == 13 - - switch ($algo) { - case 'DES': - $cipher = new DES(BlockCipher::MODE_CBC); - break; - case 'RC2': - $cipher = new RC2(BlockCipher::MODE_CBC); - break; - case '3-KeyTripleDES': - $cipher = new TripleDES(BlockCipher::MODE_CBC); - break; - case '2-KeyTripleDES': - $cipher = new TripleDES(BlockCipher::MODE_CBC); - $cipher->setKeyLength(128); - break; - case '128BitRC2': - $cipher = new RC2(BlockCipher::MODE_CBC); - $cipher->setKeyLength(128); - break; - case '40BitRC2': - $cipher = new RC2(BlockCipher::MODE_CBC); - $cipher->setKeyLength(40); - break; - case '128BitRC4': - $cipher = new RC4(); - $cipher->setKeyLength(128); - break; - case '40BitRC4': - $cipher = new RC4(); - $cipher->setKeyLength(40); - break; - default: - throw new UnsupportedAlgorithmException("$algo is not a supported algorithm"); - } - - return $cipher; - } - - /** - * Returns a hash based on a PBES1 $algo - * - * @access public - * @param string $algo - */ - private static function getPBES1Hash($algo) - { - if (preg_match('#^pbeWith(MD2|MD5|SHA1|SHA)And.*?-CBC$#', $algo, $matches)) { - return $matches[1] == 'SHA' ? 'sha1' : $matches[1]; - } - - return 'sha1'; - } - - /** - * Returns a KDF baesd on a PBES1 $algo - * - * @access public - * @param string $algo - */ - private static function getPBES1KDF($algo) - { - switch ($algo) { - case 'pbeWithMD2AndDES-CBC': - case 'pbeWithMD2AndRC2-CBC': - case 'pbeWithMD5AndDES-CBC': - case 'pbeWithMD5AndRC2-CBC': - case 'pbeWithSHA1AndDES-CBC': - case 'pbeWithSHA1AndRC2-CBC': - return 'pbkdf1'; - } - - return 'pkcs12'; - } - - /** - * Returns a SymmetricKey object baesd on a PBES2 $algo - * - * @access public - * @param string $algo - */ - private static function getPBES2EncryptionObject($algo) - { - switch ($algo) { - case 'desCBC': - $cipher = new TripleDES(BlockCipher::MODE_CBC); - break; - case 'des-EDE3-CBC': - $cipher = new TripleDES(BlockCipher::MODE_CBC); - break; - case 'rc2CBC': - $cipher = new RC2(BlockCipher::MODE_CBC); - // in theory this can be changed - $cipher->setKeyLength(128); - break; - case 'rc5-CBC-PAD': - throw new UnsupportedAlgorithmException('rc5-CBC-PAD is not supported for PBES2 PKCS#8 keys'); - case 'aes128-CBC-PAD': - case 'aes192-CBC-PAD': - case 'aes256-CBC-PAD': - $cipher = new AES(BlockCipher::MODE_CBC); - $cipher->setKeyLength(substr($algo, 3, 3)); - break; - default: - throw new UnsupportedAlgorithmException("$algo is not supported"); - } - - return $cipher; - } - - /** - * Initialize static variables - * - * @access private - */ - private static function initialize_static_variables() - { - if (!static::$childOIDsLoaded) { - ASN1::loadOIDs([static::OID_VALUE => static::OID_NAME]); - static::$childOIDsLoaded = true; - } - if (!self::$oidsLoaded) { - // from https://tools.ietf.org/html/rfc2898 - ASN1::loadOIDs([ - // PBES1 encryption schemes - '1.2.840.113549.1.5.1' => 'pbeWithMD2AndDES-CBC', - '1.2.840.113549.1.5.4' => 'pbeWithMD2AndRC2-CBC', - '1.2.840.113549.1.5.3' => 'pbeWithMD5AndDES-CBC', - '1.2.840.113549.1.5.6' => 'pbeWithMD5AndRC2-CBC', - '1.2.840.113549.1.5.10'=> 'pbeWithSHA1AndDES-CBC', - '1.2.840.113549.1.5.11'=> 'pbeWithSHA1AndRC2-CBC', - - // from PKCS#12: - // https://tools.ietf.org/html/rfc7292 - '1.2.840.113549.1.12.1.1' => 'pbeWithSHAAnd128BitRC4', - '1.2.840.113549.1.12.1.2' => 'pbeWithSHAAnd40BitRC4', - '1.2.840.113549.1.12.1.3' => 'pbeWithSHAAnd3-KeyTripleDES-CBC', - '1.2.840.113549.1.12.1.4' => 'pbeWithSHAAnd2-KeyTripleDES-CBC', - '1.2.840.113549.1.12.1.5' => 'pbeWithSHAAnd128BitRC2-CBC', - '1.2.840.113549.1.12.1.6' => 'pbeWithSHAAnd40BitRC2-CBC', - - '1.2.840.113549.1.5.12' => 'id-PBKDF2', - '1.2.840.113549.1.5.13' => 'id-PBES2', - '1.2.840.113549.1.5.14' => 'id-PBMAC1', - - // from PKCS#5 v2.1: - // http://www.rsa.com/rsalabs/pkcs/files/h11302-wp-pkcs5v2-1-password-based-cryptography-standard.pdf - '1.2.840.113549.2.7' => 'id-hmacWithSHA1', - '1.2.840.113549.2.8' => 'id-hmacWithSHA224', - '1.2.840.113549.2.9' => 'id-hmacWithSHA256', - '1.2.840.113549.2.10'=> 'id-hmacWithSHA384', - '1.2.840.113549.2.11'=> 'id-hmacWithSHA512', - '1.2.840.113549.2.12'=> 'id-hmacWithSHA512-224', - '1.2.840.113549.2.13'=> 'id-hmacWithSHA512-256', - - '1.3.14.3.2.7' => 'desCBC', - '1.2.840.113549.3.7' => 'des-EDE3-CBC', - '1.2.840.113549.3.2' => 'rc2CBC', - '1.2.840.113549.3.9' => 'rc5-CBC-PAD', - - '2.16.840.1.101.3.4.1.2' => 'aes128-CBC-PAD', - '2.16.840.1.101.3.4.1.22'=> 'aes192-CBC-PAD', - '2.16.840.1.101.3.4.1.42'=> 'aes256-CBC-PAD' - ]); - self::$oidsLoaded = true; - } - } - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - protected static function load($key, $password = '') - { - self::initialize_static_variables(); - - if (!is_string($key)) { - return false; - } - - if (self::$format != self::MODE_DER) { - $decoded = ASN1::extractBER($key); - if ($decoded !== false) { - $key = $decoded; - } elseif (self::$format == self::MODE_PEM) { - return false; - } - } - - $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { - return false; - } - - $meta = []; - - $decrypted = ASN1::asn1map($decoded[0], Maps\EncryptedPrivateKeyInfo::MAP); - if (strlen($password) && is_array($decrypted)) { - $algorithm = $decrypted['encryptionAlgorithm']['algorithm']; - switch ($algorithm) { - // PBES1 - case 'pbeWithMD2AndDES-CBC': - case 'pbeWithMD2AndRC2-CBC': - case 'pbeWithMD5AndDES-CBC': - case 'pbeWithMD5AndRC2-CBC': - case 'pbeWithSHA1AndDES-CBC': - case 'pbeWithSHA1AndRC2-CBC': - case 'pbeWithSHAAnd3-KeyTripleDES-CBC': - case 'pbeWithSHAAnd2-KeyTripleDES-CBC': - case 'pbeWithSHAAnd128BitRC2-CBC': - case 'pbeWithSHAAnd40BitRC2-CBC': - case 'pbeWithSHAAnd128BitRC4': - case 'pbeWithSHAAnd40BitRC4': - $cipher = self::getPBES1EncryptionObject($algorithm); - $hash = self::getPBES1Hash($algorithm); - $kdf = self::getPBES1KDF($algorithm); - - $meta['meta']['algorithm'] = $algorithm; - - $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP)); - $iterationCount = (int) $iterationCount->toString(); - $cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount); - $key = $cipher->decrypt($decrypted['encryptedData']); - $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { - return false; - } - - break; - case 'id-PBES2': - $meta['meta']['algorithm'] = $algorithm; - - $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); - extract($temp); - - $cipher = self::getPBES2EncryptionObject($encryptionScheme['algorithm']); - $meta['meta']['cipher'] = $encryptionScheme['algorithm']; - - $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); - extract($temp); - - if (!$cipher instanceof RC2) { - $cipher->setIV($encryptionScheme['parameters']['octetString']); - } else { - $temp = ASN1::decodeBER($encryptionScheme['parameters']); - extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP)); - $effectiveKeyLength = (int) $rc2ParametersVersion->toString(); - switch ($effectiveKeyLength) { - case 160: - $effectiveKeyLength = 40; - break; - case 120: - $effectiveKeyLength = 64; - break; - case 58: - $effectiveKeyLength = 128; - break; - //default: // should be >= 256 - } - $cipher->setIV($iv); - $cipher->setKeyLength($effectiveKeyLength); - } - - $meta['meta']['keyDerivationFunc'] = $keyDerivationFunc['algorithm']; - switch ($keyDerivationFunc['algorithm']) { - case 'id-PBKDF2': - $temp = ASN1::decodeBER($keyDerivationFunc['parameters']); - $prf = ['algorithm' => 'id-hmacWithSHA1']; - $params = ASN1::asn1map($temp[0], Maps\PBKDF2params::MAP); - extract($params); - $meta['meta']['prf'] = $prf['algorithm']; - $hash = str_replace('-', '/', substr($prf['algorithm'], 11)); - $params = [ - $password, - 'pbkdf2', - $hash, - $salt, - (int) $iterationCount->toString() - ]; - if (isset($keyLength)) { - $params[] = (int) $keyLength->toString(); - } - call_user_func_array([$cipher, 'setPassword'], $params); - $key = $cipher->decrypt($decrypted['encryptedData']); - $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { - return false; - } - break; - default: - throw new UnsupportedAlgorithmException('Only PBKDF2 is supported for PBES2 PKCS#8 keys'); - } - break; - case 'id-PBMAC1': - //$temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - //$value = ASN1::asn1map($temp[0], Maps\PBMAC1params::MAP); - // since i can't find any implementation that does PBMAC1 it is unsupported - throw new UnsupportedAlgorithmException('Only PBES1 and PBES2 PKCS#8 keys are supported.'); - // at this point we'll assume that the key conforms to PublicKeyInfo - } - } - - $private = ASN1::asn1map($decoded[0], Maps\PrivateKeyInfo::MAP); - if (is_array($private)) { - return $private['privateKeyAlgorithm']['algorithm'] == static::OID_NAME ? - $private + $meta : - false; - } - - // EncryptedPrivateKeyInfo and PublicKeyInfo have largely identical "signatures". the only difference - // is that the former has an octet string and the later has a bit string. the first byte of a bit - // string represents the number of bits in the last byte that are to be ignored but, currently, - // bit strings wanting a non-zero amount of bits trimmed are not supported - $public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP); - if (is_array($public)) { - if ($public['publicKey'][0] != "\0" || $public['publicKeyAlgorithm']['algorithm'] != static::OID_NAME) { - return false; - } - $public['publicKey'] = substr($public['publicKey'], 1); - return $public; - } - - return false; - } - - /** - * Wrap a private key appropriately - * - * @access public - * @param string $key - * @param string $attr - * @param mixed $params - * @param string $password - * @return string - */ - protected static function wrapPrivateKey($key, $attr, $params, $password) - { - self::initialize_static_variables(); - - $key = [ - 'version' => 'v1', - 'privateKeyAlgorithm' => [ - 'algorithm' => static::OID_NAME, - 'parameters' => $params - ], - 'privateKey' => $key - ]; - if (!empty($attr)) { - $key['attributes'] = $attr; - } - $key = ASN1::encodeDER($key, Maps\PrivateKeyInfo::MAP); - if (!empty($password) && is_string($password)) { - $salt = Random::string(8); - $iterationCount = self::$defaultIterationCount; - - if (self::$defaultEncryptionAlgorithm == 'id-PBES2') { - $crypto = self::getPBES2EncryptionObject(self::$defaultEncryptionScheme); - $hash = str_replace('-', '/', substr(self::$defaultPRF, 11)); - $kdf = 'pbkdf2'; - $iv = Random::string($crypto->getBlockLength() >> 3); - - $PBKDF2params = [ - 'salt' => $salt, - 'iterationCount' => $iterationCount, - 'prf' => ['algorithm' => self::$defaultPRF, 'parameters' => null] - ]; - $PBKDF2params = ASN1::encodeDER($PBKDF2params, Maps\PBKDF2params::MAP); - - if (!$crypto instanceof RC2) { - $params = ['octetString' => $iv]; - } else { - $params = [ - 'rc2ParametersVersion' => 58, - 'iv' => $iv - ]; - $params = ASN1::encodeDER($params, Maps\RC2CBCParameter::MAP); - $params = new ASN1\Element($params); - } - - $params = [ - 'keyDerivationFunc' => [ - 'algorithm' => 'id-PBKDF2', - 'parameters' => new ASN1\Element($PBKDF2params) - ], - 'encryptionScheme' => [ - 'algorithm' => self::$defaultEncryptionScheme, - 'parameters' => $params - ] - ]; - $params = ASN1::encodeDER($params, Maps\PBES2params::MAP); - - $crypto->setIV($iv); - } else { - $crypto = self::getPBES1EncryptionObject(self::$defaultEncryptionAlgorithm); - $hash = self::getPBES1Hash(self::$defaultEncryptionAlgorithm); - $kdf = self::getPBES1KDF(self::$defaultEncryptionAlgorithm); - - $params = [ - 'salt' => $salt, - 'iterationCount' => $iterationCount - ]; - $params = ASN1::encodeDER($params, Maps\PBEParameter::MAP); - } - $crypto->setPassword($password, $kdf, $hash, $salt, $iterationCount); - $key = $crypto->encrypt($key); - - $key = [ - 'encryptionAlgorithm' => [ - 'algorithm' => self::$defaultEncryptionAlgorithm, - 'parameters' => new ASN1\Element($params) - ], - 'encryptedData' => $key - ]; - - $key = ASN1::encodeDER($key, Maps\EncryptedPrivateKeyInfo::MAP); - - return "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . - chunk_split(Base64::encode($key), 64) . - "-----END ENCRYPTED PRIVATE KEY-----"; - } - - return "-----BEGIN PRIVATE KEY-----\r\n" . - chunk_split(Base64::encode($key), 64) . - "-----END PRIVATE KEY-----"; - } - - /** - * Wrap a public key appropriately - * - * @access public - * @param string $key - * @param mixed $params - * @return string - */ - protected static function wrapPublicKey($key, $params) - { - self::initialize_static_variables(); - - $key = [ - 'publicKeyAlgorithm' => [ - 'algorithm' => static::OID_NAME, - 'parameters' => $params - ], - 'publicKey' => "\0" . $key - ]; - - $key = ASN1::encodeDER($key, Maps\PublicKeyInfo::MAP); - - return "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(Base64::encode($key), 64) . - "-----END PUBLIC KEY-----"; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/Keys/PuTTY.php b/lib/phpaes/phpseclib/Crypt/Common/Keys/PuTTY.php deleted file mode 100644 index 5c3fad1d57..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/Keys/PuTTY.php +++ /dev/null @@ -1,230 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common\Keys; - -use ParagonIE\ConstantTime\Base64; -use ParagonIE\ConstantTime\Hex; -use phpseclib\Crypt\AES; -use phpseclib\Crypt\Hash; -use phpseclib\Crypt\Random; -use phpseclib\Common\Functions\Strings; - -/** - * PuTTY Formatted Key Handler - * - * @package Common - * @author Jim Wigginton - * @access public - */ -abstract class PuTTY -{ - /** - * Default comment - * - * @var string - * @access private - */ - private static $comment = 'phpseclib-generated-key'; - - /** - * Sets the default comment - * - * @access public - * @param string $comment - */ - public static function setComment($comment) - { - self::$comment = str_replace(["\r", "\n"], '', $comment); - } - - /** - * Generate a symmetric key for PuTTY keys - * - * @access public - * @param string $password - * @param int $length - * @return string - */ - private static function generateSymmetricKey($password, $length) - { - $symkey = ''; - $sequence = 0; - while (strlen($symkey) < $length) { - $temp = pack('Na*', $sequence++, $password); - $symkey.= Hex::decode(sha1($temp)); - } - return substr($symkey, 0, $length); - } - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $publicHandler - * @param string $type - * @param string $password - * @return array - */ - protected static function load($key, $password) - { - if (!is_string($key)) { - return false; - } - - if (strpos($key, 'BEGIN SSH2 PUBLIC KEY')) { - $data = preg_split('#[\r\n]+#', $key); - $data = array_splice($data, 2, -1); - $data = implode('', $data); - - $components = call_user_func([static::PUBLIC_HANDLER, 'load'], $data); - if ($components === false) { - return false; - } - - if (!preg_match('#Comment: "(.+)"#', $key, $matches)) { - return false; - } - $components['comment'] = str_replace(['\\\\', '\"'], ['\\', '"'], $matches[1]); - - return $components; - } - - $components = []; - - $key = preg_split('#\r\n|\r|\n#', trim($key)); - $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0])); - if ($type != static::TYPE) { - return false; - } - $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); - $components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2])); - - $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); - $public = Base64::decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); - - $source = Strings::packSSH2('ssss', static::TYPE, $encryption, $components['comment'], $public); - - extract(unpack('Nlength', Strings::shift($public, 4))); - if (Strings::shift($public, $length) != static::TYPE) { - return false; - } - - $components['public'] = $public; - - $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4])); - $private = Base64::decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength)))); - - switch ($encryption) { - case 'aes256-cbc': - $symkey = self::generateSymmetricKey($password, 32); - $crypto = new AES(AES::MODE_CBC); - } - - $hashkey = 'putty-private-key-file-mac-key'; - - if ($encryption != 'none') { - $hashkey.= $password; - $crypto->setKey($symkey); - $crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3)); - $crypto->disablePadding(); - $private = $crypto->decrypt($private); - } - - $source.= Strings::packSSH2('s', $private); - - $hash = new Hash('sha1'); - $hash->setKey(sha1($hashkey, true)); - $hmac = trim(preg_replace('#Private-MAC: (.+)#', '$1', $key[$publicLength + $privateLength + 5])); - $hmac = Hex::decode($hmac); - - if (!Strings::equals($hash->hash($source), $hmac)) { - throw new \UnexpectedValueException('MAC validation error'); - } - - $components['private'] = $private; - - return $components; - } - - /** - * Wrap a private key appropriately - * - * @access private - * @param string $public - * @param string $private - * @param string $password - * @return string - */ - protected static function wrapPrivateKey($public, $private, $password) - { - $key = "PuTTY-User-Key-File-2: " . static::TYPE . "\r\nEncryption: "; - $encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none'; - $key.= $encryption; - $key.= "\r\nComment: " . self::$comment . "\r\n"; - - $public = Strings::packSSH2('s', static::TYPE) . $public; - - $source = Strings::packSSH2('ssss', static::TYPE, $encryption, self::$comment, $public); - - $public = Base64::encode($public); - $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; - $key.= chunk_split($public, 64); - - if (empty($password) && !is_string($password)) { - $source.= Strings::packSSH2('s', $private); - $hashkey = 'putty-private-key-file-mac-key'; - } else { - $private.= Random::string(16 - (strlen($private) & 15)); - $source.= Strings::packSSH2('s', $private); - $crypto = new AES(AES::MODE_CBC); - - $crypto->setKey(self::generateSymmetricKey($password, 32)); - $crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3)); - $crypto->disablePadding(); - $private = $crypto->encrypt($private); - $hashkey = 'putty-private-key-file-mac-key' . $password; - } - - $private = Base64::encode($private); - $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; - $key.= chunk_split($private, 64); - $hash = new Hash('sha1'); - $hash->setKey(sha1($hashkey, true)); - $key.= 'Private-MAC: ' . Hex::encode($hash->hash($source)) . "\r\n"; - - return $key; - } - - /** - * Wrap a public key appropriately - * - * This is basically the format described in RFC 4716 (https://tools.ietf.org/html/rfc4716) - * - * @access private - * @param string $key - * @return string - */ - protected static function wrapPublicKey($key) - { - $key = pack('Na*a*', strlen(static::TYPE), static::TYPE, $key); - $key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" . - 'Comment: "' . str_replace(['\\', '"'], ['\\\\', '\"'], self::$comment) . "\"\r\n" . - chunk_split(Base64::encode($key), 64) . - '---- END SSH2 PUBLIC KEY ----'; - return $key; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/Signature/Raw.php b/lib/phpaes/phpseclib/Crypt/Common/Signature/Raw.php deleted file mode 100644 index 46929eba65..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/Signature/Raw.php +++ /dev/null @@ -1,67 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common\Signature; - -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; - -/** - * Raw Signature Handler - * - * @package Common - * @author Jim Wigginton - * @access public - */ -abstract class Raw -{ - /** - * Loads a signature - * - * @access public - * @param array $key - * @return array - */ - public static function load($sig) - { - switch (true) { - case !is_array($sig): - case !isset($sig['r']) || !isset($sig['s']): - case !$sig['r'] instanceof BigInteger: - case !$sig['s'] instanceof BigInteger: - return false; - } - - return [ - 'r' => $key['r'], - 's' => $key['s'] - ]; - } - - /** - * Returns a signature in the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $r - * @param \phpseclib\Math\BigInteger $s - * @return string - */ - public static function save(BigInteger $r, BigInteger $s) - { - return compact('r', 's'); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/StreamCipher.php b/lib/phpaes/phpseclib/Crypt/Common/StreamCipher.php deleted file mode 100644 index 01b055b2ed..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/StreamCipher.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\Common; - -/** - * Base Class for all stream cipher classes - * - * @package StreamCipher - * @author Jim Wigginton - */ -abstract class StreamCipher extends SymmetricKey -{ -} diff --git a/lib/phpaes/phpseclib/Crypt/Common/SymmetricKey.php b/lib/phpaes/phpseclib/Crypt/Common/SymmetricKey.php deleted file mode 100644 index e2c1d20e7a..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Common/SymmetricKey.php +++ /dev/null @@ -1,2588 +0,0 @@ - - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -//namespace phpseclib\Crypt\Common; -// -//use phpseclib\Crypt\Hash; -//use phpseclib\Common\Functions\Strings; -//use phpseclib\Math\BigInteger; -include PHPAES_ROOT . '/phpseclib/Crypt/Hash.php'; -include PHPAES_ROOT . '/phpseclib/Common/Functions/Strings.php'; -include PHPAES_ROOT . '/phpseclib/Math/BigInteger.php'; - -/** - * Base Class for all \phpseclib\Crypt\* cipher classes - * - * @package Base - * @author Jim Wigginton - * @author Hans-Juergen Petrich - */ -abstract class SymmetricKey -{ - /**#@+ - * @access public - * @see \phpseclib\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib\Crypt\Common\SymmetricKey::decrypt() - */ - /** - * Encrypt / decrypt using the Counter mode. - * - * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 - */ - const MODE_CTR = -1; - /** - * Encrypt / decrypt using the Electronic Code Book mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 - */ - const MODE_ECB = 1; - /** - * Encrypt / decrypt using the Code Book Chaining mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 - */ - const MODE_CBC = 2; - /** - * Encrypt / decrypt using the Cipher Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 - */ - const MODE_CFB = 3; - /** - * Encrypt / decrypt using the Output Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 - */ - const MODE_OFB = 4; - /** - * Encrypt / decrypt using streaming mode. - */ - const MODE_STREAM = 5; - /**#@-*/ - - /**#@+ - * @access private - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - */ - /** - * Base value for the internal implementation $engine switch - */ - const ENGINE_INTERNAL = 1; - /** - * Base value for the eval() implementation $engine switch - */ - const ENGINE_EVAL = 2; - /** - * Base value for the mcrypt implementation $engine switch - */ - const ENGINE_MCRYPT = 3; - /** - * Base value for the mcrypt implementation $engine switch - */ - const ENGINE_OPENSSL = 4; - /**#@-*/ - - /** - * The Encryption Mode - * - * @see self::__construct() - * @var int - * @access private - */ - protected $mode; - - /** - * The Block Length of the block cipher - * - * @var int - * @access private - */ - protected $block_size = 16; - - /** - * The Key - * - * @see self::setKey() - * @var string - * @access private - */ - protected $key = false; - - /** - * The Initialization Vector - * - * @see self::setIV() - * @var string - * @access private - */ - private $iv = false; - - /** - * A "sliding" Initialization Vector - * - * @see self::enableContinuousBuffer() - * @see self::clearBuffers() - * @var string - * @access private - */ - protected $encryptIV; - - /** - * A "sliding" Initialization Vector - * - * @see self::enableContinuousBuffer() - * @see self::clearBuffers() - * @var string - * @access private - */ - protected $decryptIV; - - /** - * Continuous Buffer status - * - * @see self::enableContinuousBuffer() - * @var bool - * @access private - */ - protected $continuousBuffer = false; - - /** - * Encryption buffer for CTR, OFB and CFB modes - * - * @see self::encrypt() - * @see self::clearBuffers() - * @var array - * @access private - */ - private $enbuffer; - - /** - * Decryption buffer for CTR, OFB and CFB modes - * - * @see self::decrypt() - * @see self::clearBuffers() - * @var array - * @access private - */ - private $debuffer; - - /** - * mcrypt resource for encryption - * - * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. - * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. - * - * @see self::encrypt() - * @var resource - * @access private - */ - private $enmcrypt; - - /** - * mcrypt resource for decryption - * - * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. - * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. - * - * @see self::decrypt() - * @var resource - * @access private - */ - private $demcrypt; - - /** - * Does the enmcrypt resource need to be (re)initialized? - * - * @see \phpseclib\Crypt\Twofish::setKey() - * @see \phpseclib\Crypt\Twofish::setIV() - * @var bool - * @access private - */ - private $enchanged = true; - - /** - * Does the demcrypt resource need to be (re)initialized? - * - * @see \phpseclib\Crypt\Twofish::setKey() - * @see \phpseclib\Crypt\Twofish::setIV() - * @var bool - * @access private - */ - private $dechanged = true; - - /** - * mcrypt resource for CFB mode - * - * mcrypt's CFB mode, in (and only in) buffered context, - * is broken, so phpseclib implements the CFB mode by it self, - * even when the mcrypt php extension is available. - * - * In order to do the CFB-mode work (fast) phpseclib - * use a separate ECB-mode mcrypt resource. - * - * @link http://phpseclib.sourceforge.net/cfb-demo.phps - * @see self::encrypt() - * @see self::decrypt() - * @see self::setupMcrypt() - * @var resource - * @access private - */ - private $ecb; - - /** - * Optimizing value while CFB-encrypting - * - * Only relevant if $continuousBuffer enabled - * and $engine == self::ENGINE_MCRYPT - * - * It's faster to re-init $enmcrypt if - * $buffer bytes > $cfb_init_len than - * using the $ecb resource furthermore. - * - * This value depends of the chosen cipher - * and the time it would be needed for it's - * initialization [by mcrypt_generic_init()] - * which, typically, depends on the complexity - * on its internaly Key-expanding algorithm. - * - * @see self::encrypt() - * @var int - * @access private - */ - protected $cfb_init_len = 600; - - /** - * Does internal cipher state need to be (re)initialized? - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @var bool - * @access private - */ - protected $changed = true; - - /** - * Padding status - * - * @see self::enablePadding() - * @var bool - * @access private - */ - private $padding = true; - - /** - * Is the mode one that is paddable? - * - * @see self::__construct() - * @var bool - * @access private - */ - private $paddable = false; - - /** - * Holds which crypt engine internaly should be use, - * which will be determined automatically on __construct() - * - * Currently available $engines are: - * - self::ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required) - * - self::ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required) - * - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required) - * - * @see self::setEngine() - * @see self::encrypt() - * @see self::decrypt() - * @var int - * @access private - */ - protected $engine; - - /** - * Holds the preferred crypt engine - * - * @see self::setEngine() - * @see self::setPreferredEngine() - * @var int - * @access private - */ - private $preferredEngine; - - /** - * The mcrypt specific name of the cipher - * - * Only used if $engine == self::ENGINE_MCRYPT - * - * @link http://www.php.net/mcrypt_module_open - * @link http://www.php.net/mcrypt_list_algorithms - * @see self::setupMcrypt() - * @var string - * @access private - */ - protected $cipher_name_mcrypt; - - /** - * The openssl specific name of the cipher - * - * Only used if $engine == self::ENGINE_OPENSSL - * - * @link http://www.php.net/openssl-get-cipher-methods - * @var string - * @access private - */ - protected $cipher_name_openssl; - - /** - * The openssl specific name of the cipher in ECB mode - * - * If OpenSSL does not support the mode we're trying to use (CTR) - * it can still be emulated with ECB mode. - * - * @link http://www.php.net/openssl-get-cipher-methods - * @var string - * @access private - */ - protected $cipher_name_openssl_ecb; - - /** - * The default salt used by setPassword() - * - * @see self::setPassword() - * @var string - * @access private - */ - private $password_default_salt = 'phpseclib/salt'; - - /** - * The name of the performance-optimized callback function - * - * Used by encrypt() / decrypt() - * only if $engine == self::ENGINE_INTERNAL - * - * @see self::encrypt() - * @see self::decrypt() - * @see self::setupInlineCrypt() - * @see self::$use_inline_crypt - * @var Callback - * @access private - */ - protected $inline_crypt; - - /** - * Holds whether performance-optimized $inline_crypt() can/should be used. - * - * @see self::encrypt() - * @see self::decrypt() - * @see self::inline_crypt - * @var mixed - * @access private - */ - protected $use_inline_crypt; - - /** - * If OpenSSL can be used in ECB but not in CTR we can emulate CTR - * - * @see self::openssl_ctr_process() - * @var bool - * @access private - */ - private $openssl_emulate_ctr = false; - - /** - * Don't truncate / null pad key - * - * @see self::clearBuffers() - * @var bool - * @access private - */ - private $skip_key_adjustment = false; - - /** - * Has the key length explicitly been set or should it be derived from the key, itself? - * - * @see self::setKeyLength() - * @var bool - * @access private - */ - protected $explicit_key_length = false; - - /** - * Default Constructor. - * - * $mode could be: - * - * - self::MODE_ECB - * - * - self::MODE_CBC - * - * - self::MODE_CTR - * - * - self::MODE_CFB - * - * - self::MODE_OFB - * - * @param int $mode - * @access public - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - // $mode dependent settings - switch ($mode) { - case self::MODE_ECB: - case self::MODE_CBC: - $this->paddable = true; - break; - case self::MODE_CTR: - case self::MODE_CFB: - case self::MODE_OFB: - case self::MODE_STREAM: - $this->paddable = false; - break; - default: - throw new \InvalidArgumentException('No valid mode has been specified'); - } - - $this->mode = $mode; - } - - /** - * Sets the initialization vector. - * - * setIV() is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used. - * - * @access public - * @param string $iv - * @throws \LengthException if the IV length isn't equal to the block size - * @throws \InvalidArgumentException if an IV is provided when one shouldn't be - * @internal Can be overwritten by a sub class, but does not have to be - */ - public function setIV($iv) - { - if ($this->mode == self::MODE_ECB) { - throw new \InvalidArgumentException('This mode does not require an IV.'); - } - - if (!$this->usesIV()) { - throw new \InvalidArgumentException('This algorithm does not use an IV.'); - } - - if (strlen($iv) != $this->block_size) { - throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required'); - } - - $this->iv = $iv; - $this->changed = true; - } - - /** - * Returns whether or not the algorithm uses an IV - * - * @access public - * @return bool - */ - public function usesIV() - { - return true; - } - - /** - * Returns the current key length in bits - * - * @access public - * @return int - */ - public function getKeyLength() - { - return $this->key_length << 3; - } - - /** - * Returns the current block length in bits - * - * @access public - * @return int - */ - public function getBlockLength() - { - return $this->block_size << 3; - } - - /** - * Returns the current block length in bytes - * - * @access public - * @return int - */ - public function getBlockLengthInBytes() - { - return $this->block_size; - } - - /** - * Sets the key length. - * - * Keys with explicitly set lengths need to be treated accordingly - * - * @access public - * @param int $length - */ - public function setKeyLength($length) - { - $this->explicit_key_length = $length >> 3; - - if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) { - $this->key = false; - throw new \LengthException('Key has already been set and is not ' .$this->explicit_key_length . ' bytes long'); - } - } - - /** - * Sets the key. - * - * The min/max length(s) of the key depends on the cipher which is used. - * If the key not fits the length(s) of the cipher it will paded with null bytes - * up to the closest valid key length. If the key is more than max length, - * we trim the excess bits. - * - * If the key is not explicitly set, it'll be assumed to be all null bytes. - * - * @access public - * @param string $key - * @internal Could, but not must, extend by the child Crypt_* class - */ - public function setKey($key) - { - if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) { - throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes'); - } - - $this->key = $key; - $this->key_length = strlen($key); - $this->changed = true; - $this->setEngine(); - } - - /** - * Sets the password. - * - * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows: - * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1: - * $hash, $salt, $count, $dkLen - * - * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php - * - * @see Crypt/Hash.php - * @param string $password - * @param string $method - * @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length - * @return bool - * @access public - * @internal Could, but not must, extend by the child Crypt_* class - */ - public function setPassword($password, $method = 'pbkdf2') - { - $key = ''; - - $method = strtolower($method); - switch ($method) { - case 'pkcs12': // from https://tools.ietf.org/html/rfc7292#appendix-B.2 - case 'pbkdf1': - case 'pbkdf2': - $func_args = func_get_args(); - - // Hash function - $hash = isset($func_args[2]) ? strtolower($func_args[2]) : 'sha1'; - $hashObj = new Hash(); - $hashObj->setHash($hash); - - // WPA and WPA2 use the SSID as the salt - $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt; - - // RFC2898#section-4.2 uses 1,000 iterations by default - // WPA and WPA2 use 4,096. - $count = isset($func_args[4]) ? $func_args[4] : 1000; - - // Keylength - if (isset($func_args[5])) { - $dkLen = $func_args[5]; - } else { - $key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length; - $dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length; - } - - switch (true) { - case $method == 'pkcs12': - /* - In this specification, however, all passwords are created from - BMPStrings with a NULL terminator. This means that each character in - the original BMPString is encoded in 2 bytes in big-endian format - (most-significant byte first). There are no Unicode byte order - marks. The 2 bytes produced from the last character in the BMPString - are followed by 2 additional bytes with the value 0x00. - - -- https://tools.ietf.org/html/rfc7292#appendix-B.1 - */ - $password = "\0". chunk_split($password, 1, "\0") . "\0"; - - /* - This standard specifies 3 different values for the ID byte mentioned - above: - - 1. If ID=1, then the pseudorandom bits being produced are to be used - as key material for performing encryption or decryption. - - 2. If ID=2, then the pseudorandom bits being produced are to be used - as an IV (Initial Value) for encryption or decryption. - - 3. If ID=3, then the pseudorandom bits being produced are to be used - as an integrity key for MACing. - */ - // Construct a string, D (the "diversifier"), by concatenating v/8 - // copies of ID. - $blockLength = $hashObj->getBlockLengthInBytes(); - $d1 = str_repeat(chr(1), $blockLength); - $d2 = str_repeat(chr(2), $blockLength); - $s = ''; - if (strlen($salt)) { - while (strlen($s) < $blockLength) { - $s.= $salt; - } - } - $s = substr($s, 0, $blockLength); - - $p = ''; - if (strlen($password)) { - while (strlen($p) < $blockLength) { - $p.= $password; - } - } - $p = substr($p, 0, $blockLength); - - $i = $s . $p; - - $this->setKey(self::pkcs12helper($dkLen, $hashObj, $i, $d1, $count)); - if ($this->usesIV()) { - $this->setIV(self::pkcs12helper($this->block_size, $hashObj, $i, $d2, $count)); - } - - return true; - case $method == 'pbkdf1': - if ($dkLen > $hashObj->getLengthInBytes()) { - throw new \LengthException('Derived key length cannot be longer than the hash length'); - } - $t = $password . $salt; - for ($i = 0; $i < $count; ++$i) { - $t = $hashObj->hash($t); - } - $key = substr($t, 0, $dkLen); - - $this->setKey(substr($key, 0, $dkLen >> 1)); - if ($this->usesIV()) { - $this->setIV(substr($key, $dkLen >> 1)); - } - - return true; - case !function_exists('hash_pbkdf2'): - case !function_exists('hash_algos'): - case !in_array($hash, hash_algos()): - $i = 1; - $hashObj->setKey($password); - while (strlen($key) < $dkLen) { - $f = $u = $hashObj->hash($salt . pack('N', $i++)); - for ($j = 2; $j <= $count; ++$j) { - $u = $hashObj->hash($u); - $f^= $u; - } - $key.= $f; - } - $key = substr($key, 0, $dkLen); - break; - default: - $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true); - } - break; - default: - throw new \InvalidArgumentException($method . ' is not a supported password hashing method'); - } - - $this->setKey($key); - - return true; - } - - /** - * PKCS#12 KDF Helper Function - * - * As discussed here: - * - * {@link https://tools.ietf.org/html/rfc7292#appendix-B} - * - * @see self::setPassword() - * @access private - * @param int $n - * @param \phpseclib\Crypt\Hash $hashObj - * @param string $i - * @param string $d - * @param int $count - * @return string $a - */ - private static function pkcs12helper($n, $hashObj, $i, $d, $count) - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - $blockLength = $hashObj->getBlockLength() >> 3; - - $c = ceil($n / $hashObj->getLengthInBytes()); - $a = ''; - for ($j = 1; $j <= $c; $j++) { - $ai = $d . $i; - for ($k = 0; $k < $count; $k++) { - $ai = $hashObj->hash($ai); - } - $b = ''; - while (strlen($b) < $blockLength) { - $b.= $ai; - } - $b = substr($b, 0, $blockLength); - $b = new BigInteger($b, 256); - $newi = ''; - for ($k = 0; $k < strlen($i); $k+= $blockLength) { - $temp = substr($i, $k, $blockLength); - $temp = new BigInteger($temp, 256); - $temp->setPrecision($blockLength << 3); - $temp = $temp->add($b); - $temp = $temp->add($one); - $newi.= $temp->toBytes(false); - } - $i = $newi; - $a.= $ai; - } - - return substr($a, 0, $n); - } - - /** - * Encrypts a message. - * - * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher - * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's - * necessary are discussed in the following - * URL: - * - * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html} - * - * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does. - * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that - * length. - * - * @see self::decrypt() - * @access public - * @param string $plaintext - * @return string $ciphertext - * @internal Could, but not must, extend by the child Crypt_* class - */ - public function encrypt($plaintext) - { - if ($this->paddable) { - $plaintext = $this->pad($plaintext); - } - - if ($this->engine === self::ENGINE_OPENSSL) { - if ($this->changed) { - $this->clearBuffers(); - $this->changed = false; - } - switch ($this->mode) { - case self::MODE_STREAM: - return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - case self::MODE_ECB: - return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - case self::MODE_CBC: - $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV); - if ($this->continuousBuffer) { - $this->encryptIV = substr($result, -$this->block_size); - } - return $result; - case self::MODE_CTR: - return $this->openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer); - case self::MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - $ciphertext = ''; - if ($this->continuousBuffer) { - $iv = &$this->encryptIV; - $pos = &$this->enbuffer['pos']; - } else { - $iv = $this->encryptIV; - $pos = 0; - } - $len = strlen($plaintext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $this->block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - $plaintext = substr($plaintext, $i); - } - - $overflow = $len % $this->block_size; - - if ($overflow) { - $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $iv = Strings::pop($ciphertext, $this->block_size); - - $size = $len - $overflow; - $block = $iv ^ substr($plaintext, -$overflow); - $iv = substr_replace($iv, $block, 0, $overflow); - $ciphertext.= $block; - $pos = $overflow; - } elseif ($len) { - $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $iv = substr($ciphertext, -$this->block_size); - } - - return $ciphertext; - case self::MODE_OFB: - return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer); - } - } - - if ($this->engine === self::ENGINE_MCRYPT) { - if ($this->changed) { - $this->setupMcrypt(); - $this->changed = false; - } - if ($this->enchanged) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV)); - $this->enchanged = false; - } - - // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} - // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's - // rewritten CFB implementation the above outputs the same thing twice. - if ($this->mode == self::MODE_CFB && $this->continuousBuffer) { - $block_size = $this->block_size; - $iv = &$this->encryptIV; - $pos = &$this->enbuffer['pos']; - $len = strlen($plaintext); - $ciphertext = ''; - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - $this->enbuffer['enmcrypt_init'] = true; - } - if ($len >= $block_size) { - if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { - if ($this->enbuffer['enmcrypt_init'] === true) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $iv); - $this->enbuffer['enmcrypt_init'] = false; - } - $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); - $iv = substr($ciphertext, -$block_size); - $len%= $block_size; - } else { - while ($len >= $block_size) { - $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); - $ciphertext.= $iv; - $len-= $block_size; - $i+= $block_size; - } - } - } - - if ($len) { - $iv = @mcrypt_generic($this->ecb, $iv); - $block = $iv ^ substr($plaintext, -$len); - $iv = substr_replace($iv, $block, 0, $len); - $ciphertext.= $block; - $pos = $len; - } - - return $ciphertext; - } - - $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext); - - if (!$this->continuousBuffer) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV)); - } - - return $ciphertext; - } - - if ($this->changed) { - $this->setup(); - $this->changed = false; - } - if ($this->engine === self::ENGINE_EVAL) { - $inline = $this->inline_crypt; - return $inline('encrypt', $plaintext); - } - - $buffer = &$this->enbuffer; - $block_size = $this->block_size; - $ciphertext = ''; - switch ($this->mode) { - case self::MODE_ECB: - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $ciphertext.= $this->encryptBlock(substr($plaintext, $i, $block_size)); - } - break; - case self::MODE_CBC: - $xor = $this->encryptIV; - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - $block = $this->encryptBlock($block ^ $xor); - $xor = $block; - $ciphertext.= $block; - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - } - break; - case self::MODE_CTR: - $xor = $this->encryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'].= $this->encryptBlock($xor); - } - $this->increment_str($xor); - $key = Strings::shift($buffer['ciphertext'], $block_size); - $ciphertext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - $key = $this->encryptBlock($xor); - $this->increment_str($xor); - $ciphertext.= $block ^ $key; - } - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - break; - case self::MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - if ($this->continuousBuffer) { - $iv = &$this->encryptIV; - $pos = &$buffer['pos']; - } else { - $iv = $this->encryptIV; - $pos = 0; - } - $len = strlen($plaintext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - } - while ($len >= $block_size) { - $iv = $this->encryptBlock($iv) ^ substr($plaintext, $i, $block_size); - $ciphertext.= $iv; - $len-= $block_size; - $i+= $block_size; - } - if ($len) { - $iv = $this->encryptBlock($iv); - $block = $iv ^ substr($plaintext, $i); - $iv = substr_replace($iv, $block, 0, $len); - $ciphertext.= $block; - $pos = $len; - } - break; - case self::MODE_OFB: - $xor = $this->encryptIV; - if (strlen($buffer['xor'])) { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['xor'])) { - $xor = $this->encryptBlock($xor); - $buffer['xor'].= $xor; - } - $key = Strings::shift($buffer['xor'], $block_size); - $ciphertext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $xor = $this->encryptBlock($xor); - $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor; - } - $key = $xor; - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; - } - } - break; - case self::MODE_STREAM: - $ciphertext = $this->encryptBlock($plaintext); - break; - } - - return $ciphertext; - } - - /** - * Decrypts a message. - * - * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until - * it is. - * - * @see self::encrypt() - * @access public - * @param string $ciphertext - * @return string $plaintext - * @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size - * @internal Could, but not must, extend by the child Crypt_* class - */ - public function decrypt($ciphertext) - { - if ($this->paddable && strlen($ciphertext) % $this->block_size) { - throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')'); - } - - if ($this->engine === self::ENGINE_OPENSSL) { - if ($this->changed) { - $this->clearBuffers(); - $this->changed = false; - } - switch ($this->mode) { - case self::MODE_STREAM: - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - break; - case self::MODE_ECB: - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - break; - case self::MODE_CBC: - $offset = $this->block_size; - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV); - if ($this->continuousBuffer) { - $this->decryptIV = substr($ciphertext, -$offset, $this->block_size); - } - break; - case self::MODE_CTR: - $plaintext = $this->openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer); - break; - case self::MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - $plaintext = ''; - if ($this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$this->buffer['pos']; - } else { - $iv = $this->decryptIV; - $pos = 0; - } - $len = strlen($ciphertext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $this->block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - $ciphertext = substr($ciphertext, $i); - } - $overflow = $len % $this->block_size; - if ($overflow) { - $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - if ($len - $overflow) { - $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow); - } - $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $plaintext.= $iv ^ substr($ciphertext, -$overflow); - $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow); - $pos = $overflow; - } elseif ($len) { - $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $iv = substr($ciphertext, -$this->block_size); - } - break; - case self::MODE_OFB: - $plaintext = $this->openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer); - } - - return $this->paddable ? $this->unpad($plaintext) : $plaintext; - } - - if ($this->engine === self::ENGINE_MCRYPT) { - $block_size = $this->block_size; - if ($this->changed) { - $this->setupMcrypt(); - $this->changed = false; - } - if ($this->dechanged) { - @mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV)); - $this->dechanged = false; - } - - if ($this->mode == self::MODE_CFB && $this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$this->debuffer['pos']; - $len = strlen($ciphertext); - $plaintext = ''; - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - } - if ($len >= $block_size) { - $cb = substr($ciphertext, $i, $len - $len % $block_size); - $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; - $iv = substr($cb, -$block_size); - $len%= $block_size; - } - if ($len) { - $iv = @mcrypt_generic($this->ecb, $iv); - $plaintext.= $iv ^ substr($ciphertext, -$len); - $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); - $pos = $len; - } - - return $plaintext; - } - - $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext); - - if (!$this->continuousBuffer) { - @mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV)); - } - - return $this->paddable ? $this->unpad($plaintext) : $plaintext; - } - - if ($this->changed) { - $this->setup(); - $this->changed = false; - } - if ($this->engine === self::ENGINE_EVAL) { - $inline = $this->inline_crypt; - return $inline('decrypt', $ciphertext); - } - - $block_size = $this->block_size; - - $buffer = &$this->debuffer; - $plaintext = ''; - switch ($this->mode) { - case self::MODE_ECB: - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $plaintext.= $this->decryptBlock(substr($ciphertext, $i, $block_size)); - } - break; - case self::MODE_CBC: - $xor = $this->decryptIV; - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - $plaintext.= $this->decryptBlock($block) ^ $xor; - $xor = $block; - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - } - break; - case self::MODE_CTR: - $xor = $this->decryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'].= $this->encryptBlock($xor); - } - $this->increment_str($xor); - $key = Strings::shift($buffer['ciphertext'], $block_size); - $plaintext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - $key = $this->encryptBlock($xor); - $this->increment_str($xor); - $plaintext.= $block ^ $key; - } - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - if ($start = strlen($ciphertext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - break; - case self::MODE_CFB: - if ($this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$buffer['pos']; - } else { - $iv = $this->decryptIV; - $pos = 0; - } - $len = strlen($ciphertext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - } - while ($len >= $block_size) { - $iv = $this->encryptBlock($iv); - $cb = substr($ciphertext, $i, $block_size); - $plaintext.= $iv ^ $cb; - $iv = $cb; - $len-= $block_size; - $i+= $block_size; - } - if ($len) { - $iv = $this->encryptBlock($iv); - $plaintext.= $iv ^ substr($ciphertext, $i); - $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len); - $pos = $len; - } - break; - case self::MODE_OFB: - $xor = $this->decryptIV; - if (strlen($buffer['xor'])) { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - if (strlen($block) > strlen($buffer['xor'])) { - $xor = $this->encryptBlock($xor); - $buffer['xor'].= $xor; - } - $key = Strings::shift($buffer['xor'], $block_size); - $plaintext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $xor = $this->encryptBlock($xor); - $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor; - } - $key = $xor; - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - if ($start = strlen($ciphertext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; - } - } - break; - case self::MODE_STREAM: - $plaintext = $this->decryptBlock($ciphertext); - break; - } - return $this->paddable ? $this->unpad($plaintext) : $plaintext; - } - - /** - * Get the IV - * - * mcrypt requires an IV even if ECB is used - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $iv - * @return string - * @access private - */ - public function getIV($iv) - { - return $this->mode == self::MODE_ECB ? str_repeat("\0", $this->block_size) : $iv; - } - - /** - * OpenSSL CTR Processor - * - * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream - * for CTR is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() - * and SymmetricKey::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this - * function will emulate CTR with ECB when necesary. - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string - * @access private - */ - private function openssl_ctr_process($plaintext, &$encryptIV, &$buffer) - { - $ciphertext = ''; - - $block_size = $this->block_size; - $key = $this->key; - - if ($this->openssl_emulate_ctr) { - $xor = $encryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'].= openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - } - $this->increment_str($xor); - $otp = Strings::shift($buffer['ciphertext'], $block_size); - $ciphertext.= $block ^ $otp; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - $this->increment_str($xor); - $ciphertext.= $block ^ $otp; - } - } - if ($this->continuousBuffer) { - $encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - - return $ciphertext; - } - - if (strlen($buffer['ciphertext'])) { - $ciphertext = $plaintext ^ Strings::shift($buffer['ciphertext'], strlen($plaintext)); - $plaintext = substr($plaintext, strlen($ciphertext)); - - if (!strlen($plaintext)) { - return $ciphertext; - } - } - - $overflow = strlen($plaintext) % $block_size; - if ($overflow) { - $plaintext2 = Strings::pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2 - $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - $temp = Strings::pop($encrypted, $block_size); - $ciphertext.= $encrypted . ($plaintext2 ^ $temp); - if ($this->continuousBuffer) { - $buffer['ciphertext'] = substr($temp, $overflow); - $encryptIV = $temp; - } - } elseif (!strlen($buffer['ciphertext'])) { - $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - $temp = Strings::pop($ciphertext, $block_size); - if ($this->continuousBuffer) { - $encryptIV = $temp; - } - } - if ($this->continuousBuffer) { - $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - if ($overflow) { - $this->increment_str($encryptIV); - } - } - - return $ciphertext; - } - - /** - * OpenSSL OFB Processor - * - * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream - * for OFB is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() - * and SymmetricKey::decrypt(). - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string - * @access private - */ - private function openssl_ofb_process($plaintext, &$encryptIV, &$buffer) - { - if (strlen($buffer['xor'])) { - $ciphertext = $plaintext ^ $buffer['xor']; - $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext)); - $plaintext = substr($plaintext, strlen($ciphertext)); - } else { - $ciphertext = ''; - } - - $block_size = $this->block_size; - - $len = strlen($plaintext); - $key = $this->key; - $overflow = $len % $block_size; - - if (strlen($plaintext)) { - if ($overflow) { - $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - $xor = Strings::pop($ciphertext, $block_size); - if ($this->continuousBuffer) { - $encryptIV = $xor; - } - $ciphertext.= Strings::shift($xor, $overflow) ^ substr($plaintext, -$overflow); - if ($this->continuousBuffer) { - $buffer['xor'] = $xor; - } - } else { - $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - if ($this->continuousBuffer) { - $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size); - } - } - } - - return $ciphertext; - } - - /** - * phpseclib <-> OpenSSL Mode Mapper - * - * May need to be overwritten by classes extending this one in some cases - * - * @return int - * @access private - */ - protected function openssl_translate_mode() - { - switch ($this->mode) { - case self::MODE_ECB: - return 'ecb'; - case self::MODE_CBC: - return 'cbc'; - case self::MODE_CTR: - return 'ctr'; - case self::MODE_CFB: - return 'cfb'; - case self::MODE_OFB: - return 'ofb'; - } - } - - /** - * Pad "packets". - * - * Block ciphers working by encrypting between their specified [$this->]block_size at a time - * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to - * pad the input so that it is of the proper length. - * - * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH, - * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping - * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is - * transmitted separately) - * - * @see self::disablePadding() - * @access public - */ - public function enablePadding() - { - $this->padding = true; - } - - /** - * Do not pad packets. - * - * @see self::enablePadding() - * @access public - */ - public function disablePadding() - { - $this->padding = false; - } - - /** - * Treat consecutive "packets" as if they are a continuous buffer. - * - * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets - * will yield different outputs: - * - * - * echo $rijndael->encrypt(substr($plaintext, 0, 16)); - * echo $rijndael->encrypt(substr($plaintext, 16, 16)); - * - * - * echo $rijndael->encrypt($plaintext); - * - * - * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates - * another, as demonstrated with the following: - * - * - * $rijndael->encrypt(substr($plaintext, 0, 16)); - * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); - * - * - * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); - * - * - * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different - * outputs. The reason is due to the fact that the initialization vector's change after every encryption / - * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. - * - * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\*() object changes after each - * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that - * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), - * however, they are also less intuitive and more likely to cause you problems. - * - * @see self::disableContinuousBuffer() - * @access public - * @internal Could, but not must, extend by the child Crypt_* class - */ - public function enableContinuousBuffer() - { - if ($this->mode == self::MODE_ECB) { - return; - } - - $this->continuousBuffer = true; - - $this->setEngine(); - } - - /** - * Treat consecutive packets as if they are a discontinuous buffer. - * - * The default behavior. - * - * @see self::enableContinuousBuffer() - * @access public - * @internal Could, but not must, extend by the child Crypt_* class - */ - public function disableContinuousBuffer() - { - if ($this->mode == self::MODE_ECB) { - return; - } - if (!$this->continuousBuffer) { - return; - } - - $this->continuousBuffer = false; - $this->changed = true; - - $this->setEngine(); - } - - /** - * Test for engine validity - * - * @see self::__construct() - * @param int $engine - * @access public - * @return bool - */ - public function isValidEngine($engine) - { - switch ($engine) { - case self::ENGINE_OPENSSL: - if ($this->mode == self::MODE_STREAM && $this->continuousBuffer) { - return false; - } - $this->openssl_emulate_ctr = false; - $result = $this->cipher_name_openssl && - extension_loaded('openssl'); - if (!$result) { - return false; - } - - $methods = openssl_get_cipher_methods(); - if (in_array($this->cipher_name_openssl, $methods)) { - return true; - } - // not all of openssl's symmetric cipher's support ctr. for those - // that don't we'll emulate it - switch ($this->mode) { - case self::MODE_CTR: - if (in_array($this->cipher_name_openssl_ecb, $methods)) { - $this->openssl_emulate_ctr = true; - return true; - } - } - return false; - case self::ENGINE_MCRYPT: - return $this->cipher_name_mcrypt && - extension_loaded('mcrypt') && - in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms()); - case self::ENGINE_EVAL: - return method_exists($this, 'setupInlineCrypt'); - case self::ENGINE_INTERNAL: - return true; - } - - return false; - } - - /** - * Sets the preferred crypt engine - * - * Currently, $engine could be: - * - * - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_OPENSSL [very fast] - * - * - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_MCRYPT [fast] - * - * - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_EVAL [slow] - * - * - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_INTERNAL [slowest] - * - * If the preferred crypt engine is not available the fastest available one will be used - * - * @see self::__construct() - * @param int $engine - * @access public - */ - public function setPreferredEngine($engine) - { - switch ($engine) { - //case self::ENGINE_OPENSSL; - case self::ENGINE_MCRYPT: - case self::ENGINE_INTERNAL: - case self::ENGINE_EVAL: - $this->preferredEngine = $engine; - break; - default: - $this->preferredEngine = self::ENGINE_OPENSSL; - } - - $this->setEngine(); - } - - /** - * Returns the engine currently being utilized - * - * @see self::setEngine() - * @access public - */ - public function getEngine() - { - return $this->engine; - } - - /** - * Sets the engine as appropriate - * - * @see self::__construct() - * @access private - */ - protected function setEngine() - { - $this->engine = null; - - $candidateEngines = array( - $this->preferredEngine, - //self::ENGINE_OPENSSL, // php 5.4+ can use this option. - self::ENGINE_MCRYPT, - //self::ENGINE_EVAL // php 5.3+ can use this option. - ); - foreach ($candidateEngines as $engine) { - if ($this->isValidEngine($engine)) { - $this->engine = $engine; - break; - } - } - if (!$this->engine) { - $this->engine = self::ENGINE_INTERNAL; - } - - if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) { - // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed, - // (re)open them with the module named in $this->cipher_name_mcrypt - @mcrypt_module_close($this->enmcrypt); - @mcrypt_module_close($this->demcrypt); - $this->enmcrypt = null; - $this->demcrypt = null; - - if ($this->ecb) { - @mcrypt_module_close($this->ecb); - $this->ecb = null; - } - } - - $this->changed = true; - } - - /** - * Encrypts a block - * - * Note: Must be extended by the child \phpseclib\Crypt\* class - * - * @access private - * @param string $in - * @return string - */ - abstract protected function encryptBlock($in); - - /** - * Decrypts a block - * - * Note: Must be extended by the child \phpseclib\Crypt\* class - * - * @access private - * @param string $in - * @return string - */ - abstract protected function decryptBlock($in); - - /** - * Setup the key (expansion) - * - * Only used if $engine == self::ENGINE_INTERNAL - * - * Note: Must extend by the child \phpseclib\Crypt\* class - * - * @see self::setup() - * @access private - */ - abstract protected function setupKey(); - - /** - * Setup the self::ENGINE_INTERNAL $engine - * - * (re)init, if necessary, the internal cipher $engine and flush all $buffers - * Used (only) if $engine == self::ENGINE_INTERNAL - * - * _setup() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setIV() - * - * - disableContinuousBuffer() - * - * - First run of encrypt() / decrypt() with no init-settings - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @access private - * @internal setup() is always called before en/decryption. - * @internal Could, but not must, extend by the child Crypt_* class - */ - protected function setup() - { - $this->clearBuffers(); - $this->setupKey(); - - if ($this->engine === self::ENGINE_EVAL) { - $this->setupInlineCrypt(); - } - } - - /** - * Setup the self::ENGINE_MCRYPT $engine - * - * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers - * Used (only) if $engine = self::ENGINE_MCRYPT - * - * _setupMcrypt() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setIV() - * - * - disableContinuousBuffer() - * - * - First run of encrypt() / decrypt() - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @access private - * @internal Could, but not must, extend by the child Crypt_* class - */ - private function setupMcrypt() - { - $this->clearBuffers(); - $this->enchanged = $this->dechanged = true; - - if (!isset($this->enmcrypt)) { - static $mcrypt_modes = array( - self::MODE_CTR => 'ctr', - self::MODE_ECB => MCRYPT_MODE_ECB, - self::MODE_CBC => MCRYPT_MODE_CBC, - self::MODE_CFB => 'ncfb', - self::MODE_OFB => MCRYPT_MODE_NOFB, - self::MODE_STREAM => MCRYPT_MODE_STREAM, - ); - - $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); - $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); - - // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer() - // to workaround mcrypt's broken ncfb implementation in buffered mode - // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} - if ($this->mode == self::MODE_CFB) { - $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); - } - } // else should mcrypt_generic_deinit be called? - - if ($this->mode == self::MODE_CFB) { - @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); - } - } - - /** - * Pads a string - * - * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize. - * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to - * chr($this->block_size - (strlen($text) % $this->block_size) - * - * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless - * and padding will, hence forth, be enabled. - * - * @see self::unpad() - * @param string $text - * @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size - * @access private - * @return string - */ - protected function pad($text) - { - $length = strlen($text); - - if (!$this->padding) { - if ($length % $this->block_size == 0) { - return $text; - } else { - throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding."); - } - } - - $pad = $this->block_size - ($length % $this->block_size); - - return str_pad($text, $length + $pad, chr($pad)); - } - - /** - * Unpads a string. - * - * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong - * and false will be returned. - * - * @see self::pad() - * @param string $text - * @throws \LengthException if the ciphertext's length is not a multiple of the block size - * @access private - * @return string - */ - protected function unpad($text) - { - if (!$this->padding) { - return $text; - } - - $length = ord($text[strlen($text) - 1]); - - if (!$length || $length > $this->block_size) { - throw new \LengthException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})"); - } - - return substr($text, 0, -$length); - } - - /** - * Clears internal buffers - * - * Clearing/resetting the internal buffers is done everytime - * after disableContinuousBuffer() or on cipher $engine (re)init - * ie after setKey() or setIV() - * - * @access private - * @internal Could, but not must, extend by the child Crypt_* class - * @throws \UnexpectedValueException when an IV is required but not defined - */ - private function clearBuffers() - { - $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true); - - if ($this->iv === false && !in_array($this->mode, array(self::MODE_STREAM, self::MODE_ECB))) { - throw new \UnexpectedValueException('No IV has been defined'); - } - - $this->encryptIV = $this->decryptIV = $this->iv; - } - - /** - * Increment the current string - * - * @see self::decrypt() - * @see self::encrypt() - * @param string $var - * @access private - */ - protected function increment_str(&$var) - { - for ($i = 4; $i <= strlen($var); $i+= 4) { - $temp = substr($var, -$i, 4); - switch ($temp) { - case "\xFF\xFF\xFF\xFF": - $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4); - break; - case "\x7F\xFF\xFF\xFF": - $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4); - return; - default: - $temp = unpack('Nnum', $temp); - $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4); - return; - } - } - - $remainder = strlen($var) % 4; - - if ($remainder == 0) { - return; - } - - $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT)); - $temp = substr(pack('N', $temp['num'] + 1), -$remainder); - $var = substr_replace($var, $temp, 0, $remainder); - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * Stores the created (or existing) callback function-name - * in $this->inline_crypt - * - * Internally for phpseclib developers: - * - * _setupInlineCrypt() would be called only if: - * - * - $this->engine === self::ENGINE_EVAL - * - * - each time on _setup(), after(!) _setupKey() - * - * - * This ensures that _setupInlineCrypt() has always a - * full ready2go initializated internal cipher $engine state - * where, for example, the keys allready expanded, - * keys/block_size calculated and such. - * - * It is, each time if called, the responsibility of _setupInlineCrypt(): - * - * - to set $this->inline_crypt to a valid and fully working callback function - * as a (faster) replacement for encrypt() / decrypt() - * - * - NOT to create unlimited callback functions (for memory reasons!) - * no matter how often _setupInlineCrypt() would be called. At some - * point of amount they must be generic re-useable. - * - * - the code of _setupInlineCrypt() it self, - * and the generated callback code, - * must be, in following order: - * - 100% safe - * - 100% compatible to encrypt()/decrypt() - * - using only php5+ features/lang-constructs/php-extensions if - * compatibility (down to php4) or fallback is provided - * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-) - * - >= 10% faster than encrypt()/decrypt() [which is, by the way, - * the reason for the existence of _setupInlineCrypt() :-)] - * - memory-nice - * - short (as good as possible) - * - * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code. - * - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib\Crypt\* class. - * - The following variable names are reserved: - * - $_* (all variable names prefixed with an underscore) - * - $self (object reference to it self. Do not use $this, but $self instead) - * - $in (the content of $in has to en/decrypt by the generated code) - * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only - * - * - * @see self::setup() - * @see self::createInlineCryptFunction() - * @see self::encrypt() - * @see self::decrypt() - * @access private - * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt() - */ - //protected function setupInlineCrypt(); - - /** - * Creates the performance-optimized function for en/decrypt() - * - * Internally for phpseclib developers: - * - * _createInlineCryptFunction(): - * - * - merge the $cipher_code [setup'ed by _setupInlineCrypt()] - * with the current [$this->]mode of operation code - * - * - create the $inline function, which called by encrypt() / decrypt() - * as its replacement to speed up the en/decryption operations. - * - * - return the name of the created $inline callback function - * - * - used to speed up en/decryption - * - * - * - * The main reason why can speed up things [up to 50%] this way are: - * - * - using variables more effective then regular. - * (ie no use of expensive arrays but integers $k_0, $k_1 ... - * or even, for example, the pure $key[] values hardcoded) - * - * - avoiding 1000's of function calls of ie _encryptBlock() - * but inlining the crypt operations. - * in the mode of operation for() loop. - * - * - full loop unroll the (sometimes key-dependent) rounds - * avoiding this way ++$i counters and runtime-if's etc... - * - * The basic code architectur of the generated $inline en/decrypt() - * lambda function, in pseudo php, is: - * - * - * +----------------------------------------------------------------------------------------------+ - * | callback $inline = create_function: | - * | lambda_function_0001_crypt_ECB($action, $text) | - * | { | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_crypt']; // general init code. | - * | // ie: $sbox'es declarations used for | - * | // encrypt and decrypt'ing. | - * | | - * | switch ($action) { | - * | case 'encrypt': | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_encrypt']; // encrypt sepcific init code. | - * | ie: specified $key or $box | - * | declarations for encrypt'ing. | - * | | - * | foreach ($ciphertext) { | - * | $in = $block_size of $ciphertext; | - * | | - * | INSERT PHP CODE OF: | - * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: | - * | // strlen($in) == $this->block_size | - * | // here comes the cipher algorithm in action | - * | // for encryption. | - * | // $cipher_code['encrypt_block'] has to | - * | // encrypt the content of the $in variable | - * | | - * | $plaintext .= $in; | - * | } | - * | return $plaintext; | - * | | - * | case 'decrypt': | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_decrypt']; // decrypt sepcific init code | - * | ie: specified $key or $box | - * | declarations for decrypt'ing. | - * | foreach ($plaintext) { | - * | $in = $block_size of $plaintext; | - * | | - * | INSERT PHP CODE OF: | - * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always | - * | // strlen($in) == $this->block_size | - * | // here comes the cipher algorithm in action | - * | // for decryption. | - * | // $cipher_code['decrypt_block'] has to | - * | // decrypt the content of the $in variable | - * | $ciphertext .= $in; | - * | } | - * | return $ciphertext; | - * | } | - * | } | - * +----------------------------------------------------------------------------------------------+ - * - * - * See also the \phpseclib\Crypt\*::_setupInlineCrypt()'s for - * productive inline $cipher_code's how they works. - * - * Structure of: - * - * $cipher_code = [ - * 'init_crypt' => (string) '', // optional - * 'init_encrypt' => (string) '', // optional - * 'init_decrypt' => (string) '', // optional - * 'encrypt_block' => (string) '', // required - * 'decrypt_block' => (string) '' // required - * ]; - * - * - * @see self::setupInlineCrypt() - * @see self::encrypt() - * @see self::decrypt() - * @param array $cipher_code - * @access private - * @return string (the name of the created callback function) - */ - protected function createInlineCryptFunction($cipher_code) - { - $block_size = $this->block_size; - - // optional - $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : ''; - $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : ''; - $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : ''; - // required - $encrypt_block = $cipher_code['encrypt_block']; - $decrypt_block = $cipher_code['decrypt_block']; - - // Generating mode of operation inline code, - // merged with the $cipher_code algorithm - // for encrypt- and decryption. - switch ($this->mode) { - case self::MODE_ECB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $in = substr($_text, $_i, '.$block_size.'); - '.$encrypt_block.' - $_ciphertext.= $in; - } - - return $_ciphertext; - '; - - $decrypt = $init_decrypt . ' - $_plaintext = ""; - $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0)); - $_ciphertext_len = strlen($_text); - - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $in = substr($_text, $_i, '.$block_size.'); - '.$decrypt_block.' - $_plaintext.= $in; - } - - return $this->unpad($_plaintext); - '; - break; - case self::MODE_CTR: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - $_xor = $this->encryptIV; - $_buffer = &$this->enbuffer; - if (strlen($_buffer["ciphertext"])) { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["ciphertext"])) { - $in = $_xor; - '.$encrypt_block.' - $this->increment_str($_xor); - $_buffer["ciphertext"].= $in; - } - $_key = \phpseclib\Common\Functions\Strings::shift($_buffer["ciphertext"], '.$block_size.'); - $_ciphertext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - $in = $_xor; - '.$encrypt_block.' - $this->increment_str($_xor); - $_key = $in; - $_ciphertext.= $_block ^ $_key; - } - } - if ($this->continuousBuffer) { - $this->encryptIV = $_xor; - if ($_start = $_plaintext_len % '.$block_size.') { - $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; - } - } - - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_ciphertext_len = strlen($_text); - $_xor = $this->decryptIV; - $_buffer = &$this->debuffer; - - if (strlen($_buffer["ciphertext"])) { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["ciphertext"])) { - $in = $_xor; - '.$encrypt_block.' - $this->increment_str($_xor); - $_buffer["ciphertext"].= $in; - } - $_key = \phpseclib\Common\Functions\Strings::shift($_buffer["ciphertext"], '.$block_size.'); - $_plaintext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - $in = $_xor; - '.$encrypt_block.' - $this->increment_str($_xor); - $_key = $in; - $_plaintext.= $_block ^ $_key; - } - } - if ($this->continuousBuffer) { - $this->decryptIV = $_xor; - if ($_start = $_ciphertext_len % '.$block_size.') { - $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; - } - } - - return $_plaintext; - '; - break; - case self::MODE_CFB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_buffer = &$this->enbuffer; - - if ($this->continuousBuffer) { - $_iv = &$this->encryptIV; - $_pos = &$_buffer["pos"]; - } else { - $_iv = $this->encryptIV; - $_pos = 0; - } - $_len = strlen($_text); - $_i = 0; - if ($_pos) { - $_orig_pos = $_pos; - $_max = '.$block_size.' - $_pos; - if ($_len >= $_max) { - $_i = $_max; - $_len-= $_max; - $_pos = 0; - } else { - $_i = $_len; - $_pos+= $_len; - $_len = 0; - } - $_ciphertext = substr($_iv, $_orig_pos) ^ $_text; - $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i); - } - while ($_len >= '.$block_size.') { - $in = $_iv; - '.$encrypt_block.'; - $_iv = $in ^ substr($_text, $_i, '.$block_size.'); - $_ciphertext.= $_iv; - $_len-= '.$block_size.'; - $_i+= '.$block_size.'; - } - if ($_len) { - $in = $_iv; - '.$encrypt_block.' - $_iv = $in; - $_block = $_iv ^ substr($_text, $_i); - $_iv = substr_replace($_iv, $_block, 0, $_len); - $_ciphertext.= $_block; - $_pos = $_len; - } - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_buffer = &$this->debuffer; - - if ($this->continuousBuffer) { - $_iv = &$this->decryptIV; - $_pos = &$_buffer["pos"]; - } else { - $_iv = $this->decryptIV; - $_pos = 0; - } - $_len = strlen($_text); - $_i = 0; - if ($_pos) { - $_orig_pos = $_pos; - $_max = '.$block_size.' - $_pos; - if ($_len >= $_max) { - $_i = $_max; - $_len-= $_max; - $_pos = 0; - } else { - $_i = $_len; - $_pos+= $_len; - $_len = 0; - } - $_plaintext = substr($_iv, $_orig_pos) ^ $_text; - $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i); - } - while ($_len >= '.$block_size.') { - $in = $_iv; - '.$encrypt_block.' - $_iv = $in; - $cb = substr($_text, $_i, '.$block_size.'); - $_plaintext.= $_iv ^ $cb; - $_iv = $cb; - $_len-= '.$block_size.'; - $_i+= '.$block_size.'; - } - if ($_len) { - $in = $_iv; - '.$encrypt_block.' - $_iv = $in; - $_plaintext.= $_iv ^ substr($_text, $_i); - $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len); - $_pos = $_len; - } - - return $_plaintext; - '; - break; - case self::MODE_OFB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - $_xor = $this->encryptIV; - $_buffer = &$this->enbuffer; - - if (strlen($_buffer["xor"])) { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["xor"])) { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_buffer["xor"].= $_xor; - } - $_key = \phpseclib\Common\Functions\Strings::shift($_buffer["xor"], '.$block_size.'); - $_ciphertext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor; - } - $_key = $_xor; - } - if ($this->continuousBuffer) { - $this->encryptIV = $_xor; - if ($_start = $_plaintext_len % '.$block_size.') { - $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; - } - } - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_ciphertext_len = strlen($_text); - $_xor = $this->decryptIV; - $_buffer = &$this->debuffer; - - if (strlen($_buffer["xor"])) { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["xor"])) { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_buffer["xor"].= $_xor; - } - $_key = \phpseclib\Common\Functions\Strings::shift($_buffer["xor"], '.$block_size.'); - $_plaintext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor; - } - $_key = $_xor; - } - if ($this->continuousBuffer) { - $this->decryptIV = $_xor; - if ($_start = $_ciphertext_len % '.$block_size.') { - $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; - } - } - return $_plaintext; - '; - break; - case self::MODE_STREAM: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - '.$encrypt_block.' - return $_ciphertext; - '; - $decrypt = $init_decrypt . ' - $_plaintext = ""; - '.$decrypt_block.' - return $_plaintext; - '; - break; - // case self::MODE_CBC: - default: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - - $in = $this->encryptIV; - - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $in = substr($_text, $_i, '.$block_size.') ^ $in; - '.$encrypt_block.' - $_ciphertext.= $in; - } - - if ($this->continuousBuffer) { - $this->encryptIV = $in; - } - - return $_ciphertext; - '; - - $decrypt = $init_decrypt . ' - $_plaintext = ""; - $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0)); - $_ciphertext_len = strlen($_text); - - $_iv = $this->decryptIV; - - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $in = $_block = substr($_text, $_i, '.$block_size.'); - '.$decrypt_block.' - $_plaintext.= $in ^ $_iv; - $_iv = $_block; - } - - if ($this->continuousBuffer) { - $this->decryptIV = $_iv; - } - - return $this->unpad($_plaintext); - '; - break; - } - - eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};'); - - return \Closure::bind($func, $this, $this->getClassContext()); - } - - /** - * Returns the class that defines the private methods - * - * @access private - * @return string - */ - protected function getClassContext() - { - return get_called_class(); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DES.php b/lib/phpaes/phpseclib/Crypt/DES.php deleted file mode 100644 index 6b3fc8c39b..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DES.php +++ /dev/null @@ -1,1408 +0,0 @@ - - * setKey('abcdefgh'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $des->decrypt($des->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package DES - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use phpseclib\Crypt\Common\BlockCipher; - -/** - * Pure-PHP implementation of DES. - * - * @package DES - * @author Jim Wigginton - * @access public - */ -class DES extends BlockCipher -{ - /**#@+ - * @access private - * @see \phpseclib\Crypt\DES::setupKey() - * @see \phpseclib\Crypt\DES::processBlock() - */ - /** - * Contains $keys[self::ENCRYPT] - */ - const ENCRYPT = 0; - /** - * Contains $keys[self::DECRYPT] - */ - const DECRYPT = 1; - /**#@-*/ - - /** - * Block Length of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::block_size - * @var int - * @access private - */ - protected $block_size = 8; - - /** - * Key Length (in bytes) - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setKeyLength() - * @var int - * @access private - */ - protected $key_length = 8; - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - * @access private - */ - protected $cipher_name_mcrypt = 'des'; - - /** - * The OpenSSL names of the cipher / modes - * - * @see \phpseclib\Crypt\Common\SymmetricKey::openssl_mode_names - * @var array - * @access private - */ - protected $openssl_mode_names = [ - self::MODE_ECB => 'des-ecb', - self::MODE_CBC => 'des-cbc', - self::MODE_CFB => 'des-cfb', - self::MODE_OFB => 'des-ofb' - // self::MODE_CTR is undefined for DES - ]; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - * @access private - */ - protected $cfb_init_len = 500; - - /** - * Switch for DES/3DES encryption - * - * Used only if $engine == self::ENGINE_INTERNAL - * - * @see self::setupKey() - * @see self::processBlock() - * @var int - * @access private - */ - protected $des_rounds = 1; - - /** - * max possible size of $key - * - * @see self::setKey() - * @var string - * @access private - */ - protected $key_length_max = 8; - - /** - * The Key Schedule - * - * @see self::setupKey() - * @var array - * @access private - */ - private $keys; - - /** - * Shuffle table. - * - * For each byte value index, the entry holds an 8-byte string - * with each byte containing all bits in the same state as the - * corresponding bit in the index value. - * - * @see self::processBlock() - * @see self::setupKey() - * @var array - * @access private - */ - private $shuffle = [ - "\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xFF", - "\x00\x00\x00\x00\x00\x00\xFF\x00", "\x00\x00\x00\x00\x00\x00\xFF\xFF", - "\x00\x00\x00\x00\x00\xFF\x00\x00", "\x00\x00\x00\x00\x00\xFF\x00\xFF", - "\x00\x00\x00\x00\x00\xFF\xFF\x00", "\x00\x00\x00\x00\x00\xFF\xFF\xFF", - "\x00\x00\x00\x00\xFF\x00\x00\x00", "\x00\x00\x00\x00\xFF\x00\x00\xFF", - "\x00\x00\x00\x00\xFF\x00\xFF\x00", "\x00\x00\x00\x00\xFF\x00\xFF\xFF", - "\x00\x00\x00\x00\xFF\xFF\x00\x00", "\x00\x00\x00\x00\xFF\xFF\x00\xFF", - "\x00\x00\x00\x00\xFF\xFF\xFF\x00", "\x00\x00\x00\x00\xFF\xFF\xFF\xFF", - "\x00\x00\x00\xFF\x00\x00\x00\x00", "\x00\x00\x00\xFF\x00\x00\x00\xFF", - "\x00\x00\x00\xFF\x00\x00\xFF\x00", "\x00\x00\x00\xFF\x00\x00\xFF\xFF", - "\x00\x00\x00\xFF\x00\xFF\x00\x00", "\x00\x00\x00\xFF\x00\xFF\x00\xFF", - "\x00\x00\x00\xFF\x00\xFF\xFF\x00", "\x00\x00\x00\xFF\x00\xFF\xFF\xFF", - "\x00\x00\x00\xFF\xFF\x00\x00\x00", "\x00\x00\x00\xFF\xFF\x00\x00\xFF", - "\x00\x00\x00\xFF\xFF\x00\xFF\x00", "\x00\x00\x00\xFF\xFF\x00\xFF\xFF", - "\x00\x00\x00\xFF\xFF\xFF\x00\x00", "\x00\x00\x00\xFF\xFF\xFF\x00\xFF", - "\x00\x00\x00\xFF\xFF\xFF\xFF\x00", "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF", - "\x00\x00\xFF\x00\x00\x00\x00\x00", "\x00\x00\xFF\x00\x00\x00\x00\xFF", - "\x00\x00\xFF\x00\x00\x00\xFF\x00", "\x00\x00\xFF\x00\x00\x00\xFF\xFF", - "\x00\x00\xFF\x00\x00\xFF\x00\x00", "\x00\x00\xFF\x00\x00\xFF\x00\xFF", - "\x00\x00\xFF\x00\x00\xFF\xFF\x00", "\x00\x00\xFF\x00\x00\xFF\xFF\xFF", - "\x00\x00\xFF\x00\xFF\x00\x00\x00", "\x00\x00\xFF\x00\xFF\x00\x00\xFF", - "\x00\x00\xFF\x00\xFF\x00\xFF\x00", "\x00\x00\xFF\x00\xFF\x00\xFF\xFF", - "\x00\x00\xFF\x00\xFF\xFF\x00\x00", "\x00\x00\xFF\x00\xFF\xFF\x00\xFF", - "\x00\x00\xFF\x00\xFF\xFF\xFF\x00", "\x00\x00\xFF\x00\xFF\xFF\xFF\xFF", - "\x00\x00\xFF\xFF\x00\x00\x00\x00", "\x00\x00\xFF\xFF\x00\x00\x00\xFF", - "\x00\x00\xFF\xFF\x00\x00\xFF\x00", "\x00\x00\xFF\xFF\x00\x00\xFF\xFF", - "\x00\x00\xFF\xFF\x00\xFF\x00\x00", "\x00\x00\xFF\xFF\x00\xFF\x00\xFF", - "\x00\x00\xFF\xFF\x00\xFF\xFF\x00", "\x00\x00\xFF\xFF\x00\xFF\xFF\xFF", - "\x00\x00\xFF\xFF\xFF\x00\x00\x00", "\x00\x00\xFF\xFF\xFF\x00\x00\xFF", - "\x00\x00\xFF\xFF\xFF\x00\xFF\x00", "\x00\x00\xFF\xFF\xFF\x00\xFF\xFF", - "\x00\x00\xFF\xFF\xFF\xFF\x00\x00", "\x00\x00\xFF\xFF\xFF\xFF\x00\xFF", - "\x00\x00\xFF\xFF\xFF\xFF\xFF\x00", "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF", - "\x00\xFF\x00\x00\x00\x00\x00\x00", "\x00\xFF\x00\x00\x00\x00\x00\xFF", - "\x00\xFF\x00\x00\x00\x00\xFF\x00", "\x00\xFF\x00\x00\x00\x00\xFF\xFF", - "\x00\xFF\x00\x00\x00\xFF\x00\x00", "\x00\xFF\x00\x00\x00\xFF\x00\xFF", - "\x00\xFF\x00\x00\x00\xFF\xFF\x00", "\x00\xFF\x00\x00\x00\xFF\xFF\xFF", - "\x00\xFF\x00\x00\xFF\x00\x00\x00", "\x00\xFF\x00\x00\xFF\x00\x00\xFF", - "\x00\xFF\x00\x00\xFF\x00\xFF\x00", "\x00\xFF\x00\x00\xFF\x00\xFF\xFF", - "\x00\xFF\x00\x00\xFF\xFF\x00\x00", "\x00\xFF\x00\x00\xFF\xFF\x00\xFF", - "\x00\xFF\x00\x00\xFF\xFF\xFF\x00", "\x00\xFF\x00\x00\xFF\xFF\xFF\xFF", - "\x00\xFF\x00\xFF\x00\x00\x00\x00", "\x00\xFF\x00\xFF\x00\x00\x00\xFF", - "\x00\xFF\x00\xFF\x00\x00\xFF\x00", "\x00\xFF\x00\xFF\x00\x00\xFF\xFF", - "\x00\xFF\x00\xFF\x00\xFF\x00\x00", "\x00\xFF\x00\xFF\x00\xFF\x00\xFF", - "\x00\xFF\x00\xFF\x00\xFF\xFF\x00", "\x00\xFF\x00\xFF\x00\xFF\xFF\xFF", - "\x00\xFF\x00\xFF\xFF\x00\x00\x00", "\x00\xFF\x00\xFF\xFF\x00\x00\xFF", - "\x00\xFF\x00\xFF\xFF\x00\xFF\x00", "\x00\xFF\x00\xFF\xFF\x00\xFF\xFF", - "\x00\xFF\x00\xFF\xFF\xFF\x00\x00", "\x00\xFF\x00\xFF\xFF\xFF\x00\xFF", - "\x00\xFF\x00\xFF\xFF\xFF\xFF\x00", "\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF", - "\x00\xFF\xFF\x00\x00\x00\x00\x00", "\x00\xFF\xFF\x00\x00\x00\x00\xFF", - "\x00\xFF\xFF\x00\x00\x00\xFF\x00", "\x00\xFF\xFF\x00\x00\x00\xFF\xFF", - "\x00\xFF\xFF\x00\x00\xFF\x00\x00", "\x00\xFF\xFF\x00\x00\xFF\x00\xFF", - "\x00\xFF\xFF\x00\x00\xFF\xFF\x00", "\x00\xFF\xFF\x00\x00\xFF\xFF\xFF", - "\x00\xFF\xFF\x00\xFF\x00\x00\x00", "\x00\xFF\xFF\x00\xFF\x00\x00\xFF", - "\x00\xFF\xFF\x00\xFF\x00\xFF\x00", "\x00\xFF\xFF\x00\xFF\x00\xFF\xFF", - "\x00\xFF\xFF\x00\xFF\xFF\x00\x00", "\x00\xFF\xFF\x00\xFF\xFF\x00\xFF", - "\x00\xFF\xFF\x00\xFF\xFF\xFF\x00", "\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF", - "\x00\xFF\xFF\xFF\x00\x00\x00\x00", "\x00\xFF\xFF\xFF\x00\x00\x00\xFF", - "\x00\xFF\xFF\xFF\x00\x00\xFF\x00", "\x00\xFF\xFF\xFF\x00\x00\xFF\xFF", - "\x00\xFF\xFF\xFF\x00\xFF\x00\x00", "\x00\xFF\xFF\xFF\x00\xFF\x00\xFF", - "\x00\xFF\xFF\xFF\x00\xFF\xFF\x00", "\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF", - "\x00\xFF\xFF\xFF\xFF\x00\x00\x00", "\x00\xFF\xFF\xFF\xFF\x00\x00\xFF", - "\x00\xFF\xFF\xFF\xFF\x00\xFF\x00", "\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF", - "\x00\xFF\xFF\xFF\xFF\xFF\x00\x00", "\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF", - "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - "\xFF\x00\x00\x00\x00\x00\x00\x00", "\xFF\x00\x00\x00\x00\x00\x00\xFF", - "\xFF\x00\x00\x00\x00\x00\xFF\x00", "\xFF\x00\x00\x00\x00\x00\xFF\xFF", - "\xFF\x00\x00\x00\x00\xFF\x00\x00", "\xFF\x00\x00\x00\x00\xFF\x00\xFF", - "\xFF\x00\x00\x00\x00\xFF\xFF\x00", "\xFF\x00\x00\x00\x00\xFF\xFF\xFF", - "\xFF\x00\x00\x00\xFF\x00\x00\x00", "\xFF\x00\x00\x00\xFF\x00\x00\xFF", - "\xFF\x00\x00\x00\xFF\x00\xFF\x00", "\xFF\x00\x00\x00\xFF\x00\xFF\xFF", - "\xFF\x00\x00\x00\xFF\xFF\x00\x00", "\xFF\x00\x00\x00\xFF\xFF\x00\xFF", - "\xFF\x00\x00\x00\xFF\xFF\xFF\x00", "\xFF\x00\x00\x00\xFF\xFF\xFF\xFF", - "\xFF\x00\x00\xFF\x00\x00\x00\x00", "\xFF\x00\x00\xFF\x00\x00\x00\xFF", - "\xFF\x00\x00\xFF\x00\x00\xFF\x00", "\xFF\x00\x00\xFF\x00\x00\xFF\xFF", - "\xFF\x00\x00\xFF\x00\xFF\x00\x00", "\xFF\x00\x00\xFF\x00\xFF\x00\xFF", - "\xFF\x00\x00\xFF\x00\xFF\xFF\x00", "\xFF\x00\x00\xFF\x00\xFF\xFF\xFF", - "\xFF\x00\x00\xFF\xFF\x00\x00\x00", "\xFF\x00\x00\xFF\xFF\x00\x00\xFF", - "\xFF\x00\x00\xFF\xFF\x00\xFF\x00", "\xFF\x00\x00\xFF\xFF\x00\xFF\xFF", - "\xFF\x00\x00\xFF\xFF\xFF\x00\x00", "\xFF\x00\x00\xFF\xFF\xFF\x00\xFF", - "\xFF\x00\x00\xFF\xFF\xFF\xFF\x00", "\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF", - "\xFF\x00\xFF\x00\x00\x00\x00\x00", "\xFF\x00\xFF\x00\x00\x00\x00\xFF", - "\xFF\x00\xFF\x00\x00\x00\xFF\x00", "\xFF\x00\xFF\x00\x00\x00\xFF\xFF", - "\xFF\x00\xFF\x00\x00\xFF\x00\x00", "\xFF\x00\xFF\x00\x00\xFF\x00\xFF", - "\xFF\x00\xFF\x00\x00\xFF\xFF\x00", "\xFF\x00\xFF\x00\x00\xFF\xFF\xFF", - "\xFF\x00\xFF\x00\xFF\x00\x00\x00", "\xFF\x00\xFF\x00\xFF\x00\x00\xFF", - "\xFF\x00\xFF\x00\xFF\x00\xFF\x00", "\xFF\x00\xFF\x00\xFF\x00\xFF\xFF", - "\xFF\x00\xFF\x00\xFF\xFF\x00\x00", "\xFF\x00\xFF\x00\xFF\xFF\x00\xFF", - "\xFF\x00\xFF\x00\xFF\xFF\xFF\x00", "\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF", - "\xFF\x00\xFF\xFF\x00\x00\x00\x00", "\xFF\x00\xFF\xFF\x00\x00\x00\xFF", - "\xFF\x00\xFF\xFF\x00\x00\xFF\x00", "\xFF\x00\xFF\xFF\x00\x00\xFF\xFF", - "\xFF\x00\xFF\xFF\x00\xFF\x00\x00", "\xFF\x00\xFF\xFF\x00\xFF\x00\xFF", - "\xFF\x00\xFF\xFF\x00\xFF\xFF\x00", "\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF", - "\xFF\x00\xFF\xFF\xFF\x00\x00\x00", "\xFF\x00\xFF\xFF\xFF\x00\x00\xFF", - "\xFF\x00\xFF\xFF\xFF\x00\xFF\x00", "\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF", - "\xFF\x00\xFF\xFF\xFF\xFF\x00\x00", "\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF", - "\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF", - "\xFF\xFF\x00\x00\x00\x00\x00\x00", "\xFF\xFF\x00\x00\x00\x00\x00\xFF", - "\xFF\xFF\x00\x00\x00\x00\xFF\x00", "\xFF\xFF\x00\x00\x00\x00\xFF\xFF", - "\xFF\xFF\x00\x00\x00\xFF\x00\x00", "\xFF\xFF\x00\x00\x00\xFF\x00\xFF", - "\xFF\xFF\x00\x00\x00\xFF\xFF\x00", "\xFF\xFF\x00\x00\x00\xFF\xFF\xFF", - "\xFF\xFF\x00\x00\xFF\x00\x00\x00", "\xFF\xFF\x00\x00\xFF\x00\x00\xFF", - "\xFF\xFF\x00\x00\xFF\x00\xFF\x00", "\xFF\xFF\x00\x00\xFF\x00\xFF\xFF", - "\xFF\xFF\x00\x00\xFF\xFF\x00\x00", "\xFF\xFF\x00\x00\xFF\xFF\x00\xFF", - "\xFF\xFF\x00\x00\xFF\xFF\xFF\x00", "\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF", - "\xFF\xFF\x00\xFF\x00\x00\x00\x00", "\xFF\xFF\x00\xFF\x00\x00\x00\xFF", - "\xFF\xFF\x00\xFF\x00\x00\xFF\x00", "\xFF\xFF\x00\xFF\x00\x00\xFF\xFF", - "\xFF\xFF\x00\xFF\x00\xFF\x00\x00", "\xFF\xFF\x00\xFF\x00\xFF\x00\xFF", - "\xFF\xFF\x00\xFF\x00\xFF\xFF\x00", "\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF", - "\xFF\xFF\x00\xFF\xFF\x00\x00\x00", "\xFF\xFF\x00\xFF\xFF\x00\x00\xFF", - "\xFF\xFF\x00\xFF\xFF\x00\xFF\x00", "\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF", - "\xFF\xFF\x00\xFF\xFF\xFF\x00\x00", "\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF", - "\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF", - "\xFF\xFF\xFF\x00\x00\x00\x00\x00", "\xFF\xFF\xFF\x00\x00\x00\x00\xFF", - "\xFF\xFF\xFF\x00\x00\x00\xFF\x00", "\xFF\xFF\xFF\x00\x00\x00\xFF\xFF", - "\xFF\xFF\xFF\x00\x00\xFF\x00\x00", "\xFF\xFF\xFF\x00\x00\xFF\x00\xFF", - "\xFF\xFF\xFF\x00\x00\xFF\xFF\x00", "\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF", - "\xFF\xFF\xFF\x00\xFF\x00\x00\x00", "\xFF\xFF\xFF\x00\xFF\x00\x00\xFF", - "\xFF\xFF\xFF\x00\xFF\x00\xFF\x00", "\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF", - "\xFF\xFF\xFF\x00\xFF\xFF\x00\x00", "\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF", - "\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF", - "\xFF\xFF\xFF\xFF\x00\x00\x00\x00", "\xFF\xFF\xFF\xFF\x00\x00\x00\xFF", - "\xFF\xFF\xFF\xFF\x00\x00\xFF\x00", "\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF", - "\xFF\xFF\xFF\xFF\x00\xFF\x00\x00", "\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF", - "\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF", - "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", "\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF", - "\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF", - "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF", - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - ]; - - /** - * IP mapping helper table. - * - * Indexing this table with each source byte performs the initial bit permutation. - * - * @var array - * @access private - */ - private $ipmap = [ - 0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x21, 0x31, - 0x02, 0x12, 0x03, 0x13, 0x22, 0x32, 0x23, 0x33, - 0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71, - 0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73, - 0x04, 0x14, 0x05, 0x15, 0x24, 0x34, 0x25, 0x35, - 0x06, 0x16, 0x07, 0x17, 0x26, 0x36, 0x27, 0x37, - 0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75, - 0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77, - 0x80, 0x90, 0x81, 0x91, 0xA0, 0xB0, 0xA1, 0xB1, - 0x82, 0x92, 0x83, 0x93, 0xA2, 0xB2, 0xA3, 0xB3, - 0xC0, 0xD0, 0xC1, 0xD1, 0xE0, 0xF0, 0xE1, 0xF1, - 0xC2, 0xD2, 0xC3, 0xD3, 0xE2, 0xF2, 0xE3, 0xF3, - 0x84, 0x94, 0x85, 0x95, 0xA4, 0xB4, 0xA5, 0xB5, - 0x86, 0x96, 0x87, 0x97, 0xA6, 0xB6, 0xA7, 0xB7, - 0xC4, 0xD4, 0xC5, 0xD5, 0xE4, 0xF4, 0xE5, 0xF5, - 0xC6, 0xD6, 0xC7, 0xD7, 0xE6, 0xF6, 0xE7, 0xF7, - 0x08, 0x18, 0x09, 0x19, 0x28, 0x38, 0x29, 0x39, - 0x0A, 0x1A, 0x0B, 0x1B, 0x2A, 0x3A, 0x2B, 0x3B, - 0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79, - 0x4A, 0x5A, 0x4B, 0x5B, 0x6A, 0x7A, 0x6B, 0x7B, - 0x0C, 0x1C, 0x0D, 0x1D, 0x2C, 0x3C, 0x2D, 0x3D, - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4C, 0x5C, 0x4D, 0x5D, 0x6C, 0x7C, 0x6D, 0x7D, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x88, 0x98, 0x89, 0x99, 0xA8, 0xB8, 0xA9, 0xB9, - 0x8A, 0x9A, 0x8B, 0x9B, 0xAA, 0xBA, 0xAB, 0xBB, - 0xC8, 0xD8, 0xC9, 0xD9, 0xE8, 0xF8, 0xE9, 0xF9, - 0xCA, 0xDA, 0xCB, 0xDB, 0xEA, 0xFA, 0xEB, 0xFB, - 0x8C, 0x9C, 0x8D, 0x9D, 0xAC, 0xBC, 0xAD, 0xBD, - 0x8E, 0x9E, 0x8F, 0x9F, 0xAE, 0xBE, 0xAF, 0xBF, - 0xCC, 0xDC, 0xCD, 0xDD, 0xEC, 0xFC, 0xED, 0xFD, - 0xCE, 0xDE, 0xCF, 0xDF, 0xEE, 0xFE, 0xEF, 0xFF - ]; - - /** - * Inverse IP mapping helper table. - * Indexing this table with a byte value reverses the bit order. - * - * @var array - * @access private - */ - private $invipmap = [ - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, - 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, - 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, - 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, - 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, - 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, - 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, - 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, - 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, - 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, - 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, - 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, - 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, - 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF - ]; - - /** - * Pre-permuted S-box1 - * - * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the - * P table: concatenation can then be replaced by exclusive ORs. - * - * @var array - * @access private - */ - private $sbox1 = [ - 0x00808200, 0x00000000, 0x00008000, 0x00808202, - 0x00808002, 0x00008202, 0x00000002, 0x00008000, - 0x00000200, 0x00808200, 0x00808202, 0x00000200, - 0x00800202, 0x00808002, 0x00800000, 0x00000002, - 0x00000202, 0x00800200, 0x00800200, 0x00008200, - 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, - 0x00000000, 0x00000202, 0x00008202, 0x00800000, - 0x00008000, 0x00808202, 0x00000002, 0x00808000, - 0x00808200, 0x00800000, 0x00800000, 0x00000200, - 0x00808002, 0x00008000, 0x00008200, 0x00800002, - 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, - 0x00800002, 0x00000202, 0x00008202, 0x00808200, - 0x00000202, 0x00800200, 0x00800200, 0x00000000, - 0x00008002, 0x00008200, 0x00000000, 0x00808002 - ]; - - /** - * Pre-permuted S-box2 - * - * @var array - * @access private - */ - private $sbox2 = [ - 0x40084010, 0x40004000, 0x00004000, 0x00084010, - 0x00080000, 0x00000010, 0x40080010, 0x40004010, - 0x40000010, 0x40084010, 0x40084000, 0x40000000, - 0x40004000, 0x00080000, 0x00000010, 0x40080010, - 0x00084000, 0x00080010, 0x40004010, 0x00000000, - 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, - 0x00004010, 0x40084000, 0x40080000, 0x00004010, - 0x00000000, 0x00084010, 0x40080010, 0x00080000, - 0x40004010, 0x40080000, 0x40084000, 0x00004000, - 0x40080000, 0x40004000, 0x00000010, 0x40084010, - 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, - 0x00080010, 0x40004010, 0x40000010, 0x00080010, - 0x00084000, 0x00000000, 0x40004000, 0x00004010, - 0x40000000, 0x40080010, 0x40084010, 0x00084000 - ]; - - /** - * Pre-permuted S-box3 - * - * @var array - * @access private - */ - private $sbox3 = [ - 0x00000104, 0x04010100, 0x00000000, 0x04010004, - 0x04000100, 0x00000000, 0x00010104, 0x04000100, - 0x00010004, 0x04000004, 0x04000004, 0x00010000, - 0x04010104, 0x00010004, 0x04010000, 0x00000104, - 0x04000000, 0x00000004, 0x04010100, 0x00000100, - 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, - 0x00000004, 0x04010104, 0x00000100, 0x04000000, - 0x04010100, 0x04000000, 0x00010004, 0x00000104, - 0x00010000, 0x04010100, 0x04000100, 0x00000000, - 0x00000100, 0x00010004, 0x04010104, 0x04000100, - 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, - 0x00000004, 0x00010104, 0x00010100, 0x04000004, - 0x04010000, 0x04000104, 0x00000104, 0x04010000, - 0x00010104, 0x00000004, 0x04010004, 0x00010100 - ]; - - /** - * Pre-permuted S-box4 - * - * @var array - * @access private - */ - private $sbox4 = [ - 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x00401040, 0x80400040, 0x80400000, 0x80001000, - 0x00000000, 0x00401000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00400040, 0x80400000, - 0x80000000, 0x00001000, 0x00400000, 0x80401000, - 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, - 0x00001000, 0x00401040, 0x80401040, 0x80000040, - 0x00400040, 0x80400000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00000000, 0x00401000, - 0x00001040, 0x00400040, 0x80400040, 0x80000000, - 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, - 0x80400000, 0x80001000, 0x00401040, 0x80400040, - 0x80001000, 0x00001040, 0x00400000, 0x80401000, - 0x00000040, 0x00400000, 0x00001000, 0x00401040 - ]; - - /** - * Pre-permuted S-box5 - * - * @var array - * @access private - */ - private $sbox5 = [ - 0x00000080, 0x01040080, 0x01040000, 0x21000080, - 0x00040000, 0x00000080, 0x20000000, 0x01040000, - 0x20040080, 0x00040000, 0x01000080, 0x20040080, - 0x21000080, 0x21040000, 0x00040080, 0x20000000, - 0x01000000, 0x20040000, 0x20040000, 0x00000000, - 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, - 0x01040080, 0x01000000, 0x21000000, 0x00040080, - 0x00040000, 0x21000080, 0x00000080, 0x01000000, - 0x20000000, 0x01040000, 0x21000080, 0x20040080, - 0x01000080, 0x20000000, 0x21040000, 0x01040080, - 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, - 0x01040000, 0x00000000, 0x20040000, 0x21000000, - 0x00040080, 0x01000080, 0x20000080, 0x00040000, - 0x00000000, 0x20040000, 0x01040080, 0x20000080 - ]; - - /** - * Pre-permuted S-box6 - * - * @var array - * @access private - */ - private $sbox6 = [ - 0x10000008, 0x10200000, 0x00002000, 0x10202008, - 0x10200000, 0x00000008, 0x10202008, 0x00200000, - 0x10002000, 0x00202008, 0x00200000, 0x10000008, - 0x00200008, 0x10002000, 0x10000000, 0x00002008, - 0x00000000, 0x00200008, 0x10002008, 0x00002000, - 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, - 0x00002008, 0x00202000, 0x10202000, 0x10000000, - 0x10002000, 0x00000008, 0x10200008, 0x00202000, - 0x10202008, 0x00200000, 0x00002008, 0x10000008, - 0x00200000, 0x10002000, 0x10000000, 0x00002008, - 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, - 0x00000008, 0x00002000, 0x10200000, 0x00202008, - 0x00002000, 0x00200008, 0x10002008, 0x00000000, - 0x10202000, 0x10000000, 0x00200008, 0x10002008 - ]; - - /** - * Pre-permuted S-box7 - * - * @var array - * @access private - */ - private $sbox7 = [ - 0x00100000, 0x02100001, 0x02000401, 0x00000000, - 0x00000400, 0x02000401, 0x00100401, 0x02100400, - 0x02100401, 0x00100000, 0x00000000, 0x02000001, - 0x00000001, 0x02000000, 0x02100001, 0x00000401, - 0x02000400, 0x00100401, 0x00100001, 0x02000400, - 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, - 0x00100400, 0x00000001, 0x02000000, 0x00100400, - 0x02000000, 0x00100400, 0x00100000, 0x02000401, - 0x02000401, 0x02100001, 0x02100001, 0x00000001, - 0x00100001, 0x02000000, 0x02000400, 0x00100000, - 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, - 0x00100400, 0x00000000, 0x00000001, 0x02100401, - 0x00000000, 0x00100401, 0x02100000, 0x00000400, - 0x02000001, 0x02000400, 0x00000400, 0x00100001 - ]; - - /** - * Pre-permuted S-box8 - * - * @var array - * @access private - */ - private $sbox8 = [ - 0x08000820, 0x00000800, 0x00020000, 0x08020820, - 0x08000000, 0x08000820, 0x00000020, 0x08000000, - 0x00020020, 0x08020000, 0x08020820, 0x00020800, - 0x08020800, 0x00020820, 0x00000800, 0x00000020, - 0x08020000, 0x08000020, 0x08000800, 0x00000820, - 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, - 0x08000020, 0x08000800, 0x00020820, 0x00020000, - 0x00020820, 0x00020000, 0x08020800, 0x00000800, - 0x00000020, 0x08020020, 0x00000800, 0x00020820, - 0x08000800, 0x00000020, 0x08000020, 0x08020000, - 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, - 0x08020000, 0x08000800, 0x08000820, 0x00000000, - 0x08020820, 0x00020800, 0x00020800, 0x00000820, - 0x00000820, 0x00020020, 0x08000000, 0x08020800 - ]; - - /** - * Default Constructor. - * - * @param int $mode - * @access public - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - if ($mode == self::MODE_STREAM) { - throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode'); - } - - parent::__construct($mode); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * @param int $engine - * @access public - * @return bool - */ - public function isValidEngine($engine) - { - if ($this->key_length_max == 8) { - if ($engine == self::ENGINE_OPENSSL) { - $this->cipher_name_openssl_ecb = 'des-ecb'; - $this->cipher_name_openssl = 'des-' . $this->openssl_translate_mode(); - } - } - - return parent::isValidEngine($engine); - } - - /** - * Sets the key. - * - * Keys must be 64-bits long or 8 bytes long. - * - * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setKey() - * @access public - * @param string $key - */ - public function setKey($key) - { - if (!($this instanceof TripleDES) && strlen($key) != 8) { - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of size 8 are supported'); - } - - // Sets the key - parent::setKey($key); - } - - /** - * Encrypts a block - * - * @see \phpseclib\Crypt\Common\SymmetricKey::encryptBlock() - * @see \phpseclib\Crypt\Common\SymmetricKey::encrypt() - * @see self::encrypt() - * @access private - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - return $this->processBlock($in, self::ENCRYPT); - } - - /** - * Decrypts a block - * - * @see \phpseclib\Crypt\Common\SymmetricKey::decryptBlock() - * @see \phpseclib\Crypt\Common\SymmetricKey::decrypt() - * @see self::decrypt() - * @access private - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - return $this->processBlock($in, self::DECRYPT); - } - - /** - * Encrypts or decrypts a 64-bit block - * - * $mode should be either self::ENCRYPT or self::DECRYPT. See - * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general - * idea of what this function does. - * - * @see self::encryptBlock() - * @see self::decryptBlock() - * @access private - * @param string $block - * @param int $mode - * @return string - */ - private function processBlock($block, $mode) - { - static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip; - if (!$sbox1) { - $sbox1 = array_map("intval", $this->sbox1); - $sbox2 = array_map("intval", $this->sbox2); - $sbox3 = array_map("intval", $this->sbox3); - $sbox4 = array_map("intval", $this->sbox4); - $sbox5 = array_map("intval", $this->sbox5); - $sbox6 = array_map("intval", $this->sbox6); - $sbox7 = array_map("intval", $this->sbox7); - $sbox8 = array_map("intval", $this->sbox8); - /* Merge $shuffle with $[inv]ipmap */ - for ($i = 0; $i < 256; ++$i) { - $shuffleip[] = $this->shuffle[$this->ipmap[$i]]; - $shuffleinvip[] = $this->shuffle[$this->invipmap[$i]]; - } - } - - $keys = $this->keys[$mode]; - $ki = -1; - - // Do the initial IP permutation. - $t = unpack('Nl/Nr', $block); - list($l, $r) = [$t['l'], $t['r']]; - $block = ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); - - // Extract L0 and R0. - $t = unpack('Nl/Nr', $block); - list($l, $r) = [$t['l'], $t['r']]; - - for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) { - // Perform the 16 steps. - for ($i = 0; $i < 16; $i++) { - // start of "the Feistel (F) function" - see the following URL: - // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png - // Merge key schedule. - $b1 = (($r >> 3) & 0x1FFFFFFF) ^ ($r << 29) ^ $keys[++$ki]; - $b2 = (($r >> 31) & 0x00000001) ^ ($r << 1) ^ $keys[++$ki]; - - // S-box indexing. - $t = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^ - $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^ - $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^ - $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ $l; - // end of "the Feistel (F) function" - - $l = $r; - $r = $t; - } - - // Last step should not permute L & R. - $t = $l; - $l = $r; - $r = $t; - } - - // Perform the inverse IP permutation. - return ($shuffleinvip[($r >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleinvip[($l >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleinvip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleinvip[($l >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleinvip[($r >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleinvip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleinvip[ $r & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleinvip[ $l & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); - } - - /** - * Creates the key schedule - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setupKey() - * @access private - */ - protected function setupKey() - { - if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) { - // already expanded - return; - } - $this->kl = ['key' => $this->key, 'des_rounds' => $this->des_rounds]; - - static $shifts = [ // number of key bits shifted per round - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 - ]; - - static $pc1map = [ - 0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C, - 0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E, - 0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1C, 0x1C, - 0x12, 0x12, 0x1A, 0x1A, 0x16, 0x16, 0x1E, 0x1E, - 0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2C, 0x2C, - 0x22, 0x22, 0x2A, 0x2A, 0x26, 0x26, 0x2E, 0x2E, - 0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3C, 0x3C, - 0x32, 0x32, 0x3A, 0x3A, 0x36, 0x36, 0x3E, 0x3E, - 0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4C, 0x4C, - 0x42, 0x42, 0x4A, 0x4A, 0x46, 0x46, 0x4E, 0x4E, - 0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5C, 0x5C, - 0x52, 0x52, 0x5A, 0x5A, 0x56, 0x56, 0x5E, 0x5E, - 0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6C, 0x6C, - 0x62, 0x62, 0x6A, 0x6A, 0x66, 0x66, 0x6E, 0x6E, - 0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7C, 0x7C, - 0x72, 0x72, 0x7A, 0x7A, 0x76, 0x76, 0x7E, 0x7E, - 0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8C, 0x8C, - 0x82, 0x82, 0x8A, 0x8A, 0x86, 0x86, 0x8E, 0x8E, - 0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9C, 0x9C, - 0x92, 0x92, 0x9A, 0x9A, 0x96, 0x96, 0x9E, 0x9E, - 0xA0, 0xA0, 0xA8, 0xA8, 0xA4, 0xA4, 0xAC, 0xAC, - 0xA2, 0xA2, 0xAA, 0xAA, 0xA6, 0xA6, 0xAE, 0xAE, - 0xB0, 0xB0, 0xB8, 0xB8, 0xB4, 0xB4, 0xBC, 0xBC, - 0xB2, 0xB2, 0xBA, 0xBA, 0xB6, 0xB6, 0xBE, 0xBE, - 0xC0, 0xC0, 0xC8, 0xC8, 0xC4, 0xC4, 0xCC, 0xCC, - 0xC2, 0xC2, 0xCA, 0xCA, 0xC6, 0xC6, 0xCE, 0xCE, - 0xD0, 0xD0, 0xD8, 0xD8, 0xD4, 0xD4, 0xDC, 0xDC, - 0xD2, 0xD2, 0xDA, 0xDA, 0xD6, 0xD6, 0xDE, 0xDE, - 0xE0, 0xE0, 0xE8, 0xE8, 0xE4, 0xE4, 0xEC, 0xEC, - 0xE2, 0xE2, 0xEA, 0xEA, 0xE6, 0xE6, 0xEE, 0xEE, - 0xF0, 0xF0, 0xF8, 0xF8, 0xF4, 0xF4, 0xFC, 0xFC, - 0xF2, 0xF2, 0xFA, 0xFA, 0xF6, 0xF6, 0xFE, 0xFE - ]; - - // Mapping tables for the PC-2 transformation. - static $pc2mapc1 = [ - 0x00000000, 0x00000400, 0x00200000, 0x00200400, - 0x00000001, 0x00000401, 0x00200001, 0x00200401, - 0x02000000, 0x02000400, 0x02200000, 0x02200400, - 0x02000001, 0x02000401, 0x02200001, 0x02200401 - ]; - static $pc2mapc2 = [ - 0x00000000, 0x00000800, 0x08000000, 0x08000800, - 0x00010000, 0x00010800, 0x08010000, 0x08010800, - 0x00000000, 0x00000800, 0x08000000, 0x08000800, - 0x00010000, 0x00010800, 0x08010000, 0x08010800, - 0x00000100, 0x00000900, 0x08000100, 0x08000900, - 0x00010100, 0x00010900, 0x08010100, 0x08010900, - 0x00000100, 0x00000900, 0x08000100, 0x08000900, - 0x00010100, 0x00010900, 0x08010100, 0x08010900, - 0x00000010, 0x00000810, 0x08000010, 0x08000810, - 0x00010010, 0x00010810, 0x08010010, 0x08010810, - 0x00000010, 0x00000810, 0x08000010, 0x08000810, - 0x00010010, 0x00010810, 0x08010010, 0x08010810, - 0x00000110, 0x00000910, 0x08000110, 0x08000910, - 0x00010110, 0x00010910, 0x08010110, 0x08010910, - 0x00000110, 0x00000910, 0x08000110, 0x08000910, - 0x00010110, 0x00010910, 0x08010110, 0x08010910, - 0x00040000, 0x00040800, 0x08040000, 0x08040800, - 0x00050000, 0x00050800, 0x08050000, 0x08050800, - 0x00040000, 0x00040800, 0x08040000, 0x08040800, - 0x00050000, 0x00050800, 0x08050000, 0x08050800, - 0x00040100, 0x00040900, 0x08040100, 0x08040900, - 0x00050100, 0x00050900, 0x08050100, 0x08050900, - 0x00040100, 0x00040900, 0x08040100, 0x08040900, - 0x00050100, 0x00050900, 0x08050100, 0x08050900, - 0x00040010, 0x00040810, 0x08040010, 0x08040810, - 0x00050010, 0x00050810, 0x08050010, 0x08050810, - 0x00040010, 0x00040810, 0x08040010, 0x08040810, - 0x00050010, 0x00050810, 0x08050010, 0x08050810, - 0x00040110, 0x00040910, 0x08040110, 0x08040910, - 0x00050110, 0x00050910, 0x08050110, 0x08050910, - 0x00040110, 0x00040910, 0x08040110, 0x08040910, - 0x00050110, 0x00050910, 0x08050110, 0x08050910, - 0x01000000, 0x01000800, 0x09000000, 0x09000800, - 0x01010000, 0x01010800, 0x09010000, 0x09010800, - 0x01000000, 0x01000800, 0x09000000, 0x09000800, - 0x01010000, 0x01010800, 0x09010000, 0x09010800, - 0x01000100, 0x01000900, 0x09000100, 0x09000900, - 0x01010100, 0x01010900, 0x09010100, 0x09010900, - 0x01000100, 0x01000900, 0x09000100, 0x09000900, - 0x01010100, 0x01010900, 0x09010100, 0x09010900, - 0x01000010, 0x01000810, 0x09000010, 0x09000810, - 0x01010010, 0x01010810, 0x09010010, 0x09010810, - 0x01000010, 0x01000810, 0x09000010, 0x09000810, - 0x01010010, 0x01010810, 0x09010010, 0x09010810, - 0x01000110, 0x01000910, 0x09000110, 0x09000910, - 0x01010110, 0x01010910, 0x09010110, 0x09010910, - 0x01000110, 0x01000910, 0x09000110, 0x09000910, - 0x01010110, 0x01010910, 0x09010110, 0x09010910, - 0x01040000, 0x01040800, 0x09040000, 0x09040800, - 0x01050000, 0x01050800, 0x09050000, 0x09050800, - 0x01040000, 0x01040800, 0x09040000, 0x09040800, - 0x01050000, 0x01050800, 0x09050000, 0x09050800, - 0x01040100, 0x01040900, 0x09040100, 0x09040900, - 0x01050100, 0x01050900, 0x09050100, 0x09050900, - 0x01040100, 0x01040900, 0x09040100, 0x09040900, - 0x01050100, 0x01050900, 0x09050100, 0x09050900, - 0x01040010, 0x01040810, 0x09040010, 0x09040810, - 0x01050010, 0x01050810, 0x09050010, 0x09050810, - 0x01040010, 0x01040810, 0x09040010, 0x09040810, - 0x01050010, 0x01050810, 0x09050010, 0x09050810, - 0x01040110, 0x01040910, 0x09040110, 0x09040910, - 0x01050110, 0x01050910, 0x09050110, 0x09050910, - 0x01040110, 0x01040910, 0x09040110, 0x09040910, - 0x01050110, 0x01050910, 0x09050110, 0x09050910 - ]; - static $pc2mapc3 = [ - 0x00000000, 0x00000004, 0x00001000, 0x00001004, - 0x00000000, 0x00000004, 0x00001000, 0x00001004, - 0x10000000, 0x10000004, 0x10001000, 0x10001004, - 0x10000000, 0x10000004, 0x10001000, 0x10001004, - 0x00000020, 0x00000024, 0x00001020, 0x00001024, - 0x00000020, 0x00000024, 0x00001020, 0x00001024, - 0x10000020, 0x10000024, 0x10001020, 0x10001024, - 0x10000020, 0x10000024, 0x10001020, 0x10001024, - 0x00080000, 0x00080004, 0x00081000, 0x00081004, - 0x00080000, 0x00080004, 0x00081000, 0x00081004, - 0x10080000, 0x10080004, 0x10081000, 0x10081004, - 0x10080000, 0x10080004, 0x10081000, 0x10081004, - 0x00080020, 0x00080024, 0x00081020, 0x00081024, - 0x00080020, 0x00080024, 0x00081020, 0x00081024, - 0x10080020, 0x10080024, 0x10081020, 0x10081024, - 0x10080020, 0x10080024, 0x10081020, 0x10081024, - 0x20000000, 0x20000004, 0x20001000, 0x20001004, - 0x20000000, 0x20000004, 0x20001000, 0x20001004, - 0x30000000, 0x30000004, 0x30001000, 0x30001004, - 0x30000000, 0x30000004, 0x30001000, 0x30001004, - 0x20000020, 0x20000024, 0x20001020, 0x20001024, - 0x20000020, 0x20000024, 0x20001020, 0x20001024, - 0x30000020, 0x30000024, 0x30001020, 0x30001024, - 0x30000020, 0x30000024, 0x30001020, 0x30001024, - 0x20080000, 0x20080004, 0x20081000, 0x20081004, - 0x20080000, 0x20080004, 0x20081000, 0x20081004, - 0x30080000, 0x30080004, 0x30081000, 0x30081004, - 0x30080000, 0x30080004, 0x30081000, 0x30081004, - 0x20080020, 0x20080024, 0x20081020, 0x20081024, - 0x20080020, 0x20080024, 0x20081020, 0x20081024, - 0x30080020, 0x30080024, 0x30081020, 0x30081024, - 0x30080020, 0x30080024, 0x30081020, 0x30081024, - 0x00000002, 0x00000006, 0x00001002, 0x00001006, - 0x00000002, 0x00000006, 0x00001002, 0x00001006, - 0x10000002, 0x10000006, 0x10001002, 0x10001006, - 0x10000002, 0x10000006, 0x10001002, 0x10001006, - 0x00000022, 0x00000026, 0x00001022, 0x00001026, - 0x00000022, 0x00000026, 0x00001022, 0x00001026, - 0x10000022, 0x10000026, 0x10001022, 0x10001026, - 0x10000022, 0x10000026, 0x10001022, 0x10001026, - 0x00080002, 0x00080006, 0x00081002, 0x00081006, - 0x00080002, 0x00080006, 0x00081002, 0x00081006, - 0x10080002, 0x10080006, 0x10081002, 0x10081006, - 0x10080002, 0x10080006, 0x10081002, 0x10081006, - 0x00080022, 0x00080026, 0x00081022, 0x00081026, - 0x00080022, 0x00080026, 0x00081022, 0x00081026, - 0x10080022, 0x10080026, 0x10081022, 0x10081026, - 0x10080022, 0x10080026, 0x10081022, 0x10081026, - 0x20000002, 0x20000006, 0x20001002, 0x20001006, - 0x20000002, 0x20000006, 0x20001002, 0x20001006, - 0x30000002, 0x30000006, 0x30001002, 0x30001006, - 0x30000002, 0x30000006, 0x30001002, 0x30001006, - 0x20000022, 0x20000026, 0x20001022, 0x20001026, - 0x20000022, 0x20000026, 0x20001022, 0x20001026, - 0x30000022, 0x30000026, 0x30001022, 0x30001026, - 0x30000022, 0x30000026, 0x30001022, 0x30001026, - 0x20080002, 0x20080006, 0x20081002, 0x20081006, - 0x20080002, 0x20080006, 0x20081002, 0x20081006, - 0x30080002, 0x30080006, 0x30081002, 0x30081006, - 0x30080002, 0x30080006, 0x30081002, 0x30081006, - 0x20080022, 0x20080026, 0x20081022, 0x20081026, - 0x20080022, 0x20080026, 0x20081022, 0x20081026, - 0x30080022, 0x30080026, 0x30081022, 0x30081026, - 0x30080022, 0x30080026, 0x30081022, 0x30081026 - ]; - static $pc2mapc4 = [ - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208 - ]; - static $pc2mapd1 = [ - 0x00000000, 0x00000001, 0x08000000, 0x08000001, - 0x00200000, 0x00200001, 0x08200000, 0x08200001, - 0x00000002, 0x00000003, 0x08000002, 0x08000003, - 0x00200002, 0x00200003, 0x08200002, 0x08200003 - ]; - static $pc2mapd2 = [ - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04 - ]; - static $pc2mapd3 = [ - 0x00000000, 0x00010000, 0x02000000, 0x02010000, - 0x00000020, 0x00010020, 0x02000020, 0x02010020, - 0x00040000, 0x00050000, 0x02040000, 0x02050000, - 0x00040020, 0x00050020, 0x02040020, 0x02050020, - 0x00002000, 0x00012000, 0x02002000, 0x02012000, - 0x00002020, 0x00012020, 0x02002020, 0x02012020, - 0x00042000, 0x00052000, 0x02042000, 0x02052000, - 0x00042020, 0x00052020, 0x02042020, 0x02052020, - 0x00000000, 0x00010000, 0x02000000, 0x02010000, - 0x00000020, 0x00010020, 0x02000020, 0x02010020, - 0x00040000, 0x00050000, 0x02040000, 0x02050000, - 0x00040020, 0x00050020, 0x02040020, 0x02050020, - 0x00002000, 0x00012000, 0x02002000, 0x02012000, - 0x00002020, 0x00012020, 0x02002020, 0x02012020, - 0x00042000, 0x00052000, 0x02042000, 0x02052000, - 0x00042020, 0x00052020, 0x02042020, 0x02052020, - 0x00000010, 0x00010010, 0x02000010, 0x02010010, - 0x00000030, 0x00010030, 0x02000030, 0x02010030, - 0x00040010, 0x00050010, 0x02040010, 0x02050010, - 0x00040030, 0x00050030, 0x02040030, 0x02050030, - 0x00002010, 0x00012010, 0x02002010, 0x02012010, - 0x00002030, 0x00012030, 0x02002030, 0x02012030, - 0x00042010, 0x00052010, 0x02042010, 0x02052010, - 0x00042030, 0x00052030, 0x02042030, 0x02052030, - 0x00000010, 0x00010010, 0x02000010, 0x02010010, - 0x00000030, 0x00010030, 0x02000030, 0x02010030, - 0x00040010, 0x00050010, 0x02040010, 0x02050010, - 0x00040030, 0x00050030, 0x02040030, 0x02050030, - 0x00002010, 0x00012010, 0x02002010, 0x02012010, - 0x00002030, 0x00012030, 0x02002030, 0x02012030, - 0x00042010, 0x00052010, 0x02042010, 0x02052010, - 0x00042030, 0x00052030, 0x02042030, 0x02052030, - 0x20000000, 0x20010000, 0x22000000, 0x22010000, - 0x20000020, 0x20010020, 0x22000020, 0x22010020, - 0x20040000, 0x20050000, 0x22040000, 0x22050000, - 0x20040020, 0x20050020, 0x22040020, 0x22050020, - 0x20002000, 0x20012000, 0x22002000, 0x22012000, - 0x20002020, 0x20012020, 0x22002020, 0x22012020, - 0x20042000, 0x20052000, 0x22042000, 0x22052000, - 0x20042020, 0x20052020, 0x22042020, 0x22052020, - 0x20000000, 0x20010000, 0x22000000, 0x22010000, - 0x20000020, 0x20010020, 0x22000020, 0x22010020, - 0x20040000, 0x20050000, 0x22040000, 0x22050000, - 0x20040020, 0x20050020, 0x22040020, 0x22050020, - 0x20002000, 0x20012000, 0x22002000, 0x22012000, - 0x20002020, 0x20012020, 0x22002020, 0x22012020, - 0x20042000, 0x20052000, 0x22042000, 0x22052000, - 0x20042020, 0x20052020, 0x22042020, 0x22052020, - 0x20000010, 0x20010010, 0x22000010, 0x22010010, - 0x20000030, 0x20010030, 0x22000030, 0x22010030, - 0x20040010, 0x20050010, 0x22040010, 0x22050010, - 0x20040030, 0x20050030, 0x22040030, 0x22050030, - 0x20002010, 0x20012010, 0x22002010, 0x22012010, - 0x20002030, 0x20012030, 0x22002030, 0x22012030, - 0x20042010, 0x20052010, 0x22042010, 0x22052010, - 0x20042030, 0x20052030, 0x22042030, 0x22052030, - 0x20000010, 0x20010010, 0x22000010, 0x22010010, - 0x20000030, 0x20010030, 0x22000030, 0x22010030, - 0x20040010, 0x20050010, 0x22040010, 0x22050010, - 0x20040030, 0x20050030, 0x22040030, 0x22050030, - 0x20002010, 0x20012010, 0x22002010, 0x22012010, - 0x20002030, 0x20012030, 0x22002030, 0x22012030, - 0x20042010, 0x20052010, 0x22042010, 0x22052010, - 0x20042030, 0x20052030, 0x22042030, 0x22052030 - ]; - static $pc2mapd4 = [ - 0x00000000, 0x00000400, 0x01000000, 0x01000400, - 0x00000000, 0x00000400, 0x01000000, 0x01000400, - 0x00000100, 0x00000500, 0x01000100, 0x01000500, - 0x00000100, 0x00000500, 0x01000100, 0x01000500, - 0x10000000, 0x10000400, 0x11000000, 0x11000400, - 0x10000000, 0x10000400, 0x11000000, 0x11000400, - 0x10000100, 0x10000500, 0x11000100, 0x11000500, - 0x10000100, 0x10000500, 0x11000100, 0x11000500, - 0x00080000, 0x00080400, 0x01080000, 0x01080400, - 0x00080000, 0x00080400, 0x01080000, 0x01080400, - 0x00080100, 0x00080500, 0x01080100, 0x01080500, - 0x00080100, 0x00080500, 0x01080100, 0x01080500, - 0x10080000, 0x10080400, 0x11080000, 0x11080400, - 0x10080000, 0x10080400, 0x11080000, 0x11080400, - 0x10080100, 0x10080500, 0x11080100, 0x11080500, - 0x10080100, 0x10080500, 0x11080100, 0x11080500, - 0x00000008, 0x00000408, 0x01000008, 0x01000408, - 0x00000008, 0x00000408, 0x01000008, 0x01000408, - 0x00000108, 0x00000508, 0x01000108, 0x01000508, - 0x00000108, 0x00000508, 0x01000108, 0x01000508, - 0x10000008, 0x10000408, 0x11000008, 0x11000408, - 0x10000008, 0x10000408, 0x11000008, 0x11000408, - 0x10000108, 0x10000508, 0x11000108, 0x11000508, - 0x10000108, 0x10000508, 0x11000108, 0x11000508, - 0x00080008, 0x00080408, 0x01080008, 0x01080408, - 0x00080008, 0x00080408, 0x01080008, 0x01080408, - 0x00080108, 0x00080508, 0x01080108, 0x01080508, - 0x00080108, 0x00080508, 0x01080108, 0x01080508, - 0x10080008, 0x10080408, 0x11080008, 0x11080408, - 0x10080008, 0x10080408, 0x11080008, 0x11080408, - 0x10080108, 0x10080508, 0x11080108, 0x11080508, - 0x10080108, 0x10080508, 0x11080108, 0x11080508, - 0x00001000, 0x00001400, 0x01001000, 0x01001400, - 0x00001000, 0x00001400, 0x01001000, 0x01001400, - 0x00001100, 0x00001500, 0x01001100, 0x01001500, - 0x00001100, 0x00001500, 0x01001100, 0x01001500, - 0x10001000, 0x10001400, 0x11001000, 0x11001400, - 0x10001000, 0x10001400, 0x11001000, 0x11001400, - 0x10001100, 0x10001500, 0x11001100, 0x11001500, - 0x10001100, 0x10001500, 0x11001100, 0x11001500, - 0x00081000, 0x00081400, 0x01081000, 0x01081400, - 0x00081000, 0x00081400, 0x01081000, 0x01081400, - 0x00081100, 0x00081500, 0x01081100, 0x01081500, - 0x00081100, 0x00081500, 0x01081100, 0x01081500, - 0x10081000, 0x10081400, 0x11081000, 0x11081400, - 0x10081000, 0x10081400, 0x11081000, 0x11081400, - 0x10081100, 0x10081500, 0x11081100, 0x11081500, - 0x10081100, 0x10081500, 0x11081100, 0x11081500, - 0x00001008, 0x00001408, 0x01001008, 0x01001408, - 0x00001008, 0x00001408, 0x01001008, 0x01001408, - 0x00001108, 0x00001508, 0x01001108, 0x01001508, - 0x00001108, 0x00001508, 0x01001108, 0x01001508, - 0x10001008, 0x10001408, 0x11001008, 0x11001408, - 0x10001008, 0x10001408, 0x11001008, 0x11001408, - 0x10001108, 0x10001508, 0x11001108, 0x11001508, - 0x10001108, 0x10001508, 0x11001108, 0x11001508, - 0x00081008, 0x00081408, 0x01081008, 0x01081408, - 0x00081008, 0x00081408, 0x01081008, 0x01081408, - 0x00081108, 0x00081508, 0x01081108, 0x01081508, - 0x00081108, 0x00081508, 0x01081108, 0x01081508, - 0x10081008, 0x10081408, 0x11081008, 0x11081408, - 0x10081008, 0x10081408, 0x11081008, 0x11081408, - 0x10081108, 0x10081508, 0x11081108, 0x11081508, - 0x10081108, 0x10081508, 0x11081108, 0x11081508 - ]; - - $keys = []; - for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) { - // pad the key and remove extra characters as appropriate. - $key = str_pad(substr($this->key, $des_round * 8, 8), 8, "\0"); - - // Perform the PC/1 transformation and compute C and D. - $t = unpack('Nl/Nr', $key); - list($l, $r) = [$t['l'], $t['r']]; - $key = ($this->shuffle[$pc1map[ $r & 0xFF]] & "\x80\x80\x80\x80\x80\x80\x80\x00") | - ($this->shuffle[$pc1map[($r >> 8) & 0xFF]] & "\x40\x40\x40\x40\x40\x40\x40\x00") | - ($this->shuffle[$pc1map[($r >> 16) & 0xFF]] & "\x20\x20\x20\x20\x20\x20\x20\x00") | - ($this->shuffle[$pc1map[($r >> 24) & 0xFF]] & "\x10\x10\x10\x10\x10\x10\x10\x00") | - ($this->shuffle[$pc1map[ $l & 0xFF]] & "\x08\x08\x08\x08\x08\x08\x08\x00") | - ($this->shuffle[$pc1map[($l >> 8) & 0xFF]] & "\x04\x04\x04\x04\x04\x04\x04\x00") | - ($this->shuffle[$pc1map[($l >> 16) & 0xFF]] & "\x02\x02\x02\x02\x02\x02\x02\x00") | - ($this->shuffle[$pc1map[($l >> 24) & 0xFF]] & "\x01\x01\x01\x01\x01\x01\x01\x00"); - $key = unpack('Nc/Nd', $key); - $c = ( $key['c'] >> 4) & 0x0FFFFFFF; - $d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F); - - $keys[$des_round] = [ - self::ENCRYPT => [], - self::DECRYPT => array_fill(0, 32, 0) - ]; - for ($i = 0, $ki = 31; $i < 16; ++$i, $ki-= 2) { - $c <<= $shifts[$i]; - $c = ($c | ($c >> 28)) & 0x0FFFFFFF; - $d <<= $shifts[$i]; - $d = ($d | ($d >> 28)) & 0x0FFFFFFF; - - // Perform the PC-2 transformation. - $cp = $pc2mapc1[ $c >> 24 ] | $pc2mapc2[($c >> 16) & 0xFF] | - $pc2mapc3[($c >> 8) & 0xFF] | $pc2mapc4[ $c & 0xFF]; - $dp = $pc2mapd1[ $d >> 24 ] | $pc2mapd2[($d >> 16) & 0xFF] | - $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF]; - - // Reorder: odd bytes/even bytes. Push the result in key schedule. - $val1 = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) | - (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF); - $val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) | - (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF); - $keys[$des_round][self::ENCRYPT][ ] = $val1; - $keys[$des_round][self::DECRYPT][$ki - 1] = $val1; - $keys[$des_round][self::ENCRYPT][ ] = $val2; - $keys[$des_round][self::DECRYPT][$ki ] = $val2; - } - } - - switch ($this->des_rounds) { - case 3: // 3DES keys - $this->keys = [ - self::ENCRYPT => array_merge( - $keys[0][self::ENCRYPT], - $keys[1][self::DECRYPT], - $keys[2][self::ENCRYPT] - ), - self::DECRYPT => array_merge( - $keys[2][self::DECRYPT], - $keys[1][self::ENCRYPT], - $keys[0][self::DECRYPT] - ) - ]; - break; - // case 1: // DES keys - default: - $this->keys = [ - self::ENCRYPT => $keys[0][self::ENCRYPT], - self::DECRYPT => $keys[0][self::DECRYPT] - ]; - } - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setupInlineCrypt() - * @access private - */ - protected function setupInlineCrypt() - { - // Engine configuration for: - // - DES ($des_rounds == 1) or - // - 3DES ($des_rounds == 3) - $des_rounds = $this->des_rounds; - - $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip; - if (!$sbox1) { - $sbox1 = array_map("intval", $this->sbox1); - $sbox2 = array_map("intval", $this->sbox2); - $sbox3 = array_map("intval", $this->sbox3); - $sbox4 = array_map("intval", $this->sbox4); - $sbox5 = array_map("intval", $this->sbox5); - $sbox6 = array_map("intval", $this->sbox6); - $sbox7 = array_map("intval", $this->sbox7); - $sbox8 = array_map("intval", $this->sbox8);' - /* Merge $shuffle with $[inv]ipmap */ . ' - for ($i = 0; $i < 256; ++$i) { - $shuffleip[] = $this->shuffle[$this->ipmap[$i]]; - $shuffleinvip[] = $this->shuffle[$this->invipmap[$i]]; - } - } - '; - - $k = [ - self::ENCRYPT => $this->keys[self::ENCRYPT], - self::DECRYPT => $this->keys[self::DECRYPT] - ]; - $init_encrypt = ''; - $init_decrypt = ''; - - // Creating code for en- and decryption. - $crypt_block = []; - foreach ([self::ENCRYPT, self::DECRYPT] as $c) { - /* Do the initial IP permutation. */ - $crypt_block[$c] = ' - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - $in = unpack("N*", - ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01") - ); - ' . /* Extract L0 and R0 */ ' - $l = $in[1]; - $r = $in[2]; - '; - - $l = '$l'; - $r = '$r'; - - // Perform DES or 3DES. - for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) { - // Perform the 16 steps. - for ($i = 0; $i < 16; ++$i) { - // start of "the Feistel (F) function" - see the following URL: - // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png - // Merge key schedule. - $crypt_block[$c].= ' - $b1 = ((' . $r . ' >> 3) & 0x1FFFFFFF) ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . '; - $b2 = ((' . $r . ' >> 31) & 0x00000001) ^ (' . $r . ' << 1) ^ ' . $k[$c][++$ki] . ';' . - /* S-box indexing. */ - $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^ - $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^ - $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^ - $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ ' . $l . '; - '; - // end of "the Feistel (F) function" - - // swap L & R - list($l, $r) = [$r, $l]; - } - list($l, $r) = [$r, $l]; - } - - // Perform the inverse IP permutation. - $crypt_block[$c].= '$in = - ($shuffleinvip[($l >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleinvip[($r >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleinvip[($l >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleinvip[($r >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleinvip[($l >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleinvip[($r >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleinvip[ $l & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleinvip[ $r & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); - '; - } - - // Creates the inline-crypt function - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'init_encrypt' => $init_encrypt, - 'init_decrypt' => $init_decrypt, - 'encrypt_block' => $crypt_block[self::ENCRYPT], - 'decrypt_block' => $crypt_block[self::DECRYPT] - ] - ); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA.php b/lib/phpaes/phpseclib/Crypt/DSA.php deleted file mode 100644 index 9cbee43eb4..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA.php +++ /dev/null @@ -1,500 +0,0 @@ - - * sign($plaintext, 'ASN1'); - * - * echo $publickey->verify($plaintext, $signature) ? 'verified' : 'unverified'; - * ?> - * - * - * @category Crypt - * @package DSA - * @author Jim Wigginton - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\File\ASN1; -use phpseclib\Math\BigInteger; -use phpseclib\Crypt\Common\AsymmetricKey; -use phpseclib\Common\Functions\Strings; - -/** - * Pure-PHP FIPS 186-4 compliant implementation of DSA. - * - * @package DSA - * @author Jim Wigginton - * @access public - */ -class DSA extends AsymmetricKey -{ - /** - * Algorithm Name - * - * @var string - * @access private - */ - const ALGORITHM = 'DSA'; - - /** - * DSA Prime P - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - private $p; - - /** - * DSA Group Order q - * - * Prime divisor of p-1 - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - protected $q; - - /** - * DSA Group Generator G - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - private $g; - - /** - * DSA secret exponent x - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - protected $x; - - /** - * DSA public key value y - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - private $y; - - /** - * Parameters Format - * - * @var string - * @access private - */ - private $parametersFormat = 'PKCS1'; - - /** - * Create DSA parameters - * - * @access public - * @param int $L - * @param int $N - * @return \phpseclib\Crypt\DSA - */ - static function createParameters($L = 2048, $N = 224) - { - self::initialize_static_variables(); - - switch (true) { - case $N == 160: - /* - in FIPS 186-1 and 186-2 N was fixed at 160 whereas K had an upper bound of 1024. - RFC 4253 (SSH Transport Layer Protocol) references FIPS 186-2 and as such most - SSH DSA implementations only support keys with an N of 160. - puttygen let's you set the size of L (but not the size of N) and uses 2048 as the - default L value. that's not really compliant with any of the FIPS standards, however, - for the purposes of maintaining compatibility with puttygen, we'll support it - */ - //case ($L >= 512 || $L <= 1024) && (($L & 0x3F) == 0) && $N == 160: - // FIPS 186-3 changed this as follows: - //case $L == 1024 && $N == 160: - case $L == 2048 && $N == 224: - case $L == 2048 && $N == 256: - case $L == 3072 && $N == 256: - break; - default: - return false; - } - - $two = new BigInteger(2); - - $q = BigInteger::randomPrime($N); - $divisor = $q->multiply($two); - - do { - $x = BigInteger::random($L); - list(, $c) = $x->divide($divisor); - $p = $x->subtract($c->subtract(self::$one)); - } while ($p->getLength() != $L || !$p->isPrime()); - - $p_1 = $p->subtract(self::$one); - list($e) = $p_1->divide($q); - - // quoting http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#page=50 , - // "h could be obtained from a random number generator or from a counter that - // changes after each use". PuTTY (sshdssg.c) starts h off at 1 and increments - // it on each loop. wikipedia says "commonly h = 2 is used" so we'll just do that - $h = clone $two; - while (true) { - $g = $h->powMod($e, $p); - if (!$g->equals(self::$one)) { - break; - } - $h = $h->add(self::$one); - } - - $dsa = new DSA(); - $dsa->p = $p; - $dsa->q = $q; - $dsa->g = $g; - - return $dsa; - } - - /** - * Create public / private key pair. - * - * This method is a bit polymorphic. It can take a DSA object (eg. pre-loaded with parameters), - * L / N as two distinct parameters or no parameters (at which point L and N will be generated - * with this method) - * - * Returns an array with the following two elements: - * - 'privatekey': The private key. - * - 'publickey': The public key. - * - * @access public - * @return \phpseclib\Crypt\DSA - */ - static function createKey() - { - self::initialize_static_variables(); - - $args = func_get_args(); - if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) { - $private = self::createParameters($args[0], $args[1]); - } else if (count($args) == 1 && $args[0] instanceof DSA) { - $private = clone $args[0]; - } else if (!count($args)) { - $private = self::createParameters(); - } else { - throw new \InvalidArgumentException('Valid parameters are either two integers (L and N), a single DSA object or no parameters at all.'); - } - - $private->x = BigInteger::randomRange(self::$one, $private->q->subtract(self::$one)); - $private->y = $private->g->powMod($private->x, $private->p); - - $public = clone $private; - unset($public->x); - - return ['privatekey' => $private, 'publickey' => $public]; - } - - /** - * Loads a public or private key - * - * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed) - * - * @access public - * @param string $key - * @param int $type optional - */ - public function load($key, $type = false) - { - if ($key instanceof DSA) { - $this->privateKeyFormat = $key->privateKeyFormat; - $this->publicKeyFormat = $key->publicKeyFormat; - $this->format = $key->format; - $this->p = $key->p; - $this->q = $key->q; - $this->g = $key->g; - $this->x = $key->x; - $this->y = $key->y; - $this->parametersFormat = $key->parametersFormat; - - return true; - } - - $components = parent::load($key, $type); - if ($components === false) { - return false; - } - - if (isset($components['p'])) { - switch (true) { - case isset($this->p) && !$this->p->equals($components['p']): - case isset($this->q) && !$this->q->equals($components['q']): - case isset($this->g) && !$this->g->equals($components['g']): - $this->x = $this->y = null; - } - - $this->p = $components['p']; - $this->q = $components['q']; - $this->g = $components['g']; - } - - if (isset($components['x'])) { - $this->x = $components['x']; - } - - if (isset($components['y'])) { - $this->y = $components['y']; - } - //} else if (isset($components['x'])) { - // $this->y = $this->g->powMod($this->x, $this->p); - //} - - return true; - } - - /** - * Returns the key size - * - * More specifically, this L (the length of DSA Prime P) and N (the length of DSA Group Order q) - * - * @access public - * @return array - */ - public function getLength() - { - return isset($this->p) ? - ['L' => $this->p->getLength(), 'N' => $this->q->getLength()] : - ['L' => 0, 'N' => 0]; - } - - /** - * __toString() magic method - * - * @access public - * @return string - */ - public function __toString() - { - $key = parent::__toString(); - if (!empty($key)) { - return $key; - } - - try { - $key = $this->getParameters($this->parametersFormat); - return is_string($key) ? $key : ''; - } catch (\Exception $e) { - return ''; - } - } - - /** - * Returns the private key - * - * PKCS1 DSA private keys contain x and y. PKCS8 DSA private keys just contain x - * but y can be derived from x. - * - * @see self::getPublicKey() - * @access public - * @param string $type optional - * @return mixed - */ - public function getPrivateKey($type = 'PKCS8') - { - $type = self::validatePlugin('Keys', $type, 'savePrivateKey'); - if ($type === false) { - return false; - } - - if (!isset($this->x)) { - return false; - } - - if (!isset($this->y)) { - $this->y = $this->g->powMod($this->x, $this->p); - } - - return $type::savePrivateKey($this->p, $this->q, $this->g, $this->y, $this->x, $this->password); - } - - /** - * Returns the public key - * - * If you do "openssl rsa -in private.rsa -pubout -outform PEM" you get a PKCS8 formatted key - * that contains a publicKeyAlgorithm AlgorithmIdentifier and a publicKey BIT STRING. - * An AlgorithmIdentifier contains an OID and a parameters field. With RSA public keys this - * parameters field is NULL. With DSA PKCS8 public keys it is not - it contains the p, q and g - * variables. The publicKey BIT STRING contains, simply, the y variable. This can be verified - * by getting a DSA PKCS8 public key: - * - * "openssl dsa -in private.dsa -pubout -outform PEM" - * - * ie. just swap out rsa with dsa in the rsa command above. - * - * A PKCS1 public key corresponds to the publicKey portion of the PKCS8 key. In the case of RSA - * the publicKey portion /is/ the key. In the case of DSA it is not. You cannot verify a signature - * without the parameters and the PKCS1 DSA public key format does not include the parameters. - * - * @see self::getPrivateKey() - * @access public - * @param string $type optional - * @return mixed - */ - public function getPublicKey($type = 'PKCS8') - { - $type = self::validatePlugin('Keys', $type, 'savePublicKey'); - if ($type === false) { - return false; - } - - if (!isset($this->y)) { - if (!isset($this->x) || !isset($this->p)) { - return false; - } - $this->y = $this->g->powMod($this->x, $this->p); - } - - return $type::savePublicKey($this->p, $this->q, $this->g, $this->y); - } - - /** - * Returns the parameters - * - * A public / private key is only returned if the currently loaded "key" contains an x or y - * value. - * - * @see self::getPublicKey() - * @see self::getPrivateKey() - * @access public - * @param string $type optional - * @return mixed - */ - public function getParameters($type = 'PKCS1') - { - $type = self::validatePlugin('Keys', $type, 'saveParameters'); - if ($type === false) { - return false; - } - - if (!isset($this->p) || !isset($this->q) || !isset($this->g)) { - return false; - } - - return $type::saveParameters($this->p, $this->q, $this->g); - } - - /** - * Create a signature - * - * @see self::verify() - * @access public - * @param string $message - * @param string $format optional - * @return mixed - */ - function sign($message, $format = 'Raw') - { - $format = self::validatePlugin('Signature', $format); - if ($format === false) { - return false; - } - - if (empty($this->x) || empty($this->p)) { - return false; - } - - while (true) { - $k = BigInteger::randomRange(self::$one, $this->q->subtract(self::$one)); - $r = $this->g->powMod($k, $this->p); - list(, $r) = $r->divide($this->q); - if ($r->equals(self::$zero)) { - continue; - } - $kinv = $k->modInverse($this->q); - $h = $this->hash->hash($message); - $h = $this->bits2int($h); - $temp = $h->add($this->x->multiply($r)); - $temp = $kinv->multiply($temp); - list(, $s) = $temp->divide($this->q); - if (!$s->equals(self::$zero)) { - break; - } - } - - // the following is an RFC6979 compliant implementation of deterministic DSA - // it's unused because it's mainly intended for use when a good CSPRNG isn't - // available. if phpseclib's CSPRNG isn't good then even key generation is - // suspect - /* - $h1 = $this->hash->hash($message); - $k = $this->computek($h1); - $r = $this->g->powMod($k, $this->p); - list(, $r) = $r->divide($this->q); - $kinv = $k->modInverse($this->q); - $h1 = $this->bits2int($h1); - $temp = $h1->add($this->x->multiply($r)); - $temp = $kinv->multiply($temp); - list(, $s) = $temp->divide($this->q); - */ - - return $format::save($r, $s); - } - - /** - * Verify a signature - * - * @see self::verify() - * @access public - * @param string $message - * @param string $format optional - * @return mixed - */ - function verify($message, $signature, $format = 'Raw') - { - $format = self::validatePlugin('Signature', $format); - if ($format === false) { - return false; - } - - $params = $format::load($signature); - if ($params === false || count($params) != 2) { - return false; - } - extract($params); - - if (empty($this->y) || empty($this->p)) { - return false; - } - - $q_1 = $this->q->subtract(self::$one); - if (!$r->between(self::$one, $q_1) || !$s->between(self::$one, $q_1)) { - return false; - } - - $w = $s->modInverse($this->q); - $h = $this->hash->hash($message); - $h = $this->bits2int($h); - list(, $u1) = $h->multiply($w)->divide($this->q); - list(, $u2) = $r->multiply($w)->divide($this->q); - $v1 = $this->g->powMod($u1, $this->p); - $v2 = $this->y->powMod($u2, $this->p); - list(, $v) = $v1->multiply($v2)->divide($this->p); - list(, $v) = $v->divide($this->q); - - return Strings::equals($v->toBytes(), $r->toBytes()); - } -} \ No newline at end of file diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Keys/OpenSSH.php b/lib/phpaes/phpseclib/Crypt/DSA/Keys/OpenSSH.php deleted file mode 100644 index 6458ba358b..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Keys/OpenSSH.php +++ /dev/null @@ -1,92 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Keys; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; -use phpseclib\Crypt\Common\Keys\OpenSSH as Progenitor; - -/** - * OpenSSH Formatted DSA Key Handler - * - * @package DSA - * @author Jim Wigginton - * @access public - */ -abstract class OpenSSH extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, 'ssh-dss'); - if ($key === false) { - return false; - } - - $result = Strings::unpackSSH2('iiii', $key); - if ($result === false) { - return false; - } - list($p, $q, $g, $y) = $result; - - $comment = parent::getComment($key); - - return compact('p', 'q', 'g', 'y', 'comment'); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - if ($q->getLength() != 160) { - throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); - } - - // from : - // string "ssh-dss" - // mpint p - // mpint q - // mpint g - // mpint y - $DSAPublicKey = Strings::packSSH2('siiii', 'ssh-dss', $p, $q, $g, $y); - - if (self::$binary) { - return $DSAPublicKey; - } - - $DSAPublicKey = 'ssh-dss ' . Base64::encode($DSAPublicKey) . ' ' . self::$comment; - - return $DSAPublicKey; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS1.php b/lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS1.php deleted file mode 100644 index 7a3920ba8b..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS1.php +++ /dev/null @@ -1,149 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Keys; - -use phpseclib\Math\BigInteger; -use phpseclib\Crypt\Common\Keys\PKCS1 as Progenitor; -use phpseclib\File\ASN1; -use phpseclib\File\ASN1\Maps; -use ParagonIE\ConstantTime\Base64; - -/** - * PKCS#1 Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PKCS1 extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $key = parent::load($key, $password); - if ($key === false) { - return false; - } - - $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { - return false; - } - - $key = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP); - if (is_array($key)) { - return $key; - } - - $key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP); - if (is_array($key)) { - return $key; - } - - $key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP); - return is_array($key) ? $key : false; - } - - /** - * Convert DSA parameters to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @return string - */ - public static function saveParameters(BigInteger $p, BigInteger $q, BigInteger $g) - { - $key = [ - 'p' => $p, - 'q' => $q, - 'g' => $g - ]; - - $key = ASN1::encodeDER($key, Maps\DSAParams::MAP); - - return "-----BEGIN DSA PARAMETERS-----\r\n" . - chunk_split(Base64::encode($key), 64) . - "-----END DSA PARAMETERS-----\r\n"; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $x - * @param \phpseclib\Math\BigInteger $y - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '') - { - $key = [ - 'version' => 0, - 'p' => $p, - 'q' => $q, - 'g' => $g, - 'y' => $y, - 'x' => $x - ]; - - $key = ASN1::encodeDER($key, Maps\DSAPrivateKey::MAP); - - return self::wrapPrivateKey($key, 'DSA', $password); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP); - - return self::wrapPublicKey($key, 'DSA'); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS8.php b/lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS8.php deleted file mode 100644 index 1415175aa1..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Keys/PKCS8.php +++ /dev/null @@ -1,169 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Keys; - -use phpseclib\Math\BigInteger; -use phpseclib\Crypt\Common\Keys\PKCS8 as Progenitor; -use phpseclib\File\ASN1; -use phpseclib\File\ASN1\Maps; - -/** - * PKCS#8 Formatted DSA Key Handler - * - * @package DSA - * @author Jim Wigginton - * @access public - */ -abstract class PKCS8 extends Progenitor -{ - /** - * OID Name - * - * @var string - * @access private - */ - const OID_NAME = 'id-dsa'; - - /** - * OID Value - * - * @var string - * @access private - */ - const OID_VALUE = '1.2.840.10040.4.1'; - - /** - * Child OIDs loaded - * - * @var bool - * @access private - */ - protected static $childOIDsLoaded = false; - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $isPublic = strpos($key, 'PUBLIC') !== false; - - $key = parent::load($key, $password); - if ($key === false) { - return false; - } - - $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey'; - - switch (true) { - case !$isPublic && $type == 'publicKey': - case $isPublic && $type == 'privateKey': - return false; - } - - $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element); - if (empty($decoded)) { - return false; - } - $components = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP); - if (!is_array($components)) { - return false; - } - - $decoded = ASN1::decodeBER($key[$type]); - if (empty($decoded)) { - return false; - } - - $var = $type == 'privateKey' ? 'x' : 'y'; - $components[$var] = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP); - if (!$components[$var] instanceof BigInteger) { - return false; - } - - if (isset($key['meta'])) { - $components['meta'] = $key['meta']; - } - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $x - * @param \phpseclib\Math\BigInteger $y - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '') - { - $params = [ - 'p' => $p, - 'q' => $q, - 'g' => $g - ]; - $params = ASN1::encodeDER($params, Maps\DSAParams::MAP); - $params = new ASN1\Element($params); - $key = ASN1::encodeDER($x, Maps\DSAPublicKey::MAP); - return self::wrapPrivateKey($key, [], $params, $password); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - $params = [ - 'p' => $p, - 'q' => $q, - 'g' => $g - ]; - $params = ASN1::encodeDER($params, Maps\DSAParams::MAP); - $params = new ASN1\Element($params); - $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP); - return self::wrapPublicKey($key, $params); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Keys/PuTTY.php b/lib/phpaes/phpseclib/Crypt/DSA/Keys/PuTTY.php deleted file mode 100644 index 7b2976313c..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Keys/PuTTY.php +++ /dev/null @@ -1,129 +0,0 @@ - 160 kinda useless, hence this handlers not supporting such keys. - * - * PHP version 5 - * - * @category Crypt - * @package DSA - * @author Jim Wigginton - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Keys; - -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; -use phpseclib\Crypt\Common\Keys\PuTTY as Progenitor; - -/** - * PuTTY Formatted DSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PuTTY extends Progenitor -{ - /** - * Public Handler - * - * @var string - * @access private - */ - const PUBLIC_HANDLER = 'phpseclib\Crypt\DSA\Keys\OpenSSH'; - - /** - * Algorithm Identifier - * - * @var string - * @access private - */ - const TYPE = 'ssh-dss'; - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $components = parent::load($key, $password); - if ($components === false || !isset($components['private'])) { - return $components; - } - extract($components); - unset($components['public'], $components['private']); - - $result = Strings::unpackSSH2('iiii', $public); - if ($result === false) { - return false; - } - list($p, $q, $g, $y) = $result; - - $result = Strings::unpackSSH2('i', $private); - if ($result === false) { - return false; - } - list($x) = $result; - - return compact('p', 'q', 'g', 'y', 'x', 'comment'); - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @param \phpseclib\Math\BigInteger $x - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '') - { - if ($q->getLength() != 160) { - throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); - } - - $public = Strings::packSSH2('iiii', $p, $q, $g, $y); - $private = Strings::packSSH2('i', $x); - - return self::wrapPrivateKey($public, $private, $password); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - if ($q->getLength() != 160) { - throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); - } - - return self::wrapPublicKey(Strings::packSSH2('iiii', $p, $q, $g, $y)); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Keys/Raw.php b/lib/phpaes/phpseclib/Crypt/DSA/Keys/Raw.php deleted file mode 100644 index 18d0b03a68..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Keys/Raw.php +++ /dev/null @@ -1,95 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Keys; - -use phpseclib\Math\BigInteger; - -/** - * Raw DSA Key Handler - * - * @package DSA - * @author Jim Wigginton - * @access public - */ -abstract class Raw -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param array $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_array($key)) { - return false; - } - - switch (true) { - case !isset($key['p']) || !isset($key['q']) || !isset($key['g']): - case !$key['p'] instanceof BigInteger: - case !$key['q'] instanceof BigInteger: - case !$key['g'] instanceof BigInteger: - case !isset($key['x']) && !isset($key['y']): - case isset($key['x']) && !$key['x'] instanceof BigInteger: - case isset($key['y']) && !$key['y'] instanceof BigInteger: - return false; - } - - $options = ['p' => 1, 'q' => 1, 'g' => 1, 'x' => 1, 'y' => 1]; - - return array_intersect_key($key, $options); - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @param \phpseclib\Math\BigInteger $x - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '') - { - return compact('p', 'q', 'g', 'y', 'x'); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - return compact('p', 'q', 'g', 'y'); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Keys/XML.php b/lib/phpaes/phpseclib/Crypt/DSA/Keys/XML.php deleted file mode 100644 index f750a589d7..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Keys/XML.php +++ /dev/null @@ -1,129 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Keys; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Math\BigInteger; - -/** - * XML Formatted DSA Key Handler - * - * @package DSA - * @author Jim Wigginton - * @access public - */ -abstract class XML -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $use_errors = libxml_use_internal_errors(true); - - $dom = new \DOMDocument(); - if (!$dom->loadXML('' . $key . '')) { - return false; - } - $xpath = new \DOMXPath($dom); - $keys = ['p', 'q', 'g', 'y', 'j', 'seed', 'pgencounter']; - foreach ($keys as $key) { - // $dom->getElementsByTagName($key) is case-sensitive - $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']"); - if (!$temp->length) { - continue; - } - $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256); - switch ($key) { - case 'p': // a prime modulus meeting the [DSS] requirements - // Parameters P, Q, and G can be public and common to a group of users. They might be known - // from application context. As such, they are optional but P and Q must either both appear - // or both be absent - $components['p'] = $value; - break; - case 'q': // an integer in the range 2**159 < Q < 2**160 which is a prime divisor of P-1 - $components['q'] = $value; - break; - case 'g': // an integer with certain properties with respect to P and Q - $components['g'] = $value; - break; - case 'y': // G**X mod P (where X is part of the private key and not made public) - $components['y'] = $value; - // the remaining options do not do anything - case 'j': // (P - 1) / Q - // Parameter J is available for inclusion solely for efficiency as it is calculatable from - // P and Q - case 'seed': // a DSA prime generation seed - // Parameters seed and pgenCounter are used in the DSA prime number generation algorithm - // specified in [DSS]. As such, they are optional but must either both be present or both - // be absent - case 'pgencounter': // a DSA prime generation counter - } - } - - libxml_use_internal_errors($use_errors); - - if (!isset($components['y'])) { - return false; - } - - switch (true) { - case !isset($components['p']): - case !isset($components['q']): - case !isset($components['g']): - return ['y' => $components['y']]; - } - - return $components; - } - - /** - * Convert a public key to the appropriate format - * - * See https://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue - * - * @access public - * @param \phpseclib\Math\BigInteger $p - * @param \phpseclib\Math\BigInteger $q - * @param \phpseclib\Math\BigInteger $g - * @param \phpseclib\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - return "\r\n" . - '

' . Base64::encode($p->toBytes()) . "

\r\n" . - ' ' . Base64::encode($q->toBytes()) . "\r\n" . - ' ' . Base64::encode($g->toBytes()) . "\r\n" . - ' ' . Base64::encode($y->toBytes()) . "\r\n" . - '
'; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Signature/PKCS.php b/lib/phpaes/phpseclib/Crypt/DSA/Signature/PKCS.php deleted file mode 100644 index fa09e54a6e..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Signature/PKCS.php +++ /dev/null @@ -1,68 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Signature; - -use phpseclib\Math\BigInteger; -use phpseclib\File\ASN1; -use phpseclib\File\ASN1\Maps; - -/** - * PKCS Signature Handler - * - * @package Common - * @author Jim Wigginton - * @access public - */ -abstract class PKCS -{ - /** - * Loads a signature - * - * @access public - * @param array $key - * @return array - */ - public static function load($sig) - { - if (!is_string($sig)) { - return false; - } - - $decoded = ASN1::decodeBER($sig); - if (empty($decoded)) { - return false; - } - $components = ASN1::asn1map($decoded[0], Maps\DssSigValue::MAP); - - return $components; - } - - /** - * Returns a signature in the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $r - * @param \phpseclib\Math\BigInteger $s - * @return string - */ - public static function save(BigInteger $r, BigInteger $s) - { - return ASN1::encodeDER(compact('r', 's'), Maps\DssSigValue::MAP); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Signature/Raw.php b/lib/phpaes/phpseclib/Crypt/DSA/Signature/Raw.php deleted file mode 100644 index 03f20ca49d..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Signature/Raw.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Signature; - -use phpseclib\Crypt\Common\Signature\Raw as Progenitor; - -/** - * Raw DSA Signature Handler - * - * @package DSA - * @author Jim Wigginton - * @access public - */ -abstract class Raw extends Progenitor -{ -} diff --git a/lib/phpaes/phpseclib/Crypt/DSA/Signature/SSH2.php b/lib/phpaes/phpseclib/Crypt/DSA/Signature/SSH2.php deleted file mode 100644 index 0e781b3585..0000000000 --- a/lib/phpaes/phpseclib/Crypt/DSA/Signature/SSH2.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\DSA\Signature; - -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; - -/** - * SSH2 Signature Handler - * - * @package Common - * @author Jim Wigginton - * @access public - */ -abstract class SSH2 -{ - /** - * Loads a signature - * - * @access public - * @param array $key - * @return array - */ - public static function load($sig) - { - if (!is_string($sig)) { - return false; - } - - $result = Strings::unpackSSH2('ss', $sig); - if ($result === false) { - return false; - } - list($type, $blob) = $result; - if ($type != 'ssh-dss' || strlen($blob) != 40) { - return false; - } - - return [ - 'r' => new BigInteger(substr($blob, 0, 20), 256), - 's' => new BigInteger(substr($blob, 20), 256) - ]; - } - - /** - * Returns a signature in the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $r - * @param \phpseclib\Math\BigInteger $s - * @return string - */ - public static function save(BigInteger $r, BigInteger $s) - { - if ($r->getLength() != 160 || $s->getLength != 160) { - return false; - } - return Strings::pack('ss', $r, $s); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Hash.php b/lib/phpaes/phpseclib/Crypt/Hash.php deleted file mode 100644 index 54d4664803..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Hash.php +++ /dev/null @@ -1,483 +0,0 @@ - - * setKey('abcdefg'); - * - * echo base64_encode($hash->hash('abcdefg')); - * ?> - * - * - * @category Crypt - * @package Hash - * @author Jim Wigginton - * @copyright 2015 Jim Wigginton - * @author Andreas Fischer - * @copyright 2015 Andreas Fischer - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use phpseclib\Math\BigInteger; -use phpseclib\Exception\UnsupportedAlgorithmException; -use phpseclib\Common\Functions\Strings; - -/** - * @package Hash - * @author Jim Wigginton - * @author Andreas Fischer - * @access public - */ -class Hash -{ - /** - * Hash Parameter - * - * @see self::setHash() - * @var int - * @access private - */ - private $hashParam; - - /** - * Byte-length of hash output (Internal HMAC) - * - * @see self::setHash() - * @var int - * @access private - */ - private $length; - - /** - * Hash Algorithm - * - * @see self::setHash() - * @var string - * @access private - */ - private $hash; - - /** - * Key - * - * @see self::setKey() - * @var string - * @access private - */ - private $key = false; - - /** - * Initial Hash - * - * Used only for sha512/* - * - * @see self::_sha512() - * @var array - * @access private - */ - private $initial = false; - - /** - * Outer XOR (Internal HMAC) - * - * Used only for sha512/* - * - * @see self::hash() - * @var string - * @access private - */ - private $opad; - - /** - * Inner XOR (Internal HMAC) - * - * Used only for sha512/* - * - * @see self::hash() - * @var string - * @access private - */ - private $ipad; - - /** - * Default Constructor. - * - * @param string $hash - * @access public - */ - public function __construct($hash = 'sha256') - { - $this->setHash($hash); - - $this->ipad = str_repeat(chr(0x36), 128); - $this->opad = str_repeat(chr(0x5C), 128); - } - - /** - * Sets the key for HMACs - * - * Keys can be of any length. - * - * @access public - * @param string $key - */ - public function setKey($key = false) - { - $this->key = $key; - } - - /** - * Gets the hash function. - * - * As set by the constructor or by the setHash() method. - * - * @access public - * @return string - */ - public function getHash() - { - return $this->hashParam; - } - - /** - * Sets the hash function. - * - * @access public - * @param string $hash - */ - public function setHash($hash) - { - $this->hashParam = $hash = strtolower($hash); - switch ($hash) { - case 'md2-96': - case 'md5-96': - case 'sha1-96': - case 'sha224-96': - case 'sha256-96': - case 'sha384-96': - case 'sha512-96': - case 'sha512/224-96': - case 'sha512/256-96': - $hash = substr($hash, 0, -3); - $this->length = 12; // 96 / 8 = 12 - break; - case 'md2': - case 'md5': - $this->length = 16; - break; - case 'sha1': - $this->length = 20; - break; - case 'sha224': - case 'sha512/224': - $this->length = 28; - break; - case 'sha256': - case 'sha512/256': - $this->length = 32; - break; - case 'sha384': - $this->length = 48; - break; - case 'sha512': - $this->length = 64; - break; - default: - throw new UnsupportedAlgorithmException( - "$hash is not a supported algorithm" - ); - } - - switch ($hash) { - case 'md2-96': - case 'md5-96': - case 'sha1-96': - case 'sha224-96': - case 'sha256-96': - case 'md2': - case 'md5': - case 'sha1': - case 'sha224': - case 'sha256': - $this->blockSize = 512; - break; - default: - $this->blockSize = 1024; - } - - if ($hash == 'sha512/224' || $hash == 'sha512/256') { - // from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24 - $this->initial = $hash == 'sha512/256' ? - array( - '22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD', - '96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2' - ) : - array( - '8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF', - '0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1' - ); - for ($i = 0; $i < 8; $i++) { - $this->initial[$i] = new BigInteger($this->initial[$i], 16); - $this->initial[$i]->setPrecision(64); - } - } - - $this->hash = $hash; - } - - /** - * Compute the HMAC. - * - * @access public - * @param string $text - * @return string - */ - public function hash($text) - { - switch ($this->hash) { - case 'sha512/224': - case 'sha512/256': - if (empty($this->key) || !is_string($this->key)) { - return substr(self::_sha512($text, $this->initial), 0, $this->length); - } - /* "Applications that use keys longer than B bytes will first hash the key using H and then use the - resultant L byte string as the actual key to HMAC." - - -- http://tools.ietf.org/html/rfc2104#section-2 */ - $key = strlen($this->key) > $this->b ? self::_sha512($this->key, $this->initial) : $this->key; - - $key = str_pad($this->key, 128, chr(0)); // step 1 - $temp = $this->ipad ^ $this->key; // step 2 - $temp .= $text; // step 3 - $temp = self::_sha512($temp, $this->initial); // step 4 - $output = $this->opad ^ $this->key; // step 5 - $output.= $temp; // step 6 - $output = self::_sha512($output, $this->initial); // step 7 - - return substr($output, 0, $this->length); - } - $output = !empty($this->key) || is_string($this->key) ? - hash_hmac($this->hash, $text, $this->key, true) : - hash($this->hash, $text, true); - - return strlen($output) > $this->length - ? substr($output, 0, $this->length) - : $output; - } - - /** - * Returns the hash length (in bits) - * - * @access public - * @return int - */ - public function getLength() - { - return $this->length << 3; - } - - /** - * Returns the hash length (in bytes) - * - * @access public - * @return int - */ - public function getLengthInBytes() - { - return $this->length; - } - - /** - * Returns the block length (in bits) - * - * @access public - * @return int - */ - public function getBlockLength() - { - return $this->blockSize; - } - - /** - * Returns the block length (in bytes) - * - * @access public - * @return int - */ - public function getBlockLengthInBytes() - { - return $this->blockSize >> 3; - } - - /** - * Pure-PHP implementation of SHA512 - * - * @access private - * @param string $m - */ - private static function _sha512($m, $hash) - { - static $k; - - if (!isset($k)) { - // Initialize table of round constants - // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) - $k = array( - '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', - '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', - 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', - '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', - 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', - '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', - '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', - 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', - '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', - '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', - 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', - 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', - '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', - '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', - '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', - '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', - 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', - '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', - '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', - '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' - ); - - for ($i = 0; $i < 80; $i++) { - $k[$i] = new BigInteger($k[$i], 16); - } - } - - // Pre-processing - $length = strlen($m); - // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 - $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); - $m[$length] = chr(0x80); - // we don't support hashing strings 512MB long - $m.= pack('N4', 0, 0, 0, $length << 3); - - // Process the message in successive 1024-bit chunks - $chunks = str_split($m, 128); - foreach ($chunks as $chunk) { - $w = array(); - for ($i = 0; $i < 16; $i++) { - $temp = new BigInteger(Strings::shift($chunk, 8), 256); - $temp->setPrecision(64); - $w[] = $temp; - } - - // Extend the sixteen 32-bit words into eighty 32-bit words - for ($i = 16; $i < 80; $i++) { - $temp = array( - $w[$i - 15]->bitwise_rightRotate(1), - $w[$i - 15]->bitwise_rightRotate(8), - $w[$i - 15]->bitwise_rightShift(7) - ); - $s0 = $temp[0]->bitwise_xor($temp[1]); - $s0 = $s0->bitwise_xor($temp[2]); - $temp = array( - $w[$i - 2]->bitwise_rightRotate(19), - $w[$i - 2]->bitwise_rightRotate(61), - $w[$i - 2]->bitwise_rightShift(6) - ); - $s1 = $temp[0]->bitwise_xor($temp[1]); - $s1 = $s1->bitwise_xor($temp[2]); - $w[$i] = clone $w[$i - 16]; - $w[$i] = $w[$i]->add($s0); - $w[$i] = $w[$i]->add($w[$i - 7]); - $w[$i] = $w[$i]->add($s1); - } - - // Initialize hash value for this chunk - $a = clone $hash[0]; - $b = clone $hash[1]; - $c = clone $hash[2]; - $d = clone $hash[3]; - $e = clone $hash[4]; - $f = clone $hash[5]; - $g = clone $hash[6]; - $h = clone $hash[7]; - - // Main loop - for ($i = 0; $i < 80; $i++) { - $temp = array( - $a->bitwise_rightRotate(28), - $a->bitwise_rightRotate(34), - $a->bitwise_rightRotate(39) - ); - $s0 = $temp[0]->bitwise_xor($temp[1]); - $s0 = $s0->bitwise_xor($temp[2]); - $temp = array( - $a->bitwise_and($b), - $a->bitwise_and($c), - $b->bitwise_and($c) - ); - $maj = $temp[0]->bitwise_xor($temp[1]); - $maj = $maj->bitwise_xor($temp[2]); - $t2 = $s0->add($maj); - - $temp = array( - $e->bitwise_rightRotate(14), - $e->bitwise_rightRotate(18), - $e->bitwise_rightRotate(41) - ); - $s1 = $temp[0]->bitwise_xor($temp[1]); - $s1 = $s1->bitwise_xor($temp[2]); - $temp = array( - $e->bitwise_and($f), - $g->bitwise_and($e->bitwise_not()) - ); - $ch = $temp[0]->bitwise_xor($temp[1]); - $t1 = $h->add($s1); - $t1 = $t1->add($ch); - $t1 = $t1->add($k[$i]); - $t1 = $t1->add($w[$i]); - - $h = clone $g; - $g = clone $f; - $f = clone $e; - $e = $d->add($t1); - $d = clone $c; - $c = clone $b; - $b = clone $a; - $a = $t1->add($t2); - } - - // Add this chunk's hash to result so far - $hash = array( - $hash[0]->add($a), - $hash[1]->add($b), - $hash[2]->add($c), - $hash[3]->add($d), - $hash[4]->add($e), - $hash[5]->add($f), - $hash[6]->add($g), - $hash[7]->add($h) - ); - } - - // Produce the final hash value (big-endian) - // (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) - $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . - $hash[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes(); - - return $temp; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RC2.php b/lib/phpaes/phpseclib/Crypt/RC2.php deleted file mode 100644 index 8854be5115..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RC2.php +++ /dev/null @@ -1,665 +0,0 @@ - - * setKey('abcdefgh'); - * - * $plaintext = str_repeat('a', 1024); - * - * echo $rc2->decrypt($rc2->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package RC2 - * @author Patrick Monnerat - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use phpseclib\Crypt\Common\BlockCipher; - -/** - * Pure-PHP implementation of RC2. - * - * @package RC2 - * @access public - */ -class RC2 extends BlockCipher -{ - /** - * Block Length of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::block_size - * @var int - * @access private - */ - protected $block_size = 8; - - /** - * The Key - * - * @see \phpseclib\Crypt\Common\SymmetricKey::key - * @see self::setKey() - * @var string - * @access private - */ - protected $key; - - /** - * The Original (unpadded) Key - * - * @see \phpseclib\Crypt\Common\SymmetricKey::key - * @see self::setKey() - * @see self::encrypt() - * @see self::decrypt() - * @var string - * @access private - */ - private $orig_key; - - /** - * Don't truncate / null pad key - * - * @see \phpseclib\Crypt\Common\SymmetricKey::clearBuffers() - * @var bool - * @access private - */ - private $skip_key_adjustment = true; - - /** - * Key Length (in bytes) - * - * @see \phpseclib\Crypt\RC2::setKeyLength() - * @var int - * @access private - */ - protected $key_length = 16; // = 128 bits - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - * @access private - */ - protected $cipher_name_mcrypt = 'rc2'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - * @access private - */ - protected $cfb_init_len = 500; - - /** - * The key length in bits. - * - * @see self::setKeyLength() - * @see self::setKey() - * @var int - * @access private - * @internal Should be in range [1..1024]. - * @internal Changing this value after setting the key has no effect. - */ - private $default_key_length = 1024; - - /** - * The key length in bits. - * - * @see self::isValidEnine() - * @see self::setKey() - * @var int - * @access private - * @internal Should be in range [1..1024]. - */ - private $current_key_length; - - /** - * The Key Schedule - * - * @see self::setupKey() - * @var array - * @access private - */ - private $keys; - - /** - * Key expansion randomization table. - * Twice the same 256-value sequence to save a modulus in key expansion. - * - * @see self::setKey() - * @var array - * @access private - */ - private $pitable = [ - 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, - 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D, - 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, - 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, - 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, - 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, - 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, - 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82, - 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, - 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, - 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1, - 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, - 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, - 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03, - 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, - 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, - 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7, - 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, - 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, - 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC, - 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, - 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, - 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, - 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, - 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, - 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9, - 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, - 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, - 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0, - 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, - 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, - 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD, - 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, - 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D, - 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, - 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, - 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, - 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, - 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, - 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82, - 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, - 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, - 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1, - 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, - 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, - 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03, - 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, - 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, - 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7, - 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, - 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, - 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC, - 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, - 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, - 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, - 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, - 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, - 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9, - 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, - 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, - 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0, - 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, - 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, - 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD - ]; - - /** - * Inverse key expansion randomization table. - * - * @see self::setKey() - * @var array - * @access private - */ - private $invpitable = [ - 0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66, - 0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4, - 0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20, - 0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53, - 0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68, - 0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B, - 0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12, - 0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB, - 0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3, - 0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26, - 0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67, - 0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB, - 0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC, - 0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60, - 0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7, - 0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD, - 0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24, - 0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31, - 0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE, - 0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99, - 0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C, - 0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA, - 0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35, - 0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61, - 0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72, - 0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3, - 0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F, - 0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9, - 0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77, - 0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75, - 0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87, - 0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6 - ]; - - /** - * Default Constructor. - * - * @param int $mode - * @access public - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - if ($mode == self::MODE_STREAM) { - throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode'); - } - - parent::__construct($mode); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @access public - * @return bool - */ - public function isValidEngine($engine) - { - switch ($engine) { - case self::ENGINE_OPENSSL: - if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) { - return false; - } - $this->cipher_name_openssl_ecb = 'rc2-ecb'; - $this->cipher_name_openssl = 'rc2-' . $this->openssl_translate_mode(); - } - - return parent::isValidEngine($engine); - } - - /** - * Sets the key length. - * - * Valid key lengths are 8 to 1024. - * Calling this function after setting the key has no effect until the next - * \phpseclib\Crypt\RC2::setKey() call. - * - * @access public - * @param int $length in bits - * @throws \LengthException if the key length isn't supported - */ - public function setKeyLength($length) - { - if ($length < 8 || $length > 1024) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported'); - } - - $this->default_key_length = $this->current_key_length = $length; - $this->explicit_key_length = $length >> 3; - } - - /** - * Returns the current key length - * - * @access public - * @return int - */ - public function getKeyLength() - { - return $this->current_key_length; - } - - /** - * Sets the key. - * - * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg. - * strlen($key) <= 128), however, we only use the first 128 bytes if $key - * has more then 128 bytes in it, and set $key to a single null byte if - * it is empty. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setKey() - * @access public - * @param string $key - * @param int $t1 optional Effective key length in bits. - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key, $t1 = false) - { - $this->orig_key = $key; - - if ($t1 === false) { - $t1 = $this->default_key_length; - } - - if ($t1 < 1 || $t1 > 1024) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported'); - } - - $this->current_key_length = $t1; - if (strlen($key) < 1 || strlen($key) > 128) { - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes between 8 and 1024 bits, inclusive, are supported'); - } - - $t = strlen($key); - - // The mcrypt RC2 implementation only supports effective key length - // of 1024 bits. It is however possible to handle effective key - // lengths in range 1..1024 by expanding the key and applying - // inverse pitable mapping to the first byte before submitting it - // to mcrypt. - - // Key expansion. - $l = array_values(unpack('C*', $key)); - $t8 = ($t1 + 7) >> 3; - $tm = 0xFF >> (8 * $t8 - $t1); - - // Expand key. - $pitable = $this->pitable; - for ($i = $t; $i < 128; $i++) { - $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]]; - } - $i = 128 - $t8; - $l[$i] = $pitable[$l[$i] & $tm]; - while ($i--) { - $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]]; - } - - // Prepare the key for mcrypt. - $l[0] = $this->invpitable[$l[0]]; - array_unshift($l, 'C*'); - - $this->key = call_user_func_array('pack', $l); - $this->key_length = strlen($this->key); - $this->changed = true; - $this->setEngine(); - } - - /** - * Encrypts a message. - * - * Mostly a wrapper for \phpseclib\Crypt\Common\SymmetricKey::encrypt, with some additional OpenSSL handling code - * - * @see self::decrypt() - * @access public - * @param string $plaintext - * @return string $ciphertext - */ - public function encrypt($plaintext) - { - if ($this->engine == self::ENGINE_OPENSSL) { - $temp = $this->key; - $this->key = $this->orig_key; - $result = parent::encrypt($plaintext); - $this->key = $temp; - return $result; - } - - return parent::encrypt($plaintext); - } - - /** - * Decrypts a message. - * - * Mostly a wrapper for \phpseclib\Crypt\Common\SymmetricKey::decrypt, with some additional OpenSSL handling code - * - * @see self::encrypt() - * @access public - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - if ($this->engine == self::ENGINE_OPENSSL) { - $temp = $this->key; - $this->key = $this->orig_key; - $result = parent::decrypt($ciphertext); - $this->key = $temp; - return $result; - } - - return parent::decrypt($ciphertext); - } - - /** - * Encrypts a block - * - * @see \phpseclib\Crypt\Common\SymmetricKey::encryptBlock() - * @see \phpseclib\Crypt\Common\SymmetricKey::encrypt() - * @access private - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in)); - $keys = $this->keys; - $limit = 20; - $actions = [$limit => 44, 44 => 64]; - $j = 0; - - for (;;) { - // Mixing round. - $r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1; - $r0 |= $r0 >> 16; - $r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2; - $r1 |= $r1 >> 16; - $r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3; - $r2 |= $r2 >> 16; - $r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5; - $r3 |= $r3 >> 16; - - if ($j === $limit) { - if ($limit === 64) { - break; - } - - // Mashing round. - $r0 += $keys[$r3 & 0x3F]; - $r1 += $keys[$r0 & 0x3F]; - $r2 += $keys[$r1 & 0x3F]; - $r3 += $keys[$r2 & 0x3F]; - $limit = $actions[$limit]; - } - } - - return pack('vvvv', $r0, $r1, $r2, $r3); - } - - /** - * Decrypts a block - * - * @see \phpseclib\Crypt\Common\SymmetricKey::decryptBlock() - * @see \phpseclib\Crypt\Common\SymmetricKey::decrypt() - * @access private - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in)); - $keys = $this->keys; - $limit = 44; - $actions = [$limit => 20, 20 => 0]; - $j = 64; - - for (;;) { - // R-mixing round. - $r3 = ($r3 | ($r3 << 16)) >> 5; - $r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF; - $r2 = ($r2 | ($r2 << 16)) >> 3; - $r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF; - $r1 = ($r1 | ($r1 << 16)) >> 2; - $r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF; - $r0 = ($r0 | ($r0 << 16)) >> 1; - $r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF; - - if ($j === $limit) { - if ($limit === 0) { - break; - } - - // R-mashing round. - $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF; - $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF; - $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF; - $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF; - $limit = $actions[$limit]; - } - } - - return pack('vvvv', $r0, $r1, $r2, $r3); - } - - /** - * Creates the key schedule - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setupKey() - * @access private - */ - protected function setupKey() - { - if (!isset($this->key)) { - $this->setKey(''); - } - - // Key has already been expanded in \phpseclib\Crypt\RC2::setKey(): - // Only the first value must be altered. - $l = unpack('Ca/Cb/v*', $this->key); - array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8)); - unset($l['a']); - unset($l['b']); - $this->keys = $l; - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setupInlineCrypt() - * @access private - */ - protected function setupInlineCrypt() - { - // Init code for both, encrypt and decrypt. - $init_crypt = '$keys = $this->keys;'; - - $keys = $this->keys; - - // $in is the current 8 bytes block which has to be en/decrypt - $encrypt_block = $decrypt_block = ' - $in = unpack("v4", $in); - $r0 = $in[1]; - $r1 = $in[2]; - $r2 = $in[3]; - $r3 = $in[4]; - '; - - // Create code for encryption. - $limit = 20; - $actions = [$limit => 44, 44 => 64]; - $j = 0; - - for (;;) { - // Mixing round. - $encrypt_block .= ' - $r0 = (($r0 + ' . $keys[$j++] . ' + - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1; - $r0 |= $r0 >> 16; - $r1 = (($r1 + ' . $keys[$j++] . ' + - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2; - $r1 |= $r1 >> 16; - $r2 = (($r2 + ' . $keys[$j++] . ' + - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3; - $r2 |= $r2 >> 16; - $r3 = (($r3 + ' . $keys[$j++] . ' + - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5; - $r3 |= $r3 >> 16;'; - - if ($j === $limit) { - if ($limit === 64) { - break; - } - - // Mashing round. - $encrypt_block .= ' - $r0 += $keys[$r3 & 0x3F]; - $r1 += $keys[$r0 & 0x3F]; - $r2 += $keys[$r1 & 0x3F]; - $r3 += $keys[$r2 & 0x3F];'; - $limit = $actions[$limit]; - } - } - - $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);'; - - // Create code for decryption. - $limit = 44; - $actions = [$limit => 20, 20 => 0]; - $j = 64; - - for (;;) { - // R-mixing round. - $decrypt_block .= ' - $r3 = ($r3 | ($r3 << 16)) >> 5; - $r3 = ($r3 - ' . $keys[--$j] . ' - - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF; - $r2 = ($r2 | ($r2 << 16)) >> 3; - $r2 = ($r2 - ' . $keys[--$j] . ' - - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF; - $r1 = ($r1 | ($r1 << 16)) >> 2; - $r1 = ($r1 - ' . $keys[--$j] . ' - - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF; - $r0 = ($r0 | ($r0 << 16)) >> 1; - $r0 = ($r0 - ' . $keys[--$j] . ' - - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;'; - - if ($j === $limit) { - if ($limit === 0) { - break; - } - - // R-mashing round. - $decrypt_block .= ' - $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF; - $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF; - $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF; - $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;'; - $limit = $actions[$limit]; - } - } - - $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);'; - - // Creates the inline-crypt function - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ] - ); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RC4.php b/lib/phpaes/phpseclib/Crypt/RC4.php deleted file mode 100644 index 66ac9957ec..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RC4.php +++ /dev/null @@ -1,332 +0,0 @@ - - * setKey('abcdefgh'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $rc4->decrypt($rc4->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package RC4 - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use phpseclib\Crypt\Common\StreamCipher; - -/** - * Pure-PHP implementation of RC4. - * - * @package RC4 - * @author Jim Wigginton - * @access public - */ -class RC4 extends StreamCipher -{ - /**#@+ - * @access private - * @see \phpseclib\Crypt\RC4::_crypt() - */ - const ENCRYPT = 0; - const DECRYPT = 1; - /**#@-*/ - - /** - * Block Length of the cipher - * - * RC4 is a stream cipher - * so we the block_size to 0 - * - * @see \phpseclib\Crypt\Common\SymmetricKey::block_size - * @var int - * @access private - */ - protected $block_size = 0; - - /** - * Key Length (in bytes) - * - * @see \phpseclib\Crypt\RC4::setKeyLength() - * @var int - * @access private - */ - protected $key_length = 128; // = 1024 bits - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - * @access private - */ - protected $cipher_name_mcrypt = 'arcfour'; - - /** - * Holds whether performance-optimized $inline_crypt() can/should be used. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::inline_crypt - * @var mixed - * @access private - */ - protected $use_inline_crypt = false; // currently not available - - /** - * The Key - * - * @see self::setKey() - * @var string - * @access private - */ - protected $key; - - /** - * The Key Stream for decryption and encryption - * - * @see self::setKey() - * @var array - * @access private - */ - private $stream; - - /** - * Default Constructor. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - * @return \phpseclib\Crypt\RC4 - * @access public - */ - public function __construct() - { - parent::__construct(self::MODE_STREAM); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @access public - * @return bool - */ - public function isValidEngine($engine) - { - if ($engine == self::ENGINE_OPENSSL) { - $this->cipher_name_openssl = 'rc4-40'; - } - - return parent::isValidEngine($engine); - } - - /** - * RC4 does not use an IV - * - * @access public - * @return bool - */ - public function usesIV() - { - return false; - } - - /** - * Sets the key length - * - * Keys can be between 1 and 256 bytes long. - * - * @access public - * @param int $length - * @throws \LengthException if the key length is invalid - */ - public function setKeyLength($length) - { - if ($length < 8 || $length > 2048) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 256 bytes are supported'); - } - - $this->key_length = $length >> 3; - - parent::setKeyLength($length); - } - - /** - * Sets the key length - * - * Keys can be between 1 and 256 bytes long. - * - * @access public - * @param int $length - * @throws \LengthException if the key length is invalid - */ - public function setKey($key) - { - $length = strlen($key); - if ($length < 1 || $length > 256) { - throw new \LengthException('Key size of ' . $length . ' bytes is not supported by RC4. Keys must be between 1 and 256 bytes long'); - } - - parent::setKey($key); - } - - /** - * Encrypts a message. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::decrypt() - * @see self::crypt() - * @access public - * @param string $plaintext - * @return string $ciphertext - */ - public function encrypt($plaintext) - { - if ($this->engine != self::ENGINE_INTERNAL) { - return parent::encrypt($plaintext); - } - return $this->crypt($plaintext, self::ENCRYPT); - } - - /** - * Decrypts a message. - * - * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). - * At least if the continuous buffer is disabled. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::encrypt() - * @see self::crypt() - * @access public - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - if ($this->engine != self::ENGINE_INTERNAL) { - return parent::decrypt($ciphertext); - } - return $this->crypt($ciphertext, self::DECRYPT); - } - - /** - * Encrypts a block - * - * @access private - * @param string $in - */ - protected function encryptBlock($in) - { - // RC4 does not utilize this method - } - - /** - * Decrypts a block - * - * @access private - * @param string $in - */ - protected function decryptBlock($in) - { - // RC4 does not utilize this method - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib\Crypt\Common\SymmetricKey::_setupKey() - * @access private - */ - protected function setupKey() - { - $key = $this->key; - $keyLength = strlen($key); - $keyStream = range(0, 255); - $j = 0; - for ($i = 0; $i < 256; $i++) { - $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255; - $temp = $keyStream[$i]; - $keyStream[$i] = $keyStream[$j]; - $keyStream[$j] = $temp; - } - - $this->stream = []; - $this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = [ - 0, // index $i - 0, // index $j - $keyStream - ]; - } - - /** - * Encrypts or decrypts a message. - * - * @see self::encrypt() - * @see self::decrypt() - * @access private - * @param string $text - * @param int $mode - * @return string $text - */ - private function crypt($text, $mode) - { - if ($this->changed) { - $this->setup(); - $this->changed = false; - } - - $stream = &$this->stream[$mode]; - if ($this->continuousBuffer) { - $i = &$stream[0]; - $j = &$stream[1]; - $keyStream = &$stream[2]; - } else { - $i = $stream[0]; - $j = $stream[1]; - $keyStream = $stream[2]; - } - - $len = strlen($text); - for ($k = 0; $k < $len; ++$k) { - $i = ($i + 1) & 255; - $ksi = $keyStream[$i]; - $j = ($j + $ksi) & 255; - $ksj = $keyStream[$j]; - - $keyStream[$i] = $ksj; - $keyStream[$j] = $ksi; - $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]); - } - - return $text; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA.php b/lib/phpaes/phpseclib/Crypt/RSA.php deleted file mode 100644 index 18f89f72aa..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA.php +++ /dev/null @@ -1,1765 +0,0 @@ - - * encrypt($plaintext); - * - * echo $privatekey->decrypt($ciphertext); - * ?> - * - * - * Here's an example of how to create signatures and verify signatures with this library: - * - * sign($plaintext); - * - * echo $publickey->verify($plaintext, $signature) ? 'verified' : 'unverified'; - * ?> - * - * - * @category Crypt - * @package RSA - * @author Jim Wigginton - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\File\ASN1; -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; -use phpseclib\File\ASN1\Maps\DigestInfo; -use phpseclib\Crypt\Common\AsymmetricKey; -use phpseclib\Exception\UnsupportedAlgorithmException; - -/** - * Pure-PHP PKCS#1 compliant implementation of RSA. - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class RSA extends AsymmetricKey -{ - /** - * Algorithm Name - * - * @var string - * @access private - */ - const ALGORITHM = 'RSA'; - - /**#@+ - * @access public - * @see self::encrypt() - * @see self::decrypt() - */ - /** - * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding} - * (OAEP) for encryption / decryption. - * - * Uses sha256 by default - * - * @see self::setHash() - * @see self::setMGFHash() - */ - const PADDING_OAEP = 1; - /** - * Use PKCS#1 padding. - * - * Although self::PADDING_OAEP / self::PADDING_PSS offers more security, including PKCS#1 padding is necessary for purposes of backwards - * compatibility with protocols (like SSH-1) written before OAEP's introduction. - */ - const PADDING_PKCS1 = 2; - /** - * Do not use any padding - * - * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy - * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc. - */ - const PADDING_NONE = 3; - /** - * Use PKCS#1 padding with PKCS1 v1.5 compatibility - * - * A PKCS1 v2.1 encrypted message may not successfully decrypt with a PKCS1 v1.5 implementation (such as OpenSSL). - */ - const PADDING_PKCS15_COMPAT = 6; - /**#@-*/ - - /**#@+ - * @access public - * @see self::sign() - * @see self::verify() - * @see self::setHash() - */ - /** - * Use the Probabilistic Signature Scheme for signing - * - * Uses sha256 and 0 as the salt length - * - * @see self::setSaltLength() - * @see self::setMGFHash() - * @see self::setHash() - */ - const PADDING_PSS = 4; - /** - * Use a relaxed version of PKCS#1 padding for signature verification - */ - const PADDING_RELAXED_PKCS1 = 5; - /**#@-*/ - - /** - * Modulus (ie. n) - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - private $modulus; - - /** - * Modulus length - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - private $k; - - /** - * Exponent (ie. e or d) - * - * @var \phpseclib\Math\BigInteger - * @access private - */ - private $exponent; - - /** - * Primes for Chinese Remainder Theorem (ie. p and q) - * - * @var array - * @access private - */ - private $primes; - - /** - * Exponents for Chinese Remainder Theorem (ie. dP and dQ) - * - * @var array - * @access private - */ - private $exponents; - - /** - * Coefficients for Chinese Remainder Theorem (ie. qInv) - * - * @var array - * @access private - */ - private $coefficients; - - /** - * Hash name - * - * @var string - * @access private - */ - private $hashName; - - /** - * Length of hash function output - * - * @var int - * @access private - */ - private $hLen; - - /** - * Length of salt - * - * @var int - * @access private - */ - private $sLen; - - /** - * Hash function for the Mask Generation Function - * - * @var \phpseclib\Crypt\Hash - * @access private - */ - private $mgfHash; - - /** - * Length of MGF hash function output - * - * @var int - * @access private - */ - private $mgfHLen; - - /** - * Public Exponent - * - * @var mixed - * @access private - */ - private $publicExponent = false; - - /** - * Public exponent - * - * @var int - * @link http://en.wikipedia.org/wiki/65537_%28number%29 - * @access private - */ - private static $defaultExponent = 65537; - - /** - * Smallest Prime - * - * Per , this number ought not result in primes smaller - * than 256 bits. As a consequence if the key you're trying to create is 1024 bits and you've set smallestPrime - * to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). At least if - * engine is set to self::ENGINE_INTERNAL. If Engine is set to self::ENGINE_OPENSSL then smallest Prime is - * ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key generation when there's - * a chance neither gmp nor OpenSSL are installed) - * - * @var int - * @access private - */ - private static $smallestPrime = 4096; - - /** - * The constructor - * - * If you want to make use of the openssl extension, you'll need to set the mode manually, yourself. The reason - * \phpseclib\Crypt\RSA doesn't do it is because OpenSSL doesn't fail gracefully. openssl_pkey_new(), in particular, requires - * openssl.cnf be present somewhere and, unfortunately, the only real way to find out is too late. - * - * @return \phpseclib\Crypt\RSA - * @access public - */ - public function __construct() - { - parent::__construct(); - - //$this->hash = new Hash('sha256'); - $this->hLen = $this->hash->getLengthInBytes(); - $this->hashName = 'sha256'; - $this->mgfHash = new Hash('sha256'); - $this->mgfHLen = $this->mgfHash->getLengthInBytes(); - } - - /** - * Sets the public exponent - * - * This will be 65537 unless changed. - * - * @access public - * @param int $val - */ - public static function setExponent($val) - { - self::$defaultExponent = $val; - } - - /** - * Sets the smallest prime number in bits - * - * This will be 4096 unless changed. - * - * @access public - * @param int $val - */ - public static function setSmallestPrime($val) - { - self::$smallestPrime = $val; - } - - /** - * Create public / private key pair - * - * Returns an array with the following two elements: - * - 'privatekey': The private key. - * - 'publickey': The public key. - * - * @access public - * @param int $bits - * @param array $p - */ - public static function createKey($bits = 2048) - { - self::initialize_static_variables(); - - if (!isset(self::$engine)) { - self::setPreferredEngine(self::ENGINE_OPENSSL); - } - - // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum - - if (self::$engine == self::ENGINE_OPENSSL && $bits >= 384 && self::$defaultExponent == 65537) { - $config = []; - if (isset(self::$configFile)) { - $config['config'] = self::$configFile; - } - $rsa = openssl_pkey_new(['private_key_bits' => $bits] + $config); - openssl_pkey_export($rsa, $privatekeystr, null, $config); - $privatekey = new RSA(); - $privatekey->load($privatekeystr); - - $publickeyarr = openssl_pkey_get_details($rsa); - $publickey = new RSA(); - $publickey->load($publickeyarr['key']); - $publickey->setPublicKey(); - - // clear the buffer of error strings stemming from a minimalistic openssl.cnf - while (openssl_error_string() !== false) { - } - - return compact('privatekey', 'publickey'); - } - - static $e; - if (!isset($e)) { - $e = new BigInteger(self::$defaultExponent); - } - - $regSize = $bits >> 1; // divide by two to see how many bits P and Q would be - if ($regSize > self::$smallestPrime) { - $num_primes = floor($bits / self::$smallestPrime); - $regSize = self::$smallestPrime; - } else { - $num_primes = 2; - } - - $n = clone self::$one; - $exponents = $coefficients = $primes = []; - $lcm = [ - 'top' => clone self::$one, - 'bottom' => false - ]; - - do { - for ($i = 1; $i <= $num_primes; $i++) { - if ($i != $num_primes) { - $primes[$i] = BigInteger::randomPrime($regSize); - } else { - extract(BigInteger::minMaxBits($bits)); - list($min) = $min->divide($n); - $min = $min->add(self::$one); - list($max) = $max->divide($n); - $primes[$i] = BigInteger::randomRangePrime($min, $max); - } - - // the first coefficient is calculated differently from the rest - // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1]) - if ($i > 2) { - $coefficients[$i] = $n->modInverse($primes[$i]); - } - - $n = $n->multiply($primes[$i]); - - $temp = $primes[$i]->subtract(self::$one); - - // textbook RSA implementations use Euler's totient function instead of the least common multiple. - // see http://en.wikipedia.org/wiki/Euler%27s_totient_function - $lcm['top'] = $lcm['top']->multiply($temp); - $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp); - } - - list($temp) = $lcm['top']->divide($lcm['bottom']); - $gcd = $temp->gcd($e); - $i0 = 1; - } while (!$gcd->equals(self::$one)); - - $coefficients[2] = $primes[2]->modInverse($primes[1]); - - $d = $e->modInverse($temp); - - foreach ($primes as $i => $prime) { - $temp = $prime->subtract(self::$one); - $exponents[$i] = $e->modInverse($temp); - } - - // from : - // RSAPrivateKey ::= SEQUENCE { - // version Version, - // modulus INTEGER, -- n - // publicExponent INTEGER, -- e - // privateExponent INTEGER, -- d - // prime1 INTEGER, -- p - // prime2 INTEGER, -- q - // exponent1 INTEGER, -- d mod (p-1) - // exponent2 INTEGER, -- d mod (q-1) - // coefficient INTEGER, -- (inverse of q) mod p - // otherPrimeInfos OtherPrimeInfos OPTIONAL - // } - $privatekey = new RSA(); - $privatekey->modulus = $n; - $privatekey->k = $bits >> 3; - $privatekey->publicExponent = $e; - $privatekey->exponent = $d; - $privatekey->privateExponent = $e; - $privatekey->primes = $primes; - $privatekey->exponents = $exponents; - $privatekey->coefficients = $coefficients; - - $publickey = new RSA(); - $publickey->modulus = $n; - $publickey->k = $bits >> 3; - $publickey->exponent = $e; - $publickey->publicExponent = $e; - - return compact('privatekey', 'publickey'); - } - - /** - * Loads a public or private key - * - * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed) - * - * @access public - * @param string $key - * @param int $type optional - */ - public function load($key, $type = false) - { - if ($key instanceof RSA) { - $this->privateKeyFormat = $key->privateKeyFormat; - $this->publicKeyFormat = $key->publicKeyFormat; - $this->format = $key->format; - $this->k = $key->k; - $this->hLen = $key->hLen; - $this->sLen = $key->sLen; - $this->mgfHLen = $key->mgfHLen; - $this->password = $key->password; - - if (is_object($key->hash)) { - $this->hash = new Hash($key->hash->getHash()); - } - if (is_object($key->mgfHash)) { - $this->mgfHash = new Hash($key->mgfHash->getHash()); - } - - if (is_object($key->modulus)) { - $this->modulus = clone $key->modulus; - } - if (is_object($key->exponent)) { - $this->exponent = clone $key->exponent; - } - if (is_object($key->publicExponent)) { - $this->publicExponent = clone $key->publicExponent; - } - - $this->primes = []; - $this->exponents = []; - $this->coefficients = []; - - foreach ($this->primes as $prime) { - $this->primes[] = clone $prime; - } - foreach ($this->exponents as $exponent) { - $this->exponents[] = clone $exponent; - } - foreach ($this->coefficients as $coefficient) { - $this->coefficients[] = clone $coefficient; - } - - return true; - } - - $components = parent::load($key, $type); - if ($components === false) { - return false; - } - - $this->modulus = $components['modulus']; - $this->k = $this->modulus->getLengthInBytes(); - $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent']; - if (isset($components['primes'])) { - $this->primes = $components['primes']; - $this->exponents = $components['exponents']; - $this->coefficients = $components['coefficients']; - $this->publicExponent = $components['publicExponent']; - } else { - $this->primes = []; - $this->exponents = []; - $this->coefficients = []; - $this->publicExponent = false; - } - - if ($components['isPublicKey']) { - $this->setPublicKey(); - } - - return true; - } - - /** - * Returns the private key - * - * The private key is only returned if the currently loaded key contains the constituent prime numbers. - * - * @see self::getPublicKey() - * @access public - * @param string $type optional - * @return mixed - */ - public function getPrivateKey($type = 'PKCS8') - { - $type = self::validatePlugin('Keys', $type, 'savePrivateKey'); - if ($type === false) { - return false; - } - - if (empty($this->primes)) { - return false; - } - - return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password); - - /* - $key = $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password); - if ($key !== false || count($this->primes) == 2) { - return $key; - } - - $nSize = $this->getSize() >> 1; - - $primes = [1 => clone self::$one, clone self::$one]; - $i = 1; - foreach ($this->primes as $prime) { - $primes[$i] = $primes[$i]->multiply($prime); - if ($primes[$i]->getLength() >= $nSize) { - $i++; - } - } - - $exponents = []; - $coefficients = [2 => $primes[2]->modInverse($primes[1])]; - - foreach ($primes as $i => $prime) { - $temp = $prime->subtract(self::$one); - $exponents[$i] = $this->modulus->modInverse($temp); - } - - return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $primes, $exponents, $coefficients, $this->password); - */ - } - - /** - * Returns a minimalistic private key - * - * Returns the private key without the prime number constituants. Structurally identical to a public key that - * hasn't been set as the public key - * - * @see self::getPrivateKey() - * @access private - * @param string $type optional - * @return mixed - */ - protected function getPrivatePublicKey($type = 'PKCS8') - { - $type = self::validatePlugin('Keys', $type, 'savePublicKey'); - if ($type === false) { - return false; - } - - if (empty($this->modulus) || empty($this->exponent)) { - return false; - } - - $oldFormat = $this->publicKeyFormat; - $this->publicKeyFormat = $type; - $temp = $type::savePublicKey($this->modulus, $this->exponent); - $this->publicKeyFormat = $oldFormat; - return $temp; - } - - /** - * Returns the key size - * - * More specifically, this returns the size of the modulo in bits. - * - * @access public - * @return int - */ - public function getLength() - { - return !isset($this->modulus) ? 0 : $this->modulus->getLength(); - } - - /** - * Defines the public key - * - * Some private key formats define the public exponent and some don't. Those that don't define it are problematic when - * used in certain contexts. For example, in SSH-2, RSA authentication works by sending the public key along with a - * message signed by the private key to the server. The SSH-2 server looks the public key up in an index of public keys - * and if it's present then proceeds to verify the signature. Problem is, if your private key doesn't include the public - * exponent this won't work unless you manually add the public exponent. phpseclib tries to guess if the key being used - * is the public key but in the event that it guesses incorrectly you might still want to explicitly set the key as being - * public. - * - * Do note that when a new key is loaded the index will be cleared. - * - * Returns true on success, false on failure - * - * @see self::getPublicKey() - * @access public - * @param string $key optional - * @param int $type optional - * @return bool - */ - public function setPublicKey($key = false, $type = false) - { - // if a public key has already been loaded return false - if (!empty($this->publicExponent)) { - return false; - } - - if ($key === false && !empty($this->modulus)) { - $this->publicExponent = $this->exponent; - return true; - } - - $components = parent::setPublicKey($key, $type); - if ($components === false) { - return false; - } - - if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) { - $this->modulus = $components['modulus']; - $this->exponent = $this->publicExponent = $components['publicExponent']; - return true; - } - - $this->publicExponent = $components['publicExponent']; - - return true; - } - - /** - * Defines the private key - * - * If phpseclib guessed a private key was a public key and loaded it as such it might be desirable to force - * phpseclib to treat the key as a private key. This function will do that. - * - * Do note that when a new key is loaded the index will be cleared. - * - * Returns true on success, false on failure - * - * @see self::getPublicKey() - * @access public - * @param string $key optional - * @param int $type optional - * @return bool - */ - public function setPrivateKey($key = false, $type = false) - { - if ($key === false && !empty($this->publicExponent)) { - $this->publicExponent = false; - return true; - } - - $rsa = new RSA(); - if (!$rsa->load($key, $type)) { - return false; - } - $rsa->publicExponent = false; - - // don't overwrite the old key if the new key is invalid - $this->load($rsa); - return true; - } - - /** - * Returns the public key - * - * The public key is only returned under two circumstances - if the private key had the public key embedded within it - * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this - * function won't return it since this library, for the most part, doesn't distinguish between public and private keys. - * - * @see self::getPrivateKey() - * @access public - * @param string $type optional - * @return mixed - */ - public function getPublicKey($type = 'PKCS8') - { - $type = self::validatePlugin('Keys', $type, 'savePublicKey'); - if ($type === false) { - return false; - } - - if (empty($this->modulus) || empty($this->publicExponent)) { - return false; - } - - return $type::savePublicKey($this->modulus, $this->publicExponent); - } - - /** - * __toString() magic method - * - * @access public - * @return string - */ - public function __toString() - { - try { - $key = $this->getPrivateKey($this->privateKeyFormat); - if (is_string($key)) { - return $key; - } - $key = $this->getPrivatePublicKey($this->publicKeyFormat); - return is_string($key) ? $key : ''; - } catch (\Exception $e) { - return ''; - } - } - - /** - * Determines which hashing function should be used - * - * Used with signature production / verification and (if the encryption mode is self::PADDING_OAEP) encryption and - * decryption. - * - * @access public - * @param string $hash - */ - public function setHash($hash) - { - // \phpseclib\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example. - switch (strtolower($hash)) { - case 'md2': - case 'md5': - case 'sha1': - case 'sha256': - case 'sha384': - case 'sha512': - case 'sha224': - case 'sha512/224': - case 'sha512/256': - $this->hash = new Hash($hash); - $this->hashName = $hash; - break; - default: - throw new UnsupportedAlgorithmException( - 'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256' - ); - } - $this->hLen = $this->hash->getLengthInBytes(); - } - - /** - * Determines which hashing function should be used for the mask generation function - * - * The mask generation function is used by self::PADDING_OAEP and self::PADDING_PSS and although it's - * best if Hash and MGFHash are set to the same thing this is not a requirement. - * - * @access public - * @param string $hash - */ - public function setMGFHash($hash) - { - // \phpseclib\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example. - switch ($hash) { - case 'md2': - case 'md5': - case 'sha1': - case 'sha256': - case 'sha384': - case 'sha512': - case 'sha224': - case 'sha512/224': - case 'sha512/256': - $this->mgfHash = new Hash($hash); - break; - default: - $this->mgfHash = new Hash('sha256'); - } - $this->mgfHLen = $this->mgfHash->getLengthInBytes(); - } - - /** - * Determines the salt length - * - * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}: - * - * Typical salt lengths in octets are hLen (the length of the output - * of the hash function Hash) and 0. - * - * @access public - * @param int $format - */ - public function setSaltLength($sLen) - { - $this->sLen = $sLen; - } - - /** - * Integer-to-Octet-String primitive - * - * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}. - * - * @access private - * @param bool|\phpseclib\Math\BigInteger $x - * @param int $xLen - * @return bool|string - */ - private function i2osp($x, $xLen) - { - if ($x === false) { - return false; - } - $x = $x->toBytes(); - if (strlen($x) > $xLen) { - return false; - } - return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); - } - - /** - * Octet-String-to-Integer primitive - * - * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}. - * - * @access private - * @param string $x - * @return \phpseclib\Math\BigInteger - */ - private function os2ip($x) - { - return new BigInteger($x, 256); - } - - /** - * Exponentiate with or without Chinese Remainder Theorem - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.2}. - * - * @access private - * @param \phpseclib\Math\BigInteger $x - * @return \phpseclib\Math\BigInteger - */ - private function exponentiate($x) - { - switch (true) { - case empty($this->primes): - case $this->primes[1]->equals(self::$zero): - case empty($this->coefficients): - case $this->coefficients[2]->equals(self::$zero): - case empty($this->exponents): - case $this->exponents[1]->equals(self::$zero): - return $x->modPow($this->exponent, $this->modulus); - } - - $num_primes = count($this->primes); - - if (defined('CRYPT_RSA_DISABLE_BLINDING')) { - $m_i = [ - 1 => $x->modPow($this->exponents[1], $this->primes[1]), - 2 => $x->modPow($this->exponents[2], $this->primes[2]) - ]; - $h = $m_i[1]->subtract($m_i[2]); - $h = $h->multiply($this->coefficients[2]); - list(, $h) = $h->divide($this->primes[1]); - $m = $m_i[2]->add($h->multiply($this->primes[2])); - - $r = $this->primes[1]; - for ($i = 3; $i <= $num_primes; $i++) { - $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]); - - $r = $r->multiply($this->primes[$i - 1]); - - $h = $m_i->subtract($m); - $h = $h->multiply($this->coefficients[$i]); - list(, $h) = $h->divide($this->primes[$i]); - - $m = $m->add($r->multiply($h)); - } - } else { - $smallest = $this->primes[1]; - for ($i = 2; $i <= $num_primes; $i++) { - if ($smallest->compare($this->primes[$i]) > 0) { - $smallest = $this->primes[$i]; - } - } - - $r = BigInteger::randomRange(self::$one, $smallest->subtract(self::$one)); - - $m_i = [ - 1 => $this->blind($x, $r, 1), - 2 => $this->blind($x, $r, 2) - ]; - $h = $m_i[1]->subtract($m_i[2]); - $h = $h->multiply($this->coefficients[2]); - list(, $h) = $h->divide($this->primes[1]); - $m = $m_i[2]->add($h->multiply($this->primes[2])); - - $r = $this->primes[1]; - for ($i = 3; $i <= $num_primes; $i++) { - $m_i = $this->blind($x, $r, $i); - - $r = $r->multiply($this->primes[$i - 1]); - - $h = $m_i->subtract($m); - $h = $h->multiply($this->coefficients[$i]); - list(, $h) = $h->divide($this->primes[$i]); - - $m = $m->add($r->multiply($h)); - } - } - - return $m; - } - - /** - * Performs RSA Blinding - * - * Protects against timing attacks by employing RSA Blinding. - * Returns $x->modPow($this->exponents[$i], $this->primes[$i]) - * - * @access private - * @param \phpseclib\Math\BigInteger $x - * @param \phpseclib\Math\BigInteger $r - * @param int $i - * @return \phpseclib\Math\BigInteger - */ - private function blind($x, $r, $i) - { - $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i])); - $x = $x->modPow($this->exponents[$i], $this->primes[$i]); - - $r = $r->modInverse($this->primes[$i]); - $x = $x->multiply($r); - list(, $x) = $x->divide($this->primes[$i]); - - return $x; - } - - /** - * RSAEP - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}. - * - * @access private - * @param \phpseclib\Math\BigInteger $m - * @return bool|\phpseclib\Math\BigInteger - */ - private function rsaep($m) - { - if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) { - return false; - } - return $this->exponentiate($m); - } - - /** - * RSADP - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}. - * - * @access private - * @param \phpseclib\Math\BigInteger $c - * @return bool|\phpseclib\Math\BigInteger - */ - private function rsadp($c) - { - if ($c->compare(self::$zero) < 0 || $c->compare($this->modulus) > 0) { - return false; - } - return $this->exponentiate($c); - } - - /** - * RSASP1 - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}. - * - * @access private - * @param \phpseclib\Math\BigInteger $m - * @return bool|\phpseclib\Math\BigInteger - */ - private function rsasp1($m) - { - if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) { - return false; - } - return $this->exponentiate($m); - } - - /** - * RSAVP1 - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}. - * - * @access private - * @param \phpseclib\Math\BigInteger $s - * @return bool|\phpseclib\Math\BigInteger - */ - private function rsavp1($s) - { - if ($s->compare(self::$zero) < 0 || $s->compare($this->modulus) > 0) { - return false; - } - return $this->exponentiate($s); - } - - /** - * MGF1 - * - * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}. - * - * @access private - * @param string $mgfSeed - * @param int $mgfLen - * @return string - */ - private function mgf1($mgfSeed, $maskLen) - { - // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output. - - $t = ''; - $count = ceil($maskLen / $this->mgfHLen); - for ($i = 0; $i < $count; $i++) { - $c = pack('N', $i); - $t.= $this->mgfHash->hash($mgfSeed . $c); - } - - return substr($t, 0, $maskLen); - } - - /** - * RSAES-OAEP-ENCRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and - * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}. - * - * @access private - * @param string $m - * @param string $l - * @throws \OutOfBoundsException if strlen($m) > $this->k - 2 * $this->hLen - 2 - * @return string - */ - private function rsaes_oaep_encrypt($m, $l = '') - { - $mLen = strlen($m); - - // Length checking - - // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - if ($mLen > $this->k - 2 * $this->hLen - 2) { - throw new \OutOfBoundsException('Message too long'); - } - - // EME-OAEP encoding - - $lHash = $this->hash->hash($l); - $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2); - $db = $lHash . $ps . chr(1) . $m; - $seed = Random::string($this->hLen); - $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1); - $maskedDB = $db ^ $dbMask; - $seedMask = $this->mgf1($maskedDB, $this->hLen); - $maskedSeed = $seed ^ $seedMask; - $em = chr(0) . $maskedSeed . $maskedDB; - - // RSA encryption - - $m = $this->os2ip($em); - $c = $this->rsaep($m); - $c = $this->i2osp($c, $this->k); - - // Output the ciphertext C - - return $c; - } - - /** - * RSAES-OAEP-DECRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error - * messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2: - * - * Note. Care must be taken to ensure that an opponent cannot - * distinguish the different error conditions in Step 3.g, whether by - * error message or timing, or, more generally, learn partial - * information about the encoded message EM. Otherwise an opponent may - * be able to obtain useful information about the decryption of the - * ciphertext C, leading to a chosen-ciphertext attack such as the one - * observed by Manger [36]. - * - * As for $l... to quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}: - * - * Both the encryption and the decryption operations of RSAES-OAEP take - * the value of a label L as input. In this version of PKCS #1, L is - * the empty string; other uses of the label are outside the scope of - * this document. - * - * @access private - * @param string $c - * @param string $l - * @return bool|string - */ - private function rsaes_oaep_decrypt($c, $l = '') - { - // Length checking - - // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) { - return false; - } - - // RSA decryption - - $c = $this->os2ip($c); - $m = $this->rsadp($c); - $em = $this->i2osp($m, $this->k); - if ($em === false) { - return false; - } - - // EME-OAEP decoding - - $lHash = $this->hash->hash($l); - $y = ord($em[0]); - $maskedSeed = substr($em, 1, $this->hLen); - $maskedDB = substr($em, $this->hLen + 1); - $seedMask = $this->mgf1($maskedDB, $this->hLen); - $seed = $maskedSeed ^ $seedMask; - $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1); - $db = $maskedDB ^ $dbMask; - $lHash2 = substr($db, 0, $this->hLen); - $m = substr($db, $this->hLen); - if (!Strings::equals($lHash, $lHash2)) { - return false; - } - $m = ltrim($m, chr(0)); - if (ord($m[0]) != 1) { - return false; - } - - // Output the message M - - return substr($m, 1); - } - - /** - * Raw Encryption / Decryption - * - * Doesn't use padding and is not recommended. - * - * @access private - * @param string $m - * @return bool|string - * @throws \OutOfBoundsException if strlen($m) > $this->k - */ - private function raw_encrypt($m) - { - if (strlen($m) > $this->k) { - throw new \OutOfBoundsException('Message too long'); - } - - $temp = $this->os2ip($m); - $temp = $this->rsaep($temp); - return $this->i2osp($temp, $this->k); - } - - /** - * RSAES-PKCS1-V1_5-ENCRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}. - * - * @access private - * @param string $m - * @param bool $pkcs15_compat optional - * @throws \OutOfBoundsException if strlen($m) > $this->k - 11 - * @return bool|string - */ - private function rsaes_pkcs1_v1_5_encrypt($m, $pkcs15_compat = false) - { - $mLen = strlen($m); - - // Length checking - - if ($mLen > $this->k - 11) { - throw new \OutOfBoundsException('Message too long'); - } - - // EME-PKCS1-v1_5 encoding - - $psLen = $this->k - $mLen - 3; - $ps = ''; - while (strlen($ps) != $psLen) { - $temp = Random::string($psLen - strlen($ps)); - $temp = str_replace("\x00", '', $temp); - $ps.= $temp; - } - $type = 2; - // see the comments of _rsaes_pkcs1_v1_5_decrypt() to understand why this is being done - if ($pkcs15_compat && (!isset($this->publicExponent) || $this->exponent !== $this->publicExponent)) { - $type = 1; - // "The padding string PS shall consist of k-3-||D|| octets. ... for block type 01, they shall have value FF" - $ps = str_repeat("\xFF", $psLen); - } - $em = chr(0) . chr($type) . $ps . chr(0) . $m; - - // RSA encryption - $m = $this->os2ip($em); - $c = $this->rsaep($m); - $c = $this->i2osp($c, $this->k); - - // Output the ciphertext C - - return $c; - } - - /** - * RSAES-PKCS1-V1_5-DECRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}. - * - * For compatibility purposes, this function departs slightly from the description given in RFC3447. - * The reason being that RFC2313#section-8.1 (PKCS#1 v1.5) states that ciphertext's encrypted by the - * private key should have the second byte set to either 0 or 1 and that ciphertext's encrypted by the - * public key should have the second byte set to 2. In RFC3447 (PKCS#1 v2.1), the second byte is supposed - * to be 2 regardless of which key is used. For compatibility purposes, we'll just check to make sure the - * second byte is 2 or less. If it is, we'll accept the decrypted string as valid. - * - * As a consequence of this, a private key encrypted ciphertext produced with \phpseclib\Crypt\RSA may not decrypt - * with a strictly PKCS#1 v1.5 compliant RSA implementation. Public key encrypted ciphertext's should but - * not private key encrypted ciphertext's. - * - * @access private - * @param string $c - * @return bool|string - */ - private function rsaes_pkcs1_v1_5_decrypt($c) - { - // Length checking - - if (strlen($c) != $this->k) { // or if k < 11 - return false; - } - - // RSA decryption - - $c = $this->os2ip($c); - $m = $this->rsadp($c); - $em = $this->i2osp($m, $this->k); - if ($em === false) { - return false; - } - - // EME-PKCS1-v1_5 decoding - - if (ord($em[0]) != 0 || ord($em[1]) > 2) { - return false; - } - - $ps = substr($em, 2, strpos($em, chr(0), 2) - 2); - $m = substr($em, strlen($ps) + 3); - - if (strlen($ps) < 8) { - return false; - } - - // Output M - - return $m; - } - - /** - * EMSA-PSS-ENCODE - * - * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}. - * - * @access private - * @param string $m - * @throws \RuntimeException on encoding error - * @param int $emBits - */ - private function emsa_pss_encode($m, $emBits) - { - // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8) - $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; - - $mHash = $this->hash->hash($m); - if ($emLen < $this->hLen + $sLen + 2) { - return false; - } - - $salt = Random::string($sLen); - $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; - $h = $this->hash->hash($m2); - $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2); - $db = $ps . chr(1) . $salt; - $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); - $maskedDB = $db ^ $dbMask; - $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0]; - $em = $maskedDB . $h . chr(0xBC); - - return $em; - } - - /** - * EMSA-PSS-VERIFY - * - * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}. - * - * @access private - * @param string $m - * @param string $em - * @param int $emBits - * @return string - */ - private function emsa_pss_verify($m, $em, $emBits) - { - // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8); - $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; - - $mHash = $this->hash->hash($m); - if ($emLen < $this->hLen + $sLen + 2) { - return false; - } - - if ($em[strlen($em) - 1] != chr(0xBC)) { - return false; - } - - $maskedDB = substr($em, 0, -$this->hLen - 1); - $h = substr($em, -$this->hLen - 1, $this->hLen); - $temp = chr(0xFF << ($emBits & 7)); - if ((~$maskedDB[0] & $temp) != $temp) { - return false; - } - $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); - $db = $maskedDB ^ $dbMask; - $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; - $temp = $emLen - $this->hLen - $sLen - 2; - if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) { - return false; - } - $salt = substr($db, $temp + 1); // should be $sLen long - $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; - $h2 = $this->hash->hash($m2); - return Strings::equals($h, $h2); - } - - /** - * RSASSA-PSS-SIGN - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}. - * - * @access private - * @param string $m - * @return bool|string - */ - private function rsassa_pss_sign($m) - { - // EMSA-PSS encoding - - $em = $this->emsa_pss_encode($m, 8 * $this->k - 1); - - // RSA signature - - $m = $this->os2ip($em); - $s = $this->rsasp1($m); - $s = $this->i2osp($s, $this->k); - - // Output the signature S - - return $s; - } - - /** - * RSASSA-PSS-VERIFY - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}. - * - * @access private - * @param string $m - * @param string $s - * @return bool|string - */ - private function rsassa_pss_verify($m, $s) - { - // Length checking - - if (strlen($s) != $this->k) { - return false; - } - - // RSA verification - - $modBits = 8 * $this->k; - - $s2 = $this->os2ip($s); - $m2 = $this->rsavp1($s2); - $em = $this->i2osp($m2, $modBits >> 3); - if ($em === false) { - return false; - } - - // EMSA-PSS verification - - return $this->emsa_pss_verify($m, $em, $modBits - 1); - } - - /** - * EMSA-PKCS1-V1_5-ENCODE - * - * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}. - * - * @access private - * @param string $m - * @param int $emLen - * @throws \LengthException if the intended encoded message length is too short - * @return string - */ - private function emsa_pkcs1_v1_5_encode($m, $emLen) - { - $h = $this->hash->hash($m); - - // see http://tools.ietf.org/html/rfc3447#page-43 - switch ($this->hashName) { - case 'md2': - $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02\x05\x00\x04\x10"; - break; - case 'md5': - $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10"; - break; - case 'sha1': - $t = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14"; - break; - case 'sha256': - $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"; - break; - case 'sha384': - $t = "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30"; - break; - case 'sha512': - $t = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40"; - break; - // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40 - case 'sha224': - $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c"; - break; - case 'sha512/224': - $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x05\x00\x04\x1c"; - break; - case 'sha512/256': - $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x05\x00\x04\x20"; - } - $t.= $h; - $tLen = strlen($t); - - if ($emLen < $tLen + 11) { - throw new \LengthException('Intended encoded message length too short'); - } - - $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3); - - $em = "\0\1$ps\0$t"; - - return $em; - } - - /** - * RSASSA-PKCS1-V1_5-SIGN - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}. - * - * @access private - * @param string $m - * @throws \LengthException if the RSA modulus is too short - * @return bool|string - */ - private function rsassa_pkcs1_v1_5_sign($m) - { - // EMSA-PKCS1-v1_5 encoding - - // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus - // too short" and stop. - try { - $em = $this->emsa_pkcs1_v1_5_encode($m, $this->k); - } catch (\LengthException $e) { - throw new \LengthException('RSA modulus too short'); - } - - // RSA signature - - $m = $this->os2ip($em); - $s = $this->rsasp1($m); - $s = $this->i2osp($s, $this->k); - - // Output the signature S - - return $s; - } - - /** - * RSASSA-PKCS1-V1_5-VERIFY - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}. - * - * @access private - * @param string $m - * @param string $s - * @throws \LengthException if the RSA modulus is too short - * @return bool - */ - private function rsassa_pkcs1_v1_5_verify($m, $s) - { - // Length checking - - if (strlen($s) != $this->k) { - return false; - } - - // RSA verification - - $s = $this->os2ip($s); - $m2 = $this->rsavp1($s); - $em = $this->i2osp($m2, $this->k); - if ($em === false) { - return false; - } - - // EMSA-PKCS1-v1_5 encoding - - // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus - // too short" and stop. - try { - $em2 = $this->emsa_pkcs1_v1_5_encode($m, $this->k); - } catch (\LengthException $e) { - throw new \LengthException('RSA modulus too short'); - } - - // Compare - return Strings::equals($em, $em2); - } - - /** - * RSASSA-PKCS1-V1_5-VERIFY (relaxed matching) - * - * Per {@link http://tools.ietf.org/html/rfc3447#page-43 RFC3447#page-43} PKCS1 v1.5 - * specified the use BER encoding rather than DER encoding that PKCS1 v2.0 specified. - * This means that under rare conditions you can have a perfectly valid v1.5 signature - * that fails to validate with _rsassa_pkcs1_v1_5_verify(). PKCS1 v2.1 also recommends - * that if you're going to validate these types of signatures you "should indicate - * whether the underlying BER encoding is a DER encoding and hence whether the signature - * is valid with respect to the specification given in [PKCS1 v2.0+]". so if you do - * $rsa->getLastPadding() and get RSA::PADDING_RELAXED_PKCS1 back instead of - * RSA::PADDING_PKCS1... that means BER encoding was used. - * - * @access private - * @param string $m - * @param string $s - * @return bool - */ - private function rsassa_pkcs1_v1_5_relaxed_verify($m, $s) - { - // Length checking - - if (strlen($s) != $this->k) { - return false; - } - - // RSA verification - - $s = $this->os2ip($s); - $m2 = $this->rsavp1($s); - if ($m2 === false) { - return false; - } - $em = $this->i2osp($m2, $this->k); - if ($em === false) { - return false; - } - - if (Strings::shift($em, 2) != "\0\1") { - return false; - } - - $em = ltrim($em, "\xFF"); - if (Strings::shift($em) != "\0") { - return false; - } - - $decoded = ASN1::decodeBER($em); - if (!is_array($decoded) || empty($decoded[0]) || strlen($em) > $decoded[0]['length']) { - return false; - } - - static $oids; - if (!isset($oids)) { - $oids = [ - '1.2.840.113549.2.2' => 'md2', - '1.2.840.113549.2.4' => 'md4', // from PKCS1 v1.5 - '1.2.840.113549.2.5' => 'md5', - '1.3.14.3.2.26' => 'id-sha1', - '2.16.840.1.101.3.4.2.1' => 'id-sha256', - '2.16.840.1.101.3.4.2.2' => 'id-sha384', - '2.16.840.1.101.3.4.2.3' => 'id-sha512', - // from PKCS1 v2.2 - '2.16.840.1.101.3.4.2.4' => 'id-sha224', - '2.16.840.1.101.3.4.2.5' => 'id-sha512/224', - '2.16.840.1.101.3.4.2.6' => 'id-sha512/256', - ]; - ASN1::loadOIDs($oids); - } - - $decoded = ASN1::asn1map($decoded[0], DigestInfo::MAP); - if (!isset($decoded) || $decoded === false) { - return false; - } - - if (!in_array($decoded['digestAlgorithm']['algorithm'], $oids)) { - return false; - } - - $hash = $decoded['digestAlgorithm']['algorithm']; - $hash = substr($hash, 0, 3) == 'id-' ? - substr($hash, 3) : - $hash; - $hash = new Hash($hash); - $em = $hash->hash($m); - $em2 = $decoded['digest']; - - return Strings::equals($em, $em2); - } - - /** - * Encryption - * - * Both self::PADDING_OAEP and self::PADDING_PKCS1 both place limits on how long $plaintext can be. - * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will - * be concatenated together. - * - * @see self::decrypt() - * @access public - * @param string $plaintext - * @param int $padding optional - * @return bool|string - * @throws \LengthException if the RSA modulus is too short - */ - public function encrypt($plaintext, $padding = self::PADDING_OAEP) - { - switch ($padding) { - case self::PADDING_NONE: - return $this->raw_encrypt($plaintext); - case self::PADDING_PKCS15_COMPAT: - case self::PADDING_PKCS1: - return $this->rsaes_pkcs1_v1_5_encrypt($plaintext, $padding == self::PADDING_PKCS15_COMPAT); - //case self::PADDING_OAEP: - default: - return $this->rsaes_oaep_encrypt($plaintext); - } - } - - /** - * Decryption - * - * @see self::encrypt() - * @access public - * @param string $plaintext - * @param int $padding optional - * @return bool|string - */ - public function decrypt($ciphertext, $padding = self::PADDING_OAEP) - { - switch ($padding) { - case self::PADDING_NONE: - return $this->raw_encrypt($ciphertext); - case self::PADDING_PKCS1: - return $this->rsaes_pkcs1_v1_5_decrypt($ciphertext); - //case self::PADDING_OAEP: - default: - return $this->rsaes_oaep_decrypt($ciphertext); - } - } - - /** - * Create a signature - * - * @see self::verify() - * @access public - * @param string $message - * @param int $padding optional - * @return string - */ - public function sign($message, $padding = self::PADDING_PSS) - { - if (empty($this->modulus) || empty($this->exponent)) { - return false; - } - - switch ($padding) { - case self::PADDING_PKCS1: - case self::PADDING_RELAXED_PKCS1: - return $this->rsassa_pkcs1_v1_5_sign($message); - //case self::PADDING_PSS: - default: - return $this->rsassa_pss_sign($message); - } - } - - /** - * Verifies a signature - * - * @see self::sign() - * @access public - * @param string $message - * @param string $signature - * @param int $padding optional - * @return bool - */ - public function verify($message, $signature, $padding = self::PADDING_PSS) - { - if (empty($this->modulus) || empty($this->exponent)) { - return false; - } - - switch ($padding) { - case self::PADDING_RELAXED_PKCS1: - return $this->rsassa_pkcs1_v1_5_relaxed_verify($message, $signature); - case self::PADDING_PKCS1: - return $this->rsassa_pkcs1_v1_5_verify($message, $signature); - //case self::PADDING_PSS: - default: - return $this->rsassa_pss_verify($message, $signature); - } - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA/Keys/MSBLOB.php b/lib/phpaes/phpseclib/Crypt/RSA/Keys/MSBLOB.php deleted file mode 100644 index 8ac478e05d..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA/Keys/MSBLOB.php +++ /dev/null @@ -1,213 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA\Keys; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; - -/** - * Microsoft BLOB Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class MSBLOB -{ - /**#@+ - * @access private - */ - /** - * Public/Private Key Pair - */ - const PRIVATEKEYBLOB = 0x7; - /** - * Public Key - */ - const PUBLICKEYBLOB = 0x6; - /** - * Public Key - */ - const PUBLICKEYBLOBEX = 0xA; - /** - * RSA public key exchange algorithm - */ - const CALG_RSA_KEYX = 0x0000A400; - /** - * RSA public key exchange algorithm - */ - const CALG_RSA_SIGN = 0x00002400; - /** - * Public Key - */ - const RSA1 = 0x31415352; - /** - * Private Key - */ - const RSA2 = 0x32415352; - /**#@-*/ - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $key = Base64::decode($key); - - if (!is_string($key) || strlen($key) < 20) { - return false; - } - - // PUBLICKEYSTRUC publickeystruc - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx - extract(unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8))); - switch (ord($type)) { - case self::PUBLICKEYBLOB: - case self::PUBLICKEYBLOBEX: - $publickey = true; - break; - case self::PRIVATEKEYBLOB: - $publickey = false; - break; - default: - return false; - } - - $components = ['isPublicKey' => $publickey]; - - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx - switch ($algo) { - case self::CALG_RSA_KEYX: - case self::CALG_RSA_SIGN: - break; - default: - return false; - } - - // RSAPUBKEY rsapubkey - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx - // could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit - extract(unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12))); - switch ($magic) { - case self::RSA2: - $components['isPublicKey'] = false; - case self::RSA1: - break; - default: - return false; - } - - $baseLength = $bitlen / 16; - if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) { - return false; - } - - $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256); - // BYTE modulus[rsapubkey.bitlen/8] - $components['modulus'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256); - - if ($publickey) { - return $components; - } - - $components['isPublicKey'] = false; - - // BYTE prime1[rsapubkey.bitlen/16] - $components['primes'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)]; - // BYTE prime2[rsapubkey.bitlen/16] - $components['primes'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256); - // BYTE exponent1[rsapubkey.bitlen/16] - $components['exponents'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)]; - // BYTE exponent2[rsapubkey.bitlen/16] - $components['exponents'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256); - // BYTE coefficient[rsapubkey.bitlen/16] - $components['coefficients'] = [2 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)]; - if (isset($components['privateExponent'])) { - $components['publicExponent'] = $components['privateExponent']; - } - // BYTE privateExponent[rsapubkey.bitlen/8] - $components['privateExponent'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256); - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - if (count($primes) != 2) { - throw new \InvalidArgumentException('MSBLOB does not support multi-prime RSA keys'); - } - - $n = strrev($n->toBytes()); - $e = str_pad(strrev($e->toBytes()), 4, "\0"); - $key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); - $key.= pack('VVa*', self::RSA2, 8 * strlen($n), $e); - $key.= $n; - $key.= strrev($primes[1]->toBytes()); - $key.= strrev($primes[2]->toBytes()); - $key.= strrev($exponents[1]->toBytes()); - $key.= strrev($exponents[2]->toBytes()); - $key.= strrev($coefficients[1]->toBytes()); - $key.= strrev($d->toBytes()); - - return Base64::encode($key); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - $n = strrev($n->toBytes()); - $e = str_pad(strrev($e->toBytes()), 4, "\0"); - $key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); - $key.= pack('VVa*', self::RSA1, 8 * strlen($n), $e); - $key.= $n; - - return Base64::encode($key); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA/Keys/OpenSSH.php b/lib/phpaes/phpseclib/Crypt/RSA/Keys/OpenSSH.php deleted file mode 100644 index 40f2033085..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA/Keys/OpenSSH.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA\Keys; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; -use phpseclib\Crypt\Common\Keys\OpenSSH as Progenitor; - -/** - * OpenSSH Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class OpenSSH extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, 'ssh-rsa'); - if ($key === false) { - return false; - } - - $result = Strings::unpackSSH2('ii', $key); - if ($result === false) { - return false; - } - list($publicExponent, $modulus) = $result; - - return [ - 'isPublicKey' => true, - 'modulus' => $modulus, - 'publicExponent' => $publicExponent, - 'comment' => parent::getComment($key) - ]; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - $RSAPublicKey = Strings::packSSH2('sii', 'ssh-rsa', $e, $n); - - if (self::$binary) { - return $RSAPublicKey; - } - - $RSAPublicKey = 'ssh-rsa ' . Base64::encode($RSAPublicKey) . ' ' . self::$comment; - - return $RSAPublicKey; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS1.php b/lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS1.php deleted file mode 100644 index 125927ce1d..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS1.php +++ /dev/null @@ -1,151 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA\Keys; - -use phpseclib\Math\BigInteger; -use phpseclib\Crypt\Common\Keys\PKCS1 as Progenitor; -use phpseclib\File\ASN1; -use phpseclib\File\ASN1\Maps; - -/** - * PKCS#1 Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PKCS1 extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $components = ['isPublicKey' => strpos($key, 'PUBLIC') !== false]; - - $key = parent::load($key, $password); - if ($key === false) { - return false; - } - - $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { - return false; - } - - $key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP); - if (is_array($key)) { - $components+= [ - 'modulus' => $key['modulus'], - 'publicExponent' => $key['publicExponent'], - 'privateExponent' => $key['privateExponent'], - 'primes' => [1 => $key['prime1'], $key['prime2']], - 'exponents' => [1 => $key['exponent1'], $key['exponent2']], - 'coefficients' => [2 => $key['coefficient']] - ]; - if ($key['version'] == 'multi') { - foreach ($key['otherPrimeInfos'] as $primeInfo) { - $components['primes'][] = $primeInfo['prime']; - $components['exponents'][] = $primeInfo['exponent']; - $components['coefficients'][] = $primeInfo['coefficient']; - } - } - return $components; - } - - $key = ASN1::asn1map($decoded[0], Maps\RSAPublicKey::MAP); - - return is_array($key) ? $components + $key : false; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - $num_primes = count($primes); - $key = [ - 'version' => $num_primes == 2 ? 'two-prime' : 'multi', - 'modulus' => $n, - 'publicExponent' => $e, - 'privateExponent' => $d, - 'prime1' => $primes[1], - 'prime2' => $primes[2], - 'exponent1' => $exponents[1], - 'exponent2' => $exponents[2], - 'coefficient' => $coefficients[2] - ]; - for ($i = 3; $i <= $num_primes; $i++) { - $key['otherPrimeInfos'][] = [ - 'prime' => $primes[$i], - 'exponent' => $exponents[$i], - 'coefficient' => $coefficients[$i] - ]; - } - - $key = ASN1::encodeDER($key, Maps\RSAPrivateKey::MAP); - - return self::wrapPrivateKey($key, 'RSA', $password); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - $key = [ - 'modulus' => $n, - 'publicExponent' => $e - ]; - - $key = ASN1::encodeDER($key, Maps\RSAPublicKey::MAP); - - return self::wrapPublicKey($key, 'RSA'); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS8.php b/lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS8.php deleted file mode 100644 index 382fb2b71b..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA/Keys/PKCS8.php +++ /dev/null @@ -1,133 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA\Keys; - -use phpseclib\Math\BigInteger; -use phpseclib\Crypt\Common\Keys\PKCS8 as Progenitor; -use phpseclib\File\ASN1; - -/** - * PKCS#1 Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PKCS8 extends Progenitor -{ - /** - * OID Name - * - * @var string - * @access private - */ - const OID_NAME = 'rsaEncryption'; - - /** - * OID Value - * - * @var string - * @access private - */ - const OID_VALUE = '1.2.840.113549.1.1.1'; - - /** - * Child OIDs loaded - * - * @var bool - * @access private - */ - protected static $childOIDsLoaded = false; - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $components = ['isPublicKey' => strpos($key, 'PUBLIC') !== false]; - - $key = parent::load($key, $password); - if ($key === false) { - return false; - } - - $type = isset($key['privateKey']) ? 'private' : 'public'; - - $result = $components + PKCS1::load($key[$type . 'Key']); - - if (isset($key['meta'])) { - $result['meta'] = $key['meta']; - } - - return $result; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients); - $key = ASN1::extractBER($key); - return self::wrapPrivateKey($key, [], null, $password); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - $key = PKCS1::savePublicKey($n, $e); - $key = ASN1::extractBER($key); - return self::wrapPublicKey($key, null); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA/Keys/PuTTY.php b/lib/phpaes/phpseclib/Crypt/RSA/Keys/PuTTY.php deleted file mode 100644 index 4353fd0212..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA/Keys/PuTTY.php +++ /dev/null @@ -1,129 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA\Keys; - -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; -use phpseclib\Crypt\Common\Keys\PuTTY as Progenitor; - -/** - * PuTTY Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PuTTY extends Progenitor -{ - /** - * Public Handler - * - * @var string - * @access private - */ - const PUBLIC_HANDLER = 'phpseclib\Crypt\RSA\Keys\OpenSSH'; - - /** - * Algorithm Identifier - * - * @var string - * @access private - */ - const TYPE = 'ssh-rsa'; - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - $components = parent::load($key, $password); - if ($components === false || !isset($components['private'])) { - return $components; - } - extract($components); - unset($components['public'], $components['private']); - - $isPublicKey = false; - - $result = Strings::unpackSSH2('ii', $public); - if ($result === false) { - return false; - } - list($publicExponent, $modulus) = $result; - - $result = Strings::unpackSSH2('iiii', $private); - if ($result === false) { - return false; - } - $primes = $coefficients = []; - list($privateExponent, $primes[1], $primes[2], $coefficients[2]) = $result; - - $temp = $primes[1]->subtract($one); - $exponents = [1 => $publicExponent->modInverse($temp)]; - $temp = $primes[2]->subtract($one); - $exponents[] = $publicExponent->modInverse($temp); - - return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey'); - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - if (count($primes) != 2) { - throw new \InvalidArgumentException('PuTTY does not support multi-prime RSA keys'); - } - - $public = Strings::packSSH2('ii', $e, $n); - $private = Strings::packSSH2('iiii', $d, $primes[1], $primes[2], $coefficients[2]); - - return self::wrapPrivateKey($public, $private, $password); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - return self::wrapPublicKey(Strings::packSSH2($e, $n)); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA/Keys/Raw.php b/lib/phpaes/phpseclib/Crypt/RSA/Keys/Raw.php deleted file mode 100644 index e2bd636c83..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA/Keys/Raw.php +++ /dev/null @@ -1,104 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA\Keys; - -use phpseclib\Math\BigInteger; - -/** - * Raw RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class Raw -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_array($key)) { - return false; - } - if (isset($key['isPublicKey']) && isset($key['modulus'])) { - if (isset($key['privateExponent']) || isset($key['publicExponent'])) { - if (!isset($key['primes'])) { - return $key; - } - if (isset($key['exponents']) && isset($key['coefficients']) && isset($key['publicExponent']) && isset($key['privateExponent'])) { - return $key; - } - } - } - $components = ['isPublicKey' => true]; - switch (true) { - case isset($key['e']): - $components['publicExponent'] = $key['e']; - break; - case isset($key['exponent']): - $components['publicExponent'] = $key['exponent']; - break; - case isset($key['publicExponent']): - $components['publicExponent'] = $key['publicExponent']; - break; - case isset($key[0]): - $components['publicExponent'] = $key[0]; - } - switch (true) { - case isset($key['n']): - $components['modulus'] = $key['n']; - break; - case isset($key['modulo']): - $components['modulus'] = $key['modulo']; - break; - case isset($key['modulus']): - $components['modulus'] = $key['modulus']; - break; - case isset($key[1]): - $components['modulus'] = $key[1]; - } - return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - return ['e' => clone $e, 'n' => clone $n]; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/RSA/Keys/XML.php b/lib/phpaes/phpseclib/Crypt/RSA/Keys/XML.php deleted file mode 100644 index e24861f941..0000000000 --- a/lib/phpaes/phpseclib/Crypt/RSA/Keys/XML.php +++ /dev/null @@ -1,148 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA\Keys; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Math\BigInteger; - -/** - * XML Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class XML -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $components = [ - 'isPublicKey' => false, - 'primes' => [], - 'exponents' => [], - 'coefficients' => [] - ]; - - $use_errors = libxml_use_internal_errors(true); - - $dom = new \DOMDocument(); - if (!$dom->loadXML('' . $key . '')) { - return false; - } - $xpath = new \DOMXPath($dom); - $keys = ['modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd']; - foreach ($keys as $key) { - // $dom->getElementsByTagName($key) is case-sensitive - $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']"); - if (!$temp->length) { - continue; - } - $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256); - switch ($key) { - case 'modulus': - $components['modulus'] = $value; - break; - case 'exponent': - $components['publicExponent'] = $value; - break; - case 'p': - $components['primes'][1] = $value; - break; - case 'q': - $components['primes'][2] = $value; - break; - case 'dp': - $components['exponents'][1] = $value; - break; - case 'dq': - $components['exponents'][2] = $value; - break; - case 'inverseq': - $components['coefficients'][2] = $value; - break; - case 'd': - $components['privateExponent'] = $value; - } - } - - libxml_use_internal_errors($use_errors); - - return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - if (count($primes) != 2) { - throw new \InvalidArgumentException('XML does not support multi-prime RSA keys'); - } - return "\r\n" . - ' ' . Base64::encode($n->toBytes()) . "\r\n" . - ' ' . Base64::encode($e->toBytes()) . "\r\n" . - '

' . Base64::encode($primes[1]->toBytes()) . "

\r\n" . - ' ' . Base64::encode($primes[2]->toBytes()) . "\r\n" . - ' ' . Base64::encode($exponents[1]->toBytes()) . "\r\n" . - ' ' . Base64::encode($exponents[2]->toBytes()) . "\r\n" . - ' ' . Base64::encode($coefficients[2]->toBytes()) . "\r\n" . - ' ' . Base64::encode($d->toBytes()) . "\r\n" . - '
'; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - return "\r\n" . - ' ' . Base64::encode($n->toBytes()) . "\r\n" . - ' ' . Base64::encode($e->toBytes()) . "\r\n" . - ''; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Random.php b/lib/phpaes/phpseclib/Crypt/Random.php deleted file mode 100644 index 071f5ed8dd..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Random.php +++ /dev/null @@ -1,222 +0,0 @@ - - * - * - * - * @category Crypt - * @package Random - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use phpseclib\Crypt\Common\BlockCipher; - -/** - * Pure-PHP Random Number Generator - * - * @package Random - * @author Jim Wigginton - * @access public - */ -abstract class Random -{ - /** - * Generate a random string. - * - * Although microoptimizations are generally discouraged as they impair readability this function is ripe with - * microoptimizations because this function has the potential of being called a huge number of times. - * eg. for RSA key generation. - * - * @param int $length - * @throws \RuntimeException if a symmetric cipher is needed but not loaded - * @return string - */ - public static function string($length) - { - try { - return \random_bytes($length); - } catch (\Exception $e) { - // random_compat will throw an Exception, which in PHP 5 does not implement Throwable - } catch (\Throwable $e) { - // If a sufficient source of randomness is unavailable, random_bytes() will throw an - // object that implements the Throwable interface (Exception, TypeError, Error). - // We don't actually need to do anything here. The string() method should just continue - // as normal. Note, however, that if we don't have a sufficient source of randomness for - // random_bytes(), most of the other calls here will fail too, so we'll end up using - // the PHP implementation. - } - // at this point we have no choice but to use a pure-PHP CSPRNG - - // cascade entropy across multiple PHP instances by fixing the session and collecting all - // environmental variables, including the previous session data and the current session - // data. - // - // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively) - // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but - // PHP isn't low level to be able to use those as sources and on a web server there's not likely - // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use - // however, a ton of people visiting the website. obviously you don't want to base your seeding - // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled - // by the user and (2) this isn't just looking at the data sent by the current user - it's based - // on the data sent by all users. one user requests the page and a hash of their info is saved. - // another user visits the page and the serialization of their data is utilized along with the - // server envirnment stuff and a hash of the previous http request data (which itself utilizes - // a hash of the session data before that). certainly an attacker should be assumed to have - // full control over his own http requests. he, however, is not going to have control over - // everyone's http requests. - static $crypto = false, $v; - if ($crypto === false) { - // save old session data - $old_session_id = session_id(); - $old_use_cookies = ini_get('session.use_cookies'); - $old_session_cache_limiter = session_cache_limiter(); - $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false; - if ($old_session_id != '') { - session_write_close(); - } - - session_id(1); - ini_set('session.use_cookies', 0); - session_cache_limiter(''); - session_start(); - - $v = (isset($_SERVER) ? self::safe_serialize($_SERVER) : '') . - (isset($_POST) ? self::safe_serialize($_POST) : '') . - (isset($_GET) ? self::safe_serialize($_GET) : '') . - (isset($_COOKIE) ? self::safe_serialize($_COOKIE) : '') . - self::safe_serialize($GLOBALS) . - self::safe_serialize($_SESSION) . - self::safe_serialize($_OLD_SESSION); - $v = $seed = $_SESSION['seed'] = sha1($v, true); - if (!isset($_SESSION['count'])) { - $_SESSION['count'] = 0; - } - $_SESSION['count']++; - - session_write_close(); - - // restore old session data - if ($old_session_id != '') { - session_id($old_session_id); - session_start(); - ini_set('session.use_cookies', $old_use_cookies); - session_cache_limiter($old_session_cache_limiter); - } else { - if ($_OLD_SESSION !== false) { - $_SESSION = $_OLD_SESSION; - unset($_OLD_SESSION); - } else { - unset($_SESSION); - } - } - - // in SSH2 a shared secret and an exchange hash are generated through the key exchange process. - // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C. - // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the - // original hash and the current hash. we'll be emulating that. for more info see the following URL: - // - // http://tools.ietf.org/html/rfc4253#section-7.2 - // - // see the is_string($crypto) part for an example of how to expand the keys - $key = sha1($seed . 'A', true); - $iv = sha1($seed . 'C', true); - - // ciphers are used as per the nist.gov link below. also, see this link: - // - // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives - switch (true) { - case class_exists('\phpseclib\Crypt\AES'): - $crypto = new AES(BlockCipher::MODE_CTR); - break; - case class_exists('\phpseclib\Crypt\Twofish'): - $crypto = new Twofish(BlockCipher::MODE_CTR); - break; - case class_exists('\phpseclib\Crypt\Blowfish'): - $crypto = new Blowfish(BlockCipher::MODE_CTR); - break; - case class_exists('\phpseclib\Crypt\TripleDES'): - $crypto = new TripleDES(BlockCipher::MODE_CTR); - break; - case class_exists('\phpseclib\Crypt\DES'): - $crypto = new DES(BlockCipher::MODE_CTR); - break; - case class_exists('\phpseclib\Crypt\RC4'): - $crypto = new RC4(); - break; - default: - throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded'); - } - - $crypto->setKey(substr($key, 0, $crypto->getKeyLength() >> 3)); - $crypto->setIV(substr($iv, 0, $crypto->getBlockLength() >> 3)); - $crypto->enableContinuousBuffer(); - } - - //return $crypto->encrypt(str_repeat("\0", $length)); - - // the following is based off of ANSI X9.31: - // - // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf - // - // OpenSSL uses that same standard for it's random numbers: - // - // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c - // (do a search for "ANS X9.31 A.2.4") - $result = ''; - while (strlen($result) < $length) { - $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21 - $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20 - $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20 - $result.= $r; - } - - return substr($result, 0, $length); - } - - /** - * Safely serialize variables - * - * If a class has a private __sleep() it'll emit a warning - * - * @param mixed $arr - * @access public - */ - private static function safe_serialize(&$arr) - { - if (is_object($arr)) { - return ''; - } - if (!is_array($arr)) { - return serialize($arr); - } - // prevent circular array recursion - if (isset($arr['__phpseclib_marker'])) { - return ''; - } - $safearr = []; - $arr['__phpseclib_marker'] = true; - foreach (array_keys($arr) as $key) { - // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage - if ($key !== '__phpseclib_marker') { - $safearr[$key] = self::safe_serialize($arr[$key]); - } - } - unset($arr['__phpseclib_marker']); - return serialize($safearr); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Rijndael.php b/lib/phpaes/phpseclib/Crypt/Rijndael.php deleted file mode 100644 index afb5d58edb..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Rijndael.php +++ /dev/null @@ -1,938 +0,0 @@ - - * setKey('abcdefghijklmnop'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $rijndael->decrypt($rijndael->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package Rijndael - * @author Jim Wigginton - * @copyright 2008 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -//namespace phpseclib\Crypt; -// -//use phpseclib\Crypt\Common\BlockCipher; -include PHPAES_ROOT . '/phpseclib/Crypt/Common/BlockCipher.php'; - -/** - * Pure-PHP implementation of Rijndael. - * - * @package Rijndael - * @author Jim Wigginton - * @access public - */ -class Rijndael extends BlockCipher -{ - /** - * The mcrypt specific name of the cipher - * - * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not. - * \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable - * or not for the current $block_size/$key_length. - * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @see \phpseclib\Crypt\Common\SymmetricKey::engine - * @see self::isValidEngine() - * @var string - * @access private - */ - protected $cipher_name_mcrypt = 'rijndael-128'; - - /** - * The Key Schedule - * - * @see self::setup() - * @var array - * @access private - */ - private $w; - - /** - * The Inverse Key Schedule - * - * @see self::setup() - * @var array - * @access private - */ - private $dw; - - /** - * The Block Length divided by 32 - * - * @see self::setBlockLength() - * @var int - * @access private - * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size - * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could - * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once. - */ - private $Nb = 4; - - /** - * The Key Length (in bytes) - * - * @see self::setKeyLength() - * @var int - * @access private - * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk - * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could - * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once. - */ - protected $key_length = 16; - - /** - * The Key Length divided by 32 - * - * @see self::setKeyLength() - * @var int - * @access private - * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4 - */ - private $Nk = 4; - - /** - * The Number of Rounds - * - * @var int - * @access private - * @internal The max value is 14, the min value is 10. - */ - private $Nr; - - /** - * Shift offsets - * - * @var array - * @access private - */ - private $c; - - /** - * Holds the last used key- and block_size information - * - * @var array - * @access private - */ - private $kl; - - /** - * Default Constructor. - * - * @param int $mode - * @access public - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - if ($mode == self::MODE_STREAM) { - throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode'); - } - - parent::__construct($mode); - } - - /** - * Sets the key length. - * - * Valid key lengths are 128, 160, 192, 224, and 256. - * - * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined - * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to - * 192/256 bits as, for example, mcrypt will do. - * - * That said, if you want be compatible with other Rijndael and AES implementations, - * you should not setKeyLength(160) or setKeyLength(224). - * - * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use - * the mcrypt php extension, even if available. - * This results then in slower encryption. - * - * @access public - * @throws \LengthException if the key length is invalid - * @param int $length - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 160: - case 192: - case 224: - case 256: - $this->key_length = $length >> 3; - break; - default: - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported'); - } - - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Rijndael supports five different key lengths - * - * @see setKeyLength() - * @access public - * @param string $key - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key) - { - switch (strlen($key)) { - case 16: - case 20: - case 24: - case 28: - case 32: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 20, 24, 28 or 32 are supported'); - } - - parent::setKey($key); - } - - /** - * Sets the block length - * - * Valid block lengths are 128, 160, 192, 224, and 256. - * - * @access public - * @param int $length - */ - public function setBlockLength($length) - { - switch ($length) { - case 128: - case 160: - case 192: - case 224: - case 256: - break; - default: - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported'); - } - - $this->Nb = $length >> 5; - $this->block_size = $length >> 3; - $this->changed = true; - $this->setEngine(); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @access public - * @return bool - */ - public function isValidEngine($engine) - { - switch ($engine) { - case self::ENGINE_OPENSSL: - if ($this->block_size != 16) { - return false; - } - $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb'; - $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->openssl_translate_mode(); - break; - case self::ENGINE_MCRYPT: - $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3); - if ($this->key_length % 8) { // is it a 160/224-bit key? - // mcrypt is not usable for them, only for 128/192/256-bit keys - return false; - } - } - - return parent::isValidEngine($engine); - } - - /** - * Encrypts a block - * - * @access private - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - static $tables; - if (empty($tables)) { - $tables = &$this->getTables(); - } - $t0 = $tables[0]; - $t1 = $tables[1]; - $t2 = $tables[2]; - $t3 = $tables[3]; - $sbox = $tables[4]; - - $state = array(); - $words = unpack('N*', $in); - - $c = $this->c; - $w = $this->w; - $Nb = $this->Nb; - $Nr = $this->Nr; - - // addRoundKey - $wc = $Nb - 1; - foreach ($words as $word) { - $state[] = $word ^ $w[++$wc]; - } - - // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components - - // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding - // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf. - // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization. - // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1], - // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well. - - // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf - $temp = array(); - for ($round = 1; $round < $Nr; ++$round) { - $i = 0; // $c[0] == 0 - $j = $c[1]; - $k = $c[2]; - $l = $c[3]; - - while ($i < $Nb) { - $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^ - $t1[$state[$j] >> 16 & 0x000000FF] ^ - $t2[$state[$k] >> 8 & 0x000000FF] ^ - $t3[$state[$l] & 0x000000FF] ^ - $w[++$wc]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - $state = $temp; - } - - // subWord - for ($i = 0; $i < $Nb; ++$i) { - $state[$i] = $sbox[$state[$i] & 0x000000FF] | - ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) | - ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) | - ($sbox[$state[$i] >> 24 & 0x000000FF] << 24); - } - - // shiftRows + addRoundKey - $i = 0; // $c[0] == 0 - $j = $c[1]; - $k = $c[2]; - $l = $c[3]; - while ($i < $Nb) { - $temp[$i] = ($state[$i] & 0xFF000000) ^ - ($state[$j] & 0x00FF0000) ^ - ($state[$k] & 0x0000FF00) ^ - ($state[$l] & 0x000000FF) ^ - $w[$i]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - - switch ($Nb) { - case 8: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]); - case 7: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]); - case 6: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]); - case 5: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]); - default: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]); - } - } - - /** - * Decrypts a block - * - * @access private - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - static $invtables; - if (empty($invtables)) { - $invtables = &$this->getInvTables(); - } - $dt0 = $invtables[0]; - $dt1 = $invtables[1]; - $dt2 = $invtables[2]; - $dt3 = $invtables[3]; - $isbox = $invtables[4]; - - $state = array(); - $words = unpack('N*', $in); - - $c = $this->c; - $dw = $this->dw; - $Nb = $this->Nb; - $Nr = $this->Nr; - - // addRoundKey - $wc = $Nb - 1; - foreach ($words as $word) { - $state[] = $word ^ $dw[++$wc]; - } - - $temp = array(); - for ($round = $Nr - 1; $round > 0; --$round) { - $i = 0; // $c[0] == 0 - $j = $Nb - $c[1]; - $k = $Nb - $c[2]; - $l = $Nb - $c[3]; - - while ($i < $Nb) { - $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^ - $dt1[$state[$j] >> 16 & 0x000000FF] ^ - $dt2[$state[$k] >> 8 & 0x000000FF] ^ - $dt3[$state[$l] & 0x000000FF] ^ - $dw[++$wc]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - $state = $temp; - } - - // invShiftRows + invSubWord + addRoundKey - $i = 0; // $c[0] == 0 - $j = $Nb - $c[1]; - $k = $Nb - $c[2]; - $l = $Nb - $c[3]; - - while ($i < $Nb) { - $word = ($state[$i] & 0xFF000000) | - ($state[$j] & 0x00FF0000) | - ($state[$k] & 0x0000FF00) | - ($state[$l] & 0x000000FF); - - $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] | - ($isbox[$word >> 8 & 0x000000FF] << 8) | - ($isbox[$word >> 16 & 0x000000FF] << 16) | - ($isbox[$word >> 24 & 0x000000FF] << 24)); - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - - switch ($Nb) { - case 8: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]); - case 7: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]); - case 6: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]); - case 5: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]); - default: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]); - } - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setupKey() - * @access private - */ - protected function setupKey() - { - // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field. - // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse - static $rcon = array(0, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, - 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000, - 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000, - 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000, - 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 - ); - - if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) { - // already expanded - return; - } - $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size); - - $this->Nk = $this->key_length >> 2; - // see Rijndael-ammended.pdf#page=44 - $this->Nr = max($this->Nk, $this->Nb) + 6; - - // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44, - // "Table 8: Shift offsets in Shiftrow for the alternative block lengths" - // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14, - // "Table 2: Shift offsets for different block lengths" - switch ($this->Nb) { - case 4: - case 5: - case 6: - $this->c = array(0, 1, 2, 3); - break; - case 7: - $this->c = array(0, 1, 2, 4); - break; - case 8: - $this->c = array(0, 1, 3, 4); - } - - $w = array_values(unpack('N*words', $this->key)); - - $length = $this->Nb * ($this->Nr + 1); - for ($i = $this->Nk; $i < $length; $i++) { - $temp = $w[$i - 1]; - if ($i % $this->Nk == 0) { - // according to , "the size of an integer is platform-dependent". - // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine, - // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and' - // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is. - $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord - $temp = $this->subWord($temp) ^ $rcon[$i / $this->Nk]; - } elseif ($this->Nk > 6 && $i % $this->Nk == 4) { - $temp = $this->subWord($temp); - } - $w[$i] = $w[$i - $this->Nk] ^ $temp; - } - - // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns - // and generate the inverse key schedule. more specifically, - // according to (section 5.3.3), - // "The key expansion for the Inverse Cipher is defined as follows: - // 1. Apply the Key Expansion. - // 2. Apply InvMixColumn to all Round Keys except the first and the last one." - // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher" - list($dt0, $dt1, $dt2, $dt3) = $this->getInvTables(); - $temp = $this->w = $this->dw = array(); - for ($i = $row = $col = 0; $i < $length; $i++, $col++) { - if ($col == $this->Nb) { - if ($row == 0) { - $this->dw[0] = $this->w[0]; - } else { - // subWord + invMixColumn + invSubWord = invMixColumn - $j = 0; - while ($j < $this->Nb) { - $dw = $this->subWord($this->w[$row][$j]); - $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^ - $dt1[$dw >> 16 & 0x000000FF] ^ - $dt2[$dw >> 8 & 0x000000FF] ^ - $dt3[$dw & 0x000000FF]; - $j++; - } - $this->dw[$row] = $temp; - } - - $col = 0; - $row++; - } - $this->w[$row][$col] = $w[$i]; - } - - $this->dw[$row] = $this->w[$row]; - - // Converting to 1-dim key arrays (both ascending) - $this->dw = array_reverse($this->dw); - $w = array_pop($this->w); - $dw = array_pop($this->dw); - foreach ($this->w as $r => $wr) { - foreach ($wr as $c => $wc) { - $w[] = $wc; - $dw[] = $this->dw[$r][$c]; - } - } - $this->w = $w; - $this->dw = $dw; - } - - /** - * Performs S-Box substitutions - * - * @access private - * @param int $word - */ - private function subWord($word) - { - static $sbox; - if (empty($sbox)) { - list(, , , , $sbox) = self::getTables(); - } - - return $sbox[$word & 0x000000FF] | - ($sbox[$word >> 8 & 0x000000FF] << 8) | - ($sbox[$word >> 16 & 0x000000FF] << 16) | - ($sbox[$word >> 24 & 0x000000FF] << 24); - } - - /** - * Provides the mixColumns and sboxes tables - * - * @see self::encryptBlock() - * @see self::setupInlineCrypt() - * @see self::subWord() - * @access private - * @return array &$tables - */ - private function &getTables() - { - static $tables; - if (empty($tables)) { - // according to (section 5.2.1), - // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so - // those are the names we'll use. - $t3 = array_map('intval', array( - // with array_map('intval', ...) we ensure we have only int's and not - // some slower floats converted by php automatically on high values - 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, - 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, - 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, - 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, - 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, - 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, - 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, - 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, - 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, - 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, - 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, - 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, - 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, - 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, - 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, - 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, - 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, - 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, - 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, - 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, - 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, - 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, - 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, - 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, - 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, - 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, - 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, - 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, - 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, - 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, - 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, - 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C - )); - - foreach ($t3 as $t3i) { - $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF); - $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF); - $t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF); - } - - $tables = array( - // The Precomputed mixColumns tables t0 - t3 - $t0, - $t1, - $t2, - $t3, - // The SubByte S-Box - array( - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 - ) - ); - } - return $tables; - } - - /** - * Provides the inverse mixColumns and inverse sboxes tables - * - * @see self::decryptBlock() - * @see self::setupInlineCrypt() - * @see self::setupKey() - * @access private - * @return array &$tables - */ - private function &getInvTables() - { - static $tables; - if (empty($tables)) { - $dt3 = array_map('intval', array( - 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, - 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, - 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, - 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, - 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, - 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, - 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, - 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, - 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, - 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, - 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, - 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, - 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, - 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, - 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, - 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, - 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, - 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, - 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, - 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, - 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, - 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, - 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, - 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, - 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, - 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, - 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, - 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, - 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, - 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, - 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, - 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 - )); - - foreach ($dt3 as $dt3i) { - $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF); - $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF); - $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF); - }; - - $tables = array( - // The Precomputed inverse mixColumns tables dt0 - dt3 - $dt0, - $dt1, - $dt2, - $dt3, - // The inverse SubByte S-Box - array( - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D - ) - ); - } - return $tables; - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setupInlineCrypt() - * @access private - */ - protected function setupInlineCrypt() - { - $w = $this->w; - $dw = $this->dw; - $init_encrypt = ''; - $init_decrypt = ''; - - $Nr = $this->Nr; - $Nb = $this->Nb; - $c = $this->c; - - // Generating encrypt code: - $init_encrypt.= ' - static $tables; - if (empty($tables)) { - $tables = &$this->getTables(); - } - $t0 = $tables[0]; - $t1 = $tables[1]; - $t2 = $tables[2]; - $t3 = $tables[3]; - $sbox = $tables[4]; - '; - - $s = 'e'; - $e = 's'; - $wc = $Nb - 1; - - // Preround: addRoundKey - $encrypt_block = '$in = unpack("N*", $in);'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n"; - } - - // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey - for ($round = 1; $round < $Nr; ++$round) { - list($s, $e) = array($e, $s); - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block.= - '$'.$e.$i.' = - $t0[($'.$s.$i .' >> 24) & 0xff] ^ - $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^ - $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^ - $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^ - '.$w[++$wc].";\n"; - } - } - - // Finalround: subWord + shiftRows + addRoundKey - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block.= - '$'.$e.$i.' = - $sbox[ $'.$e.$i.' & 0xff] | - ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) | - ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) | - ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; - } - $encrypt_block .= '$in = pack("N*"'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block.= ', - ($'.$e.$i .' & '.((int)0xFF000000).') ^ - ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^ - ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^ - ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^ - '.$w[$i]."\n"; - } - $encrypt_block .= ');'; - - // Generating decrypt code: - $init_decrypt.= ' - static $invtables; - if (empty($invtables)) { - $invtables = &$this->getInvTables(); - } - $dt0 = $invtables[0]; - $dt1 = $invtables[1]; - $dt2 = $invtables[2]; - $dt3 = $invtables[3]; - $isbox = $invtables[4]; - '; - - $s = 'e'; - $e = 's'; - $wc = $Nb - 1; - - // Preround: addRoundKey - $decrypt_block = '$in = unpack("N*", $in);'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n"; - } - - // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey - for ($round = 1; $round < $Nr; ++$round) { - list($s, $e) = array($e, $s); - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block.= - '$'.$e.$i.' = - $dt0[($'.$s.$i .' >> 24) & 0xff] ^ - $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^ - $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^ - $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^ - '.$dw[++$wc].";\n"; - } - } - - // Finalround: subWord + shiftRows + addRoundKey - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block.= - '$'.$e.$i.' = - $isbox[ $'.$e.$i.' & 0xff] | - ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) | - ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) | - ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; - } - $decrypt_block .= '$in = pack("N*"'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block.= ', - ($'.$e.$i. ' & '.((int)0xFF000000).') ^ - ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^ - ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^ - ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^ - '.$dw[$i]."\n"; - } - $decrypt_block .= ');'; - - $this->inline_crypt = $this->createInlineCryptFunction( - array( - 'init_crypt' => '', - 'init_encrypt' => $init_encrypt, - 'init_decrypt' => $init_decrypt, - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ) - ); - } -} diff --git a/lib/phpaes/phpseclib/Crypt/TripleDES.php b/lib/phpaes/phpseclib/Crypt/TripleDES.php deleted file mode 100644 index b597d29dea..0000000000 --- a/lib/phpaes/phpseclib/Crypt/TripleDES.php +++ /dev/null @@ -1,459 +0,0 @@ - - * setKey('abcdefghijklmnopqrstuvwx'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $des->decrypt($des->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package TripleDES - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -/** - * Pure-PHP implementation of Triple DES. - * - * @package TripleDES - * @author Jim Wigginton - * @access public - */ -class TripleDES extends DES -{ - /** - * Encrypt / decrypt using inner chaining - * - * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3). - */ - const MODE_3CBC = -2; - - /** - * Encrypt / decrypt using outer chaining - * - * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Common\BlockCipher::MODE_CBC. - */ - const MODE_CBC3 = self::MODE_CBC; - - /** - * Key Length (in bytes) - * - * @see \phpseclib\Crypt\TripleDES::setKeyLength() - * @var int - * @access private - */ - protected $key_length = 24; - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib\Crypt\DES::cipher_name_mcrypt - * @see \phpseclib\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - * @access private - */ - protected $cipher_name_mcrypt = 'tripledes'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - * @access private - */ - protected $cfb_init_len = 750; - - /** - * max possible size of $key - * - * @see self::setKey() - * @see \phpseclib\Crypt\DES::setKey() - * @var string - * @access private - */ - protected $key_length_max = 24; - - /** - * Internal flag whether using self::MODE_3CBC or not - * - * @var bool - * @access private - */ - private $mode_3cbc; - - /** - * The \phpseclib\Crypt\DES objects - * - * Used only if $mode_3cbc === true - * - * @var array - * @access private - */ - private $des; - - /** - * Default Constructor. - * - * Determines whether or not the mcrypt or OpenSSL extensions should be used. - * - * $mode could be: - * - * - \phpseclib\Crypt\Common\BlockCipher::MODE_ECB - * - * - \phpseclib\Crypt\Common\BlockCipher::MODE_CBC - * - * - \phpseclib\Crypt\Common\BlockCipher::MODE_CTR - * - * - \phpseclib\Crypt\Common\BlockCipher::MODE_CFB - * - * - \phpseclib\Crypt\Common\BlockCipher::MODE_OFB - * - * - \phpseclib\Crypt\TripleDES::MODE_3CB - * - * @see \phpseclib\Crypt\DES::__construct() - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - * @param int $mode - * @access public - */ - public function __construct($mode) - { - switch ($mode) { - // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC - // and additional flag us internally as 3CBC - case self::MODE_3CBC: - parent::__construct(self::MODE_CBC); - $this->mode_3cbc = true; - - // This three $des'es will do the 3CBC work (if $key > 64bits) - $this->des = [ - new DES(self::MODE_CBC), - new DES(self::MODE_CBC), - new DES(self::MODE_CBC), - ]; - - // we're going to be doing the padding, ourselves, so disable it in the \phpseclib\Crypt\DES objects - $this->des[0]->disablePadding(); - $this->des[1]->disablePadding(); - $this->des[2]->disablePadding(); - break; - // If not 3CBC, we init as usual - default: - parent::__construct($mode); - } - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @access public - * @return bool - */ - public function isValidEngine($engine) - { - if ($engine == self::ENGINE_OPENSSL) { - $this->cipher_name_openssl_ecb = 'des-ede3'; - $mode = $this->openssl_translate_mode(); - $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode; - } - - return parent::isValidEngine($engine); - } - - /** - * Sets the initialization vector. - * - * SetIV is not required when \phpseclib\Crypt\Common\SymmetricKey::MODE_ECB is being used. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::setIV() - * @access public - * @param string $iv - */ - public function setIV($iv) - { - parent::setIV($iv); - if ($this->mode_3cbc) { - $this->des[0]->setIV($iv); - $this->des[1]->setIV($iv); - $this->des[2]->setIV($iv); - } - } - - /** - * Sets the key length. - * - * Valid key lengths are 128 and 192 bits. - * - * If you want to use a 64-bit key use DES.php - * - * @see \phpseclib\Crypt\Common\SymmetricKey:setKeyLength() - * @access public - * @throws \LengthException if the key length is invalid - * @param int $length - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 192: - break; - default: - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128 or 192 bits are supported'); - } - - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys. - * - * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. - * - * @access public - * @see \phpseclib\Crypt\DES::setKey() - * @see \phpseclib\Crypt\Common\SymmetricKey::setKey() - * @throws \LengthException if the key length is invalid - * @param string $key - */ - public function setKey($key) - { - if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) { - throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes'); - } - - switch (strlen($key)) { - case 16: - $key.= substr($key, 0, 8); - case 24: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 24 are supported'); - } - - // copied from self::setKey() - $this->key = $key; - $this->key_length = strlen($key); - $this->changed = true; - $this->setEngine(); - - if ($this->mode_3cbc) { - $this->des[0]->setKey(substr($key, 0, 8)); - $this->des[1]->setKey(substr($key, 8, 8)); - $this->des[2]->setKey(substr($key, 16, 8)); - } - } - - /** - * Encrypts a message. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::encrypt() - * @access public - * @param string $plaintext - * @return string $cipertext - */ - public function encrypt($plaintext) - { - // parent::en/decrypt() is able to do all the work for all modes and keylengths, - // except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits - - // if the key is smaller then 8, do what we'd normally do - if ($this->mode_3cbc && strlen($this->key) > 8) { - return $this->des[2]->encrypt( - $this->des[1]->decrypt( - $this->des[0]->encrypt( - $this->pad($plaintext) - ) - ) - ); - } - - return parent::encrypt($plaintext); - } - - /** - * Decrypts a message. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::decrypt() - * @access public - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - if ($this->mode_3cbc && strlen($this->key) > 8) { - return $this->unpad( - $this->des[0]->decrypt( - $this->des[1]->encrypt( - $this->des[2]->decrypt( - str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0") - ) - ) - ) - ); - } - - return parent::decrypt($ciphertext); - } - - /** - * Treat consecutive "packets" as if they are a continuous buffer. - * - * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets - * will yield different outputs: - * - * - * echo $des->encrypt(substr($plaintext, 0, 8)); - * echo $des->encrypt(substr($plaintext, 8, 8)); - * - * - * echo $des->encrypt($plaintext); - * - * - * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates - * another, as demonstrated with the following: - * - * - * $des->encrypt(substr($plaintext, 0, 8)); - * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8))); - * - * - * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8))); - * - * - * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different - * outputs. The reason is due to the fact that the initialization vector's change after every encryption / - * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. - * - * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\DES() object changes after each - * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that - * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), - * however, they are also less intuitive and more likely to cause you problems. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::enableContinuousBuffer() - * @see self::disableContinuousBuffer() - * @access public - */ - public function enableContinuousBuffer() - { - parent::enableContinuousBuffer(); - if ($this->mode_3cbc) { - $this->des[0]->enableContinuousBuffer(); - $this->des[1]->enableContinuousBuffer(); - $this->des[2]->enableContinuousBuffer(); - } - } - - /** - * Treat consecutive packets as if they are a discontinuous buffer. - * - * The default behavior. - * - * @see \phpseclib\Crypt\Common\SymmetricKey::disableContinuousBuffer() - * @see self::enableContinuousBuffer() - * @access public - */ - public function disableContinuousBuffer() - { - parent::disableContinuousBuffer(); - if ($this->mode_3cbc) { - $this->des[0]->disableContinuousBuffer(); - $this->des[1]->disableContinuousBuffer(); - $this->des[2]->disableContinuousBuffer(); - } - } - - /** - * Creates the key schedule - * - * @see \phpseclib\Crypt\DES::setupKey() - * @see \phpseclib\Crypt\Common\SymmetricKey::setupKey() - * @access private - */ - protected function setupKey() - { - switch (true) { - // if $key <= 64bits we configure our internal pure-php cipher engine - // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same. - case strlen($this->key) <= 8: - $this->des_rounds = 1; - break; - - // otherwise, if $key > 64bits, we configure our engine to work as 3DES. - default: - $this->des_rounds = 3; - - // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately. - if ($this->mode_3cbc) { - $this->des[0]->setupKey(); - $this->des[1]->setupKey(); - $this->des[2]->setupKey(); - - // because $des[0-2] will, now, do all the work we can return here - // not need unnecessary stress parent::setupKey() with our, now unused, $key. - return; - } - } - // setup our key - parent::setupKey(); - } - - /** - * Sets the internal crypt engine - * - * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() - * @see \phpseclib\Crypt\Common\SymmetricKey::setPreferredEngine() - * @param int $engine - * @access public - * @return int - */ - public function setPreferredEngine($engine) - { - if ($this->mode_3cbc) { - $this->des[0]->setPreferredEngine($engine); - $this->des[1]->setPreferredEngine($engine); - $this->des[2]->setPreferredEngine($engine); - } - - return parent::setPreferredEngine($engine); - } - - /** - * Returns the class that defines the private methods - * - * @access private - * @return string - */ - protected function getClassContext() - { - return 'phpseclib\Crypt\DES'; - } -} diff --git a/lib/phpaes/phpseclib/Crypt/Twofish.php b/lib/phpaes/phpseclib/Crypt/Twofish.php deleted file mode 100644 index 3c1f6dcb06..0000000000 --- a/lib/phpaes/phpseclib/Crypt/Twofish.php +++ /dev/null @@ -1,817 +0,0 @@ - - * setKey('12345678901234567890123456789012'); - * - * $plaintext = str_repeat('a', 1024); - * - * echo $twofish->decrypt($twofish->encrypt($plaintext)); - * ?> - * - * - * @category Crypt - * @package Twofish - * @author Jim Wigginton - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt; - -use phpseclib\Crypt\Common\BlockCipher; - -/** - * Pure-PHP implementation of Twofish. - * - * @package Twofish - * @author Jim Wigginton - * @author Hans-Juergen Petrich - * @access public - */ -class Twofish extends BlockCipher -{ - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - * @access private - */ - protected $cipher_name_mcrypt = 'twofish'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - * @access private - */ - protected $cfb_init_len = 800; - - /** - * Q-Table - * - * @var array - * @access private - */ - private $q0 = [ - 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, - 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, - 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, - 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, - 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, - 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, - 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, - 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, - 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, - 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, - 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, - 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, - 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, - 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, - 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, - 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, - 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, - 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, - 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, - 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, - 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, - 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, - 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, - 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, - 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, - 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, - 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, - 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, - 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, - 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, - 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, - 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 - ]; - - /** - * Q-Table - * - * @var array - * @access private - */ - private $q1 = [ - 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, - 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, - 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, - 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, - 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, - 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, - 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, - 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, - 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, - 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, - 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, - 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, - 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, - 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, - 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, - 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, - 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, - 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, - 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, - 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, - 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, - 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, - 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, - 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, - 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, - 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, - 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, - 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, - 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, - 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, - 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, - 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 - ]; - - /** - * M-Table - * - * @var array - * @access private - */ - private $m0 = [ - 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, - 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, - 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, - 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F, - 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, - 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, - 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3, - 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, - 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, - 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C, - 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, - 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, - 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC, - 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, - 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, - 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17, - 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, - 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, - 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149, - 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, - 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, - 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48, - 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, - 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, - 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5, - 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, - 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, - 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC, - 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, - 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, - 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2, - 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91 - ]; - - /** - * M-Table - * - * @var array - * @access private - */ - private $m1 = [ - 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, - 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, - 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, - 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E, - 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, - 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, - 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D, - 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, - 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, - 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B, - 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, - 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, - 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D, - 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, - 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, - 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7, - 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, - 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, - 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E, - 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, - 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, - 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F, - 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, - 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, - 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7, - 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, - 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, - 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323, - 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, - 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, - 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000, - 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8 - ]; - - /** - * M-Table - * - * @var array - * @access private - */ - private $m2 = [ - 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, - 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, - 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, - 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE, - 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, - 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, - 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065, - 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, - 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, - 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF, - 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, - 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, - 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF, - 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, - 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, - 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC, - 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, - 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, - 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101, - 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, - 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, - 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A, - 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, - 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, - 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6, - 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, - 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, - 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB, - 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, - 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, - 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746, - 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF - ]; - - /** - * M-Table - * - * @var array - * @access private - */ - private $m3 = [ - 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, - 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, - 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, - 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A, - 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, - 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, - 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63, - 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, - 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, - 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197, - 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, - 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, - 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20, - 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, - 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, - 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730, - 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, - 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, - 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F, - 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, - 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, - 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D, - 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, - 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, - 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6, - 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, - 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, - 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439, - 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, - 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, - 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000, - 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8 - ]; - - /** - * The Key Schedule Array - * - * @var array - * @access private - */ - private $K = []; - - /** - * The Key depended S-Table 0 - * - * @var array - * @access private - */ - private $S0 = []; - - /** - * The Key depended S-Table 1 - * - * @var array - * @access private - */ - private $S1 = []; - - /** - * The Key depended S-Table 2 - * - * @var array - * @access private - */ - private $S2 = []; - - /** - * The Key depended S-Table 3 - * - * @var array - * @access private - */ - private $S3 = []; - - /** - * Holds the last used key - * - * @var array - * @access private - */ - private $kl; - - /** - * The Key Length (in bytes) - * - * @see Crypt_Twofish::setKeyLength() - * @var int - * @access private - */ - protected $key_length = 16; - - /** - * Default Constructor. - * - * @param int $mode - * @access public - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - if ($mode == self::MODE_STREAM) { - throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode'); - } - - parent::__construct($mode); - } - - /** - * Sets the key length. - * - * Valid key lengths are 128, 192 or 256 bits - * - * @access public - * @param int $length - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 192: - case 256: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); - } - - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Rijndael supports five different key lengths - * - * @see setKeyLength() - * @access public - * @param string $key - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key) - { - switch (strlen($key)) { - case 16: - case 24: - case 32: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); - } - - parent::setKey($key); - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib\Crypt\Common\SymmetricKey::_setupKey() - * @access private - */ - protected function setupKey() - { - if (isset($this->kl['key']) && $this->key === $this->kl['key']) { - // already expanded - return; - } - $this->kl = ['key' => $this->key]; - - /* Key expanding and generating the key-depended s-boxes */ - $le_longs = unpack('V*', $this->key); - $key = unpack('C*', $this->key); - $m0 = $this->m0; - $m1 = $this->m1; - $m2 = $this->m2; - $m3 = $this->m3; - $q0 = $this->q0; - $q1 = $this->q1; - - $K = $S0 = $S1 = $S2 = $S3 = []; - - switch (strlen($this->key)) { - case 16: - list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[1], $le_longs[2]); - list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[3], $le_longs[4]); - for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { - $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^ - $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^ - $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^ - $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]]; - $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^ - $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^ - $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^ - $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]]; - $B = ($B << 8) | ($B >> 24 & 0xff); - $K[] = $A+= $B; - $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff); - } - for ($i = 0; $i < 256; ++$i) { - $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0]; - $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1]; - $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2]; - $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3]; - } - break; - case 24: - list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[1], $le_longs[2]); - list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[3], $le_longs[4]); - list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[5], $le_longs[6]); - for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { - $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ - $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ - $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ - $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]]; - $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ - $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ - $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ - $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]]; - $B = ($B << 8) | ($B >> 24 & 0xff); - $K[] = $A+= $B; - $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff); - } - for ($i = 0; $i < 256; ++$i) { - $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0]; - $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1]; - $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2]; - $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3]; - } - break; - default: // 32 - list($sf, $se, $sd, $sc) = $this->mdsrem($le_longs[1], $le_longs[2]); - list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[3], $le_longs[4]); - list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[5], $le_longs[6]); - list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[7], $le_longs[8]); - for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { - $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ - $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ - $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ - $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]]; - $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ - $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ - $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ - $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]]; - $B = ($B << 8) | ($B >> 24 & 0xff); - $K[] = $A+= $B; - $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff); - } - for ($i = 0; $i < 256; ++$i) { - $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0]; - $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1]; - $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2]; - $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3]; - } - } - - $this->K = $K; - $this->S0 = $S0; - $this->S1 = $S1; - $this->S2 = $S2; - $this->S3 = $S3; - } - - /** - * _mdsrem function using by the twofish cipher algorithm - * - * @access private - * @param string $A - * @param string $B - * @return array - */ - private function mdsrem($A, $B) - { - // No gain by unrolling this loop. - for ($i = 0; $i < 8; ++$i) { - // Get most significant coefficient. - $t = 0xff & ($B >> 24); - - // Shift the others up. - $B = ($B << 8) | (0xff & ($A >> 24)); - $A<<= 8; - - $u = $t << 1; - - // Subtract the modular polynomial on overflow. - if ($t & 0x80) { - $u^= 0x14d; - } - - // Remove t * (a * x^2 + 1). - $B ^= $t ^ ($u << 16); - - // Form u = a*t + t/a = t*(a + 1/a). - $u^= 0x7fffffff & ($t >> 1); - - // Add the modular polynomial on underflow. - if ($t & 0x01) { - $u^= 0xa6 ; - } - - // Remove t * (a + 1/a) * (x^3 + x). - $B^= ($u << 24) | ($u << 8); - } - - return [ - 0xff & $B >> 24, - 0xff & $B >> 16, - 0xff & $B >> 8, - 0xff & $B]; - } - - /** - * Encrypts a block - * - * @access private - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - $S0 = $this->S0; - $S1 = $this->S1; - $S2 = $this->S2; - $S3 = $this->S3; - $K = $this->K; - - $in = unpack("V4", $in); - $R0 = $K[0] ^ $in[1]; - $R1 = $K[1] ^ $in[2]; - $R2 = $K[2] ^ $in[3]; - $R3 = $K[3] ^ $in[4]; - - $ki = 7; - while ($ki < 39) { - $t0 = $S0[ $R0 & 0xff] ^ - $S1[($R0 >> 8) & 0xff] ^ - $S2[($R0 >> 16) & 0xff] ^ - $S3[($R0 >> 24) & 0xff]; - $t1 = $S0[($R1 >> 24) & 0xff] ^ - $S1[ $R1 & 0xff] ^ - $S2[($R1 >> 8) & 0xff] ^ - $S3[($R1 >> 16) & 0xff]; - $R2^= $t0 + $t1 + $K[++$ki]; - $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31); - $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]); - - $t0 = $S0[ $R2 & 0xff] ^ - $S1[($R2 >> 8) & 0xff] ^ - $S2[($R2 >> 16) & 0xff] ^ - $S3[($R2 >> 24) & 0xff]; - $t1 = $S0[($R3 >> 24) & 0xff] ^ - $S1[ $R3 & 0xff] ^ - $S2[($R3 >> 8) & 0xff] ^ - $S3[($R3 >> 16) & 0xff]; - $R0^= ($t0 + $t1 + $K[++$ki]); - $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31); - $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]); - } - - // @codingStandardsIgnoreStart - return pack("V4", $K[4] ^ $R2, - $K[5] ^ $R3, - $K[6] ^ $R0, - $K[7] ^ $R1); - // @codingStandardsIgnoreEnd - } - - /** - * Decrypts a block - * - * @access private - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - $S0 = $this->S0; - $S1 = $this->S1; - $S2 = $this->S2; - $S3 = $this->S3; - $K = $this->K; - - $in = unpack("V4", $in); - $R0 = $K[4] ^ $in[1]; - $R1 = $K[5] ^ $in[2]; - $R2 = $K[6] ^ $in[3]; - $R3 = $K[7] ^ $in[4]; - - $ki = 40; - while ($ki > 8) { - $t0 = $S0[$R0 & 0xff] ^ - $S1[$R0 >> 8 & 0xff] ^ - $S2[$R0 >> 16 & 0xff] ^ - $S3[$R0 >> 24 & 0xff]; - $t1 = $S0[$R1 >> 24 & 0xff] ^ - $S1[$R1 & 0xff] ^ - $S2[$R1 >> 8 & 0xff] ^ - $S3[$R1 >> 16 & 0xff]; - $R3^= $t0 + ($t1 << 1) + $K[--$ki]; - $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31; - $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]); - - $t0 = $S0[$R2 & 0xff] ^ - $S1[$R2 >> 8 & 0xff] ^ - $S2[$R2 >> 16 & 0xff] ^ - $S3[$R2 >> 24 & 0xff]; - $t1 = $S0[$R3 >> 24 & 0xff] ^ - $S1[$R3 & 0xff] ^ - $S2[$R3 >> 8 & 0xff] ^ - $S3[$R3 >> 16 & 0xff]; - $R1^= $t0 + ($t1 << 1) + $K[--$ki]; - $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31; - $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]); - } - - // @codingStandardsIgnoreStart - return pack("V4", $K[0] ^ $R2, - $K[1] ^ $R3, - $K[2] ^ $R0, - $K[3] ^ $R1); - // @codingStandardsIgnoreEnd - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib\Crypt\Common\SymmetricKey::_setupInlineCrypt() - * @access private - */ - protected function setupInlineCrypt() - { - $K = $this->K; - $init_crypt = ' - static $S0, $S1, $S2, $S3; - if (!$S0) { - for ($i = 0; $i < 256; ++$i) { - $S0[] = (int)$this->S0[$i]; - $S1[] = (int)$this->S1[$i]; - $S2[] = (int)$this->S2[$i]; - $S3[] = (int)$this->S3[$i]; - } - } - '; - - // Generating encrypt code: - $encrypt_block = ' - $in = unpack("V4", $in); - $R0 = '.$K[0].' ^ $in[1]; - $R1 = '.$K[1].' ^ $in[2]; - $R2 = '.$K[2].' ^ $in[3]; - $R3 = '.$K[3].' ^ $in[4]; - '; - for ($ki = 7, $i = 0; $i < 8; ++$i) { - $encrypt_block.= ' - $t0 = $S0[ $R0 & 0xff] ^ - $S1[($R0 >> 8) & 0xff] ^ - $S2[($R0 >> 16) & 0xff] ^ - $S3[($R0 >> 24) & 0xff]; - $t1 = $S0[($R1 >> 24) & 0xff] ^ - $S1[ $R1 & 0xff] ^ - $S2[($R1 >> 8) & 0xff] ^ - $S3[($R1 >> 16) & 0xff]; - $R2^= ($t0 + $t1 + '.$K[++$ki].'); - $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31); - $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].'); - - $t0 = $S0[ $R2 & 0xff] ^ - $S1[($R2 >> 8) & 0xff] ^ - $S2[($R2 >> 16) & 0xff] ^ - $S3[($R2 >> 24) & 0xff]; - $t1 = $S0[($R3 >> 24) & 0xff] ^ - $S1[ $R3 & 0xff] ^ - $S2[($R3 >> 8) & 0xff] ^ - $S3[($R3 >> 16) & 0xff]; - $R0^= ($t0 + $t1 + '.$K[++$ki].'); - $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31); - $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].'); - '; - } - $encrypt_block.= ' - $in = pack("V4", '.$K[4].' ^ $R2, - '.$K[5].' ^ $R3, - '.$K[6].' ^ $R0, - '.$K[7].' ^ $R1); - '; - - // Generating decrypt code: - $decrypt_block = ' - $in = unpack("V4", $in); - $R0 = '.$K[4].' ^ $in[1]; - $R1 = '.$K[5].' ^ $in[2]; - $R2 = '.$K[6].' ^ $in[3]; - $R3 = '.$K[7].' ^ $in[4]; - '; - for ($ki = 40, $i = 0; $i < 8; ++$i) { - $decrypt_block.= ' - $t0 = $S0[$R0 & 0xff] ^ - $S1[$R0 >> 8 & 0xff] ^ - $S2[$R0 >> 16 & 0xff] ^ - $S3[$R0 >> 24 & 0xff]; - $t1 = $S0[$R1 >> 24 & 0xff] ^ - $S1[$R1 & 0xff] ^ - $S2[$R1 >> 8 & 0xff] ^ - $S3[$R1 >> 16 & 0xff]; - $R3^= $t0 + ($t1 << 1) + '.$K[--$ki].'; - $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31; - $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].'); - - $t0 = $S0[$R2 & 0xff] ^ - $S1[$R2 >> 8 & 0xff] ^ - $S2[$R2 >> 16 & 0xff] ^ - $S3[$R2 >> 24 & 0xff]; - $t1 = $S0[$R3 >> 24 & 0xff] ^ - $S1[$R3 & 0xff] ^ - $S2[$R3 >> 8 & 0xff] ^ - $S3[$R3 >> 16 & 0xff]; - $R1^= $t0 + ($t1 << 1) + '.$K[--$ki].'; - $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31; - $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].'); - '; - } - $decrypt_block.= ' - $in = pack("V4", '.$K[0].' ^ $R2, - '.$K[1].' ^ $R3, - '.$K[2].' ^ $R0, - '.$K[3].' ^ $R1); - '; - - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'init_encrypt' => '', - 'init_decrypt' => '', - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ] - ); - } -} diff --git a/lib/phpaes/phpseclib/Exception/BadConfigurationException.php b/lib/phpaes/phpseclib/Exception/BadConfigurationException.php deleted file mode 100644 index 096148a0df..0000000000 --- a/lib/phpaes/phpseclib/Exception/BadConfigurationException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * BadConfigurationException - * - * @package BadConfigurationException - * @author Jim Wigginton - */ -class BadConfigurationException extends \RuntimeException -{ -} diff --git a/lib/phpaes/phpseclib/Exception/FileNotFoundException.php b/lib/phpaes/phpseclib/Exception/FileNotFoundException.php deleted file mode 100644 index 984edfcc7a..0000000000 --- a/lib/phpaes/phpseclib/Exception/FileNotFoundException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * FileNotFoundException - * - * @package FileNotFoundException - * @author Jim Wigginton - */ -class FileNotFoundException extends \RuntimeException -{ -} diff --git a/lib/phpaes/phpseclib/Exception/NoSupportedAlgorithmsException.php b/lib/phpaes/phpseclib/Exception/NoSupportedAlgorithmsException.php deleted file mode 100644 index bca9a753b5..0000000000 --- a/lib/phpaes/phpseclib/Exception/NoSupportedAlgorithmsException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * NoSupportedAlgorithmsException - * - * @package NoSupportedAlgorithmsException - * @author Jim Wigginton - */ -class NoSupportedAlgorithmsException extends \RuntimeException -{ -} diff --git a/lib/phpaes/phpseclib/Exception/UnsupportedAlgorithmException.php b/lib/phpaes/phpseclib/Exception/UnsupportedAlgorithmException.php deleted file mode 100644 index 47cc41d4d3..0000000000 --- a/lib/phpaes/phpseclib/Exception/UnsupportedAlgorithmException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * UnsupportedAlgorithmException - * - * @package UnsupportedAlgorithmException - * @author Jim Wigginton - */ -class UnsupportedAlgorithmException extends \RuntimeException -{ -} diff --git a/lib/phpaes/phpseclib/File/ANSI.php b/lib/phpaes/phpseclib/File/ANSI.php deleted file mode 100644 index 0f1990d4ab..0000000000 --- a/lib/phpaes/phpseclib/File/ANSI.php +++ /dev/null @@ -1,574 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File; - -/** - * Pure-PHP ANSI Decoder - * - * @package ANSI - * @author Jim Wigginton - * @access public - */ -class ANSI -{ - /** - * Max Width - * - * @var int - * @access private - */ - private $max_x; - - /** - * Max Height - * - * @var int - * @access private - */ - private $max_y; - - /** - * Max History - * - * @var int - * @access private - */ - private $max_history; - - /** - * History - * - * @var array - * @access private - */ - private $history; - - /** - * History Attributes - * - * @var array - * @access private - */ - private $history_attrs; - - /** - * Current Column - * - * @var int - * @access private - */ - private $x; - - /** - * Current Row - * - * @var int - * @access private - */ - private $y; - - /** - * Old Column - * - * @var int - * @access private - */ - private $old_x; - - /** - * Old Row - * - * @var int - * @access private - */ - private $old_y; - - /** - * An empty attribute cell - * - * @var object - * @access private - */ - private $base_attr_cell; - - /** - * The current attribute cell - * - * @var object - * @access private - */ - private $attr_cell; - - /** - * An empty attribute row - * - * @var array - * @access private - */ - private $attr_row; - - /** - * The current screen text - * - * @var array - * @access private - */ - private $screen; - - /** - * The current screen attributes - * - * @var array - * @access private - */ - private $attrs; - - /** - * Current ANSI code - * - * @var string - * @access private - */ - private $ansi; - - /** - * Tokenization - * - * @var array - * @access private - */ - private $tokenization; - - /** - * Default Constructor. - * - * @return \phpseclib\File\ANSI - * @access public - */ - public function __construct() - { - $attr_cell = new \stdClass(); - $attr_cell->bold = false; - $attr_cell->underline = false; - $attr_cell->blink = false; - $attr_cell->background = 'black'; - $attr_cell->foreground = 'white'; - $attr_cell->reverse = false; - $this->base_attr_cell = clone $attr_cell; - $this->attr_cell = clone $attr_cell; - - $this->setHistory(200); - $this->setDimensions(80, 24); - } - - /** - * Set terminal width and height - * - * Resets the screen as well - * - * @param int $x - * @param int $y - * @access public - */ - public function setDimensions($x, $y) - { - $this->max_x = $x - 1; - $this->max_y = $y - 1; - $this->x = $this->y = 0; - $this->history = $this->history_attrs = []; - $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell); - $this->screen = array_fill(0, $this->max_y + 1, ''); - $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row); - $this->ansi = ''; - } - - /** - * Set the number of lines that should be logged past the terminal height - * - * @param int $x - * @param int $y - * @access public - */ - public function setHistory($history) - { - $this->max_history = $history; - } - - /** - * Load a string - * - * @param string $source - * @access public - */ - public function loadString($source) - { - $this->setDimensions($this->max_x + 1, $this->max_y + 1); - $this->appendString($source); - } - - /** - * Appdend a string - * - * @param string $source - * @access public - */ - public function appendString($source) - { - $this->tokenization = ['']; - for ($i = 0; $i < strlen($source); $i++) { - if (strlen($this->ansi)) { - $this->ansi.= $source[$i]; - $chr = ord($source[$i]); - // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements - // single character CSI's not currently supported - switch (true) { - case $this->ansi == "\x1B=": - $this->ansi = ''; - continue 2; - case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['): - case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126: - break; - default: - continue 2; - } - $this->tokenization[] = $this->ansi; - $this->tokenization[] = ''; - // http://ascii-table.com/ansi-escape-sequences-vt-100.php - switch ($this->ansi) { - case "\x1B[H": // Move cursor to upper left corner - $this->old_x = $this->x; - $this->old_y = $this->y; - $this->x = $this->y = 0; - break; - case "\x1B[J": // Clear screen from cursor down - $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y)); - $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, '')); - - $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y)); - $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row)); - - if (count($this->history) == $this->max_history) { - array_shift($this->history); - array_shift($this->history_attrs); - } - case "\x1B[K": // Clear screen from cursor right - $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); - - array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell)); - break; - case "\x1B[2K": // Clear entire line - $this->screen[$this->y] = str_repeat(' ', $this->x); - $this->attrs[$this->y] = $this->attr_row; - break; - case "\x1B[?1h": // set cursor key to application - case "\x1B[?25h": // show the cursor - case "\x1B(B": // set united states g0 character set - break; - case "\x1BE": // Move to next line - $this->newLine(); - $this->x = 0; - break; - default: - switch (true) { - case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines - $this->old_y = $this->y; - $this->y+= $match[1]; - break; - case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h - $this->old_x = $this->x; - $this->old_y = $this->y; - $this->x = $match[2] - 1; - $this->y = $match[1] - 1; - break; - case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines - $this->old_x = $this->x; - $this->x+= $match[1]; - break; - case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines - $this->old_x = $this->x; - $this->x-= $match[1]; - break; - case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window - break; - case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes - $attr_cell = &$this->attr_cell; - $mods = explode(';', $match[1]); - foreach ($mods as $mod) { - switch ($mod) { - case 0: // Turn off character attributes - $attr_cell = clone $this->base_attr_cell; - break; - case 1: // Turn bold mode on - $attr_cell->bold = true; - break; - case 4: // Turn underline mode on - $attr_cell->underline = true; - break; - case 5: // Turn blinking mode on - $attr_cell->blink = true; - break; - case 7: // Turn reverse video on - $attr_cell->reverse = !$attr_cell->reverse; - $temp = $attr_cell->background; - $attr_cell->background = $attr_cell->foreground; - $attr_cell->foreground = $temp; - break; - default: // set colors - //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground; - $front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' }; - //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background; - $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' }; - switch ($mod) { - // @codingStandardsIgnoreStart - case 30: $front = 'black'; break; - case 31: $front = 'red'; break; - case 32: $front = 'green'; break; - case 33: $front = 'yellow'; break; - case 34: $front = 'blue'; break; - case 35: $front = 'magenta'; break; - case 36: $front = 'cyan'; break; - case 37: $front = 'white'; break; - - case 40: $back = 'black'; break; - case 41: $back = 'red'; break; - case 42: $back = 'green'; break; - case 43: $back = 'yellow'; break; - case 44: $back = 'blue'; break; - case 45: $back = 'magenta'; break; - case 46: $back = 'cyan'; break; - case 47: $back = 'white'; break; - // @codingStandardsIgnoreEnd - - default: - //user_error('Unsupported attribute: ' . $mod); - $this->ansi = ''; - break 2; - } - } - } - break; - default: - //user_error("{$this->ansi} is unsupported\r\n"); - } - } - $this->ansi = ''; - continue; - } - - $this->tokenization[count($this->tokenization) - 1].= $source[$i]; - switch ($source[$i]) { - case "\r": - $this->x = 0; - break; - case "\n": - $this->newLine(); - break; - case "\x08": // backspace - if ($this->x) { - $this->x--; - $this->attrs[$this->y][$this->x] = clone $this->base_attr_cell; - $this->screen[$this->y] = substr_replace( - $this->screen[$this->y], - $source[$i], - $this->x, - 1 - ); - } - break; - case "\x0F": // shift - break; - case "\x1B": // start ANSI escape code - $this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1); - //if (!strlen($this->tokenization[count($this->tokenization) - 1])) { - // array_pop($this->tokenization); - //} - $this->ansi.= "\x1B"; - break; - default: - $this->attrs[$this->y][$this->x] = clone $this->attr_cell; - if ($this->x > strlen($this->screen[$this->y])) { - $this->screen[$this->y] = str_repeat(' ', $this->x); - } - $this->screen[$this->y] = substr_replace( - $this->screen[$this->y], - $source[$i], - $this->x, - 1 - ); - - if ($this->x > $this->max_x) { - $this->x = 0; - $this->y++; - } else { - $this->x++; - } - } - } - } - - /** - * Add a new line - * - * Also update the $this->screen and $this->history buffers - * - * @access private - */ - private function newLine() - { - //if ($this->y < $this->max_y) { - // $this->y++; - //} - - while ($this->y >= $this->max_y) { - $this->history = array_merge($this->history, [array_shift($this->screen)]); - $this->screen[] = ''; - - $this->history_attrs = array_merge($this->history_attrs, [array_shift($this->attrs)]); - $this->attrs[] = $this->attr_row; - - if (count($this->history) >= $this->max_history) { - array_shift($this->history); - array_shift($this->history_attrs); - } - - $this->y--; - } - $this->y++; - } - - /** - * Returns the current coordinate without preformating - * - * @access private - * @return string - */ - private function processCoordinate($last_attr, $cur_attr, $char) - { - $output = ''; - - if ($last_attr != $cur_attr) { - $close = $open = ''; - if ($last_attr->foreground != $cur_attr->foreground) { - if ($cur_attr->foreground != 'white') { - $open.= ''; - } - if ($last_attr->foreground != 'white') { - $close = '' . $close; - } - } - if ($last_attr->background != $cur_attr->background) { - if ($cur_attr->background != 'black') { - $open.= ''; - } - if ($last_attr->background != 'black') { - $close = '' . $close; - } - } - if ($last_attr->bold != $cur_attr->bold) { - if ($cur_attr->bold) { - $open.= ''; - } else { - $close = '' . $close; - } - } - if ($last_attr->underline != $cur_attr->underline) { - if ($cur_attr->underline) { - $open.= ''; - } else { - $close = '' . $close; - } - } - if ($last_attr->blink != $cur_attr->blink) { - if ($cur_attr->blink) { - $open.= ''; - } else { - $close = '' . $close; - } - } - $output.= $close . $open; - } - - $output.= htmlspecialchars($char); - - return $output; - } - - /** - * Returns the current screen without preformating - * - * @access private - * @return string - */ - private function getScreenHelper() - { - $output = ''; - $last_attr = $this->base_attr_cell; - for ($i = 0; $i <= $this->max_y; $i++) { - for ($j = 0; $j <= $this->max_x; $j++) { - $cur_attr = $this->attrs[$i][$j]; - $output.= $this->processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : ''); - $last_attr = $this->attrs[$i][$j]; - } - $output.= "\r\n"; - } - $output = substr($output, 0, -2); - // close any remaining open tags - $output.= $this->processCoordinate($last_attr, $this->base_attr_cell, ''); - return rtrim($output); - } - - /** - * Returns the current screen - * - * @access public - * @return string - */ - public function getScreen() - { - return '
' . $this->getScreenHelper() . '
'; - } - - /** - * Returns the current screen and the x previous lines - * - * @access public - * @return string - */ - public function getHistory() - { - $scrollback = ''; - $last_attr = $this->base_attr_cell; - for ($i = 0; $i < count($this->history); $i++) { - for ($j = 0; $j <= $this->max_x + 1; $j++) { - $cur_attr = $this->history_attrs[$i][$j]; - $scrollback.= $this->processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : ''); - $last_attr = $this->history_attrs[$i][$j]; - } - $scrollback.= "\r\n"; - } - $base_attr_cell = $this->base_attr_cell; - $this->base_attr_cell = $last_attr; - $scrollback.= $this->getScreen(); - $this->base_attr_cell = $base_attr_cell; - - return '
' . $scrollback . '
'; - } -} diff --git a/lib/phpaes/phpseclib/File/ASN1.php b/lib/phpaes/phpseclib/File/ASN1.php deleted file mode 100644 index 295a2b721f..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1.php +++ /dev/null @@ -1,1414 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\File\ASN1\Element; -use phpseclib\Math\BigInteger; - -/** - * Pure-PHP ASN.1 Parser - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class ASN1 -{ - /**#@+ - * Tag Classes - * - * @access private - * @link http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12 - */ - const CLASS_UNIVERSAL = 0; - const CLASS_APPLICATION = 1; - const CLASS_CONTEXT_SPECIFIC = 2; - const CLASS_PRIVATE = 3; - /**#@-*/ - - /**#@+ - * Tag Classes - * - * @access private - * @link http://www.obj-sys.com/asn1tutorial/node124.html - */ - const TYPE_BOOLEAN = 1; - const TYPE_INTEGER = 2; - const TYPE_BIT_STRING = 3; - const TYPE_OCTET_STRING = 4; - const TYPE_NULL = 5; - const TYPE_OBJECT_IDENTIFIER = 6; - //const TYPE_OBJECT_DESCRIPTOR = 7; - //const TYPE_INSTANCE_OF = 8; // EXTERNAL - const TYPE_REAL = 9; - const TYPE_ENUMERATED = 10; - //const TYPE_EMBEDDED = 11; - const TYPE_UTF8_STRING = 12; - //const TYPE_RELATIVE_OID = 13; - const TYPE_SEQUENCE = 16; // SEQUENCE OF - const TYPE_SET = 17; // SET OF - /**#@-*/ - /**#@+ - * More Tag Classes - * - * @access private - * @link http://www.obj-sys.com/asn1tutorial/node10.html - */ - const TYPE_NUMERIC_STRING = 18; - const TYPE_PRINTABLE_STRING = 19; - const TYPE_TELETEX_STRING = 20; // T61String - const TYPE_VIDEOTEX_STRING = 21; - const TYPE_IA5_STRING = 22; - const TYPE_UTC_TIME = 23; - const TYPE_GENERALIZED_TIME = 24; - const TYPE_GRAPHIC_STRING = 25; - const TYPE_VISIBLE_STRING = 26; // ISO646String - const TYPE_GENERAL_STRING = 27; - const TYPE_UNIVERSAL_STRING = 28; - //const TYPE_CHARACTER_STRING = 29; - const TYPE_BMP_STRING = 30; - /**#@-*/ - - /**#@+ - * Tag Aliases - * - * These tags are kinda place holders for other tags. - * - * @access private - */ - const TYPE_CHOICE = -1; - const TYPE_ANY = -2; - /**#@-*/ - - /** - * ASN.1 object identifiers - * - * @var array - * @access private - * @link http://en.wikipedia.org/wiki/Object_identifier - */ - private static $oids = []; - - /** - * ASN.1 object identifier reverse mapping - * - * @var array - * @access private - */ - private static $reverseOIDs = []; - - /** - * Default date format - * - * @var string - * @access private - * @link http://php.net/class.datetime - */ - private static $format = 'D, d M Y H:i:s O'; - - /** - * Filters - * - * If the mapping type is self::TYPE_ANY what do we actually encode it as? - * - * @var array - * @access private - * @see self::encode_der() - */ - private static $filters; - - /** - * Current Location of most recent ASN.1 encode process - * - * Useful for debug purposes - * - * @var array - * @access private - * @see self::encode_der() - */ - private static $location; - - /** - * DER Encoded String - * - * In case we need to create ASN1\Element object's.. - * - * @var string - * @access private - * @see self::decodeDER() - */ - private static $encoded; - - /** - * Type mapping table for the ANY type. - * - * Structured or unknown types are mapped to a \phpseclib\File\ASN1\Element. - * Unambiguous types get the direct mapping (int/real/bool). - * Others are mapped as a choice, with an extra indexing level. - * - * @var array - * @access public - */ - const ANY_MAP = [ - self::TYPE_BOOLEAN => true, - self::TYPE_INTEGER => true, - self::TYPE_BIT_STRING => 'bitString', - self::TYPE_OCTET_STRING => 'octetString', - self::TYPE_NULL => 'null', - self::TYPE_OBJECT_IDENTIFIER => 'objectIdentifier', - self::TYPE_REAL => true, - self::TYPE_ENUMERATED => 'enumerated', - self::TYPE_UTF8_STRING => 'utf8String', - self::TYPE_NUMERIC_STRING => 'numericString', - self::TYPE_PRINTABLE_STRING => 'printableString', - self::TYPE_TELETEX_STRING => 'teletexString', - self::TYPE_VIDEOTEX_STRING => 'videotexString', - self::TYPE_IA5_STRING => 'ia5String', - self::TYPE_UTC_TIME => 'utcTime', - self::TYPE_GENERALIZED_TIME => 'generalTime', - self::TYPE_GRAPHIC_STRING => 'graphicString', - self::TYPE_VISIBLE_STRING => 'visibleString', - self::TYPE_GENERAL_STRING => 'generalString', - self::TYPE_UNIVERSAL_STRING => 'universalString', - //self::TYPE_CHARACTER_STRING => 'characterString', - self::TYPE_BMP_STRING => 'bmpString' - ]; - - /** - * String type to character size mapping table. - * - * Non-convertable types are absent from this table. - * size == 0 indicates variable length encoding. - * - * @var array - * @access public - */ - const STRING_TYPE_SIZE = [ - self::TYPE_UTF8_STRING => 0, - self::TYPE_BMP_STRING => 2, - self::TYPE_UNIVERSAL_STRING => 4, - self::TYPE_PRINTABLE_STRING => 1, - self::TYPE_TELETEX_STRING => 1, - self::TYPE_IA5_STRING => 1, - self::TYPE_VISIBLE_STRING => 1, - ]; - - /** - * Parse BER-encoding - * - * Serves a similar purpose to openssl's asn1parse - * - * @param string $encoded - * @return array - * @access public - */ - public static function decodeBER($encoded) - { - if ($encoded instanceof Element) { - $encoded = $encoded->element; - } - - self::$encoded = $encoded; - - $decoded = [self::decode_ber($encoded)]; - - // encapsulate in an array for BC with the old decodeBER - return $decoded; - } - - /** - * Parse BER-encoding (Helper function) - * - * Sometimes we want to get the BER encoding of a particular tag. $start lets us do that without having to reencode. - * $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and - * self::TYPE_OCTET_STRING. In those cases, the indefinite length is used. - * - * @param string $encoded - * @param int $start - * @param int $encoded_pos - * @return array - * @access private - */ - private static function decode_ber($encoded, $start = 0, $encoded_pos = 0) - { - $current = ['start' => $start]; - - $type = ord($encoded[$encoded_pos++]); - $start++; - - $constructed = ($type >> 5) & 1; - - $tag = $type & 0x1F; - if ($tag == 0x1F) { - $tag = 0; - // process septets (since the eighth bit is ignored, it's not an octet) - do { - $loop = ord($encoded[0]) >> 7; - $tag <<= 7; - $tag |= ord($encoded[$encoded_pos++]) & 0x7F; - $start++; - } while ($loop); - } - - // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13 - $length = ord($encoded[$encoded_pos++]); - $start++; - if ($length == 0x80) { // indefinite length - // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all - // immediately available." -- paragraph 8.1.3.2.c - $length = strlen($encoded) - $encoded_pos; - } elseif ($length & 0x80) { // definite length, long form - // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only - // support it up to four. - $length&= 0x7F; - $temp = substr($encoded, $encoded_pos, $length); - $encoded_pos += $length; - // tags of indefinte length don't really have a header length; this length includes the tag - $current+= ['headerlength' => $length + 2]; - $start+= $length; - extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4))); - } else { - $current+= ['headerlength' => 2]; - } - - if ($length > (strlen($encoded) - $encoded_pos)) { - return false; - } - - $content = substr($encoded, $encoded_pos, $length); - $content_pos = 0; - - // at this point $length can be overwritten. it's only accurate for definite length things as is - - /* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1 - built-in types. It defines an application-independent data type that must be distinguishable from all other - data types. The other three classes are user defined. The APPLICATION class distinguishes data types that - have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within - a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the - alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this - data type; the term CONTEXT-SPECIFIC does not appear. - - -- http://www.obj-sys.com/asn1tutorial/node12.html */ - $class = ($type >> 6) & 3; - switch ($class) { - case self::CLASS_APPLICATION: - case self::CLASS_PRIVATE: - case self::CLASS_CONTEXT_SPECIFIC: - if (!$constructed) { - return [ - 'type' => $class, - 'constant' => $tag, - 'content' => $content, - 'length' => $length + $start - $current['start'] - ] + $current; - } - - $newcontent = []; - $remainingLength = $length; - while ($remainingLength > 0) { - $temp = self::decode_ber($content, $start, $content_pos); - $length = $temp['length']; - // end-of-content octets - see paragraph 8.1.5 - if (substr($content, $content_pos + $length, 2) == "\0\0") { - $length+= 2; - $start+= $length; - $newcontent[] = $temp; - break; - } - $start+= $length; - $remainingLength-= $length; - $newcontent[] = $temp; - $content_pos += $length; - } - - return [ - 'type' => $class, - 'constant' => $tag, - // the array encapsulation is for BC with the old format - 'content' => $newcontent, - // the only time when $content['headerlength'] isn't defined is when the length is indefinite. - // the absence of $content['headerlength'] is how we know if something is indefinite or not. - // technically, it could be defined to be 2 and then another indicator could be used but whatever. - 'length' => $start - $current['start'] - ] + $current; - } - - $current+= ['type' => $tag]; - - // decode UNIVERSAL tags - switch ($tag) { - case self::TYPE_BOOLEAN: - // "The contents octets shall consist of a single octet." -- paragraph 8.2.1 - //if (strlen($content) != 1) { - // return false; - //} - $current['content'] = (bool) ord($content[$content_pos]); - break; - case self::TYPE_INTEGER: - case self::TYPE_ENUMERATED: - $current['content'] = new BigInteger(substr($content, $content_pos), -256); - break; - case self::TYPE_REAL: // not currently supported - return false; - case self::TYPE_BIT_STRING: - // The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit, - // the number of unused bits in the final subsequent octet. The number shall be in the range zero to - // seven. - if (!$constructed) { - $current['content'] = substr($content, $content_pos); - } else { - $temp = self::decode_ber($content, $start, $content_pos); - $length-= (strlen($content) - $content_pos); - $last = count($temp) - 1; - for ($i = 0; $i < $last; $i++) { - // all subtags should be bit strings - //if ($temp[$i]['type'] != self::TYPE_BIT_STRING) { - // return false; - //} - $current['content'].= substr($temp[$i]['content'], 1); - } - // all subtags should be bit strings - //if ($temp[$last]['type'] != self::TYPE_BIT_STRING) { - // return false; - //} - $current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1); - } - break; - case self::TYPE_OCTET_STRING: - if (!$constructed) { - $current['content'] = substr($content, $content_pos); - } else { - $current['content'] = ''; - $length = 0; - while (substr($content, $content_pos, 2) != "\0\0") { - $temp = self::decode_ber($content, $length + $start, $content_pos); - $content_pos += $temp['length']; - // all subtags should be octet strings - //if ($temp['type'] != self::TYPE_OCTET_STRING) { - // return false; - //} - $current['content'].= $temp['content']; - $length+= $temp['length']; - } - if (substr($content, $content_pos, 2) == "\0\0") { - $length+= 2; // +2 for the EOC - } - } - break; - case self::TYPE_NULL: - // "The contents octets shall not contain any octets." -- paragraph 8.8.2 - //if (strlen($content)) { - // return false; - //} - break; - case self::TYPE_SEQUENCE: - case self::TYPE_SET: - $offset = 0; - $current['content'] = []; - $content_len = strlen($content); - while ($content_pos < $content_len) { - // if indefinite length construction was used and we have an end-of-content string next - // see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2 - if (!isset($current['headerlength']) && substr($content, $content_pos, 2) == "\0\0") { - $length = $offset + 2; // +2 for the EOC - break 2; - } - $temp = self::decode_ber($content, $start + $offset, $content_pos); - $content_pos += $temp['length']; - $current['content'][] = $temp; - $offset+= $temp['length']; - } - break; - case self::TYPE_OBJECT_IDENTIFIER: - $temp = ord($content[$content_pos++]); - $current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40); - $valuen = 0; - // process septets - $content_len = strlen($content); - while ($content_pos < $content_len) { - $temp = ord($content[$content_pos++]); - $valuen <<= 7; - $valuen |= $temp & 0x7F; - if (~$temp & 0x80) { - $current['content'].= ".$valuen"; - $valuen = 0; - } - } - // the eighth bit of the last byte should not be 1 - //if ($temp >> 7) { - // return false; - //} - break; - /* Each character string type shall be encoded as if it had been declared: - [UNIVERSAL x] IMPLICIT OCTET STRING - - -- X.690-0207.pdf#page=23 (paragraph 8.21.3) - - Per that, we're not going to do any validation. If there are any illegal characters in the string, - we don't really care */ - case self::TYPE_NUMERIC_STRING: - // 0,1,2,3,4,5,6,7,8,9, and space - case self::TYPE_PRINTABLE_STRING: - // Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma, - // hyphen, full stop, solidus, colon, equal sign, question mark - case self::TYPE_TELETEX_STRING: - // The Teletex character set in CCITT's T61, space, and delete - // see http://en.wikipedia.org/wiki/Teletex#Character_sets - case self::TYPE_VIDEOTEX_STRING: - // The Videotex character set in CCITT's T.100 and T.101, space, and delete - case self::TYPE_VISIBLE_STRING: - // Printing character sets of international ASCII, and space - case self::TYPE_IA5_STRING: - // International Alphabet 5 (International ASCII) - case self::TYPE_GRAPHIC_STRING: - // All registered G sets, and space - case self::TYPE_GENERAL_STRING: - // All registered C and G sets, space and delete - case self::TYPE_UTF8_STRING: - // ???? - case self::TYPE_BMP_STRING: - $current['content'] = substr($content, $content_pos); - break; - case self::TYPE_UTC_TIME: - case self::TYPE_GENERALIZED_TIME: - $current['content'] = self::decodeTime(substr($content, $content_pos), $tag); - default: - } - - $start+= $length; - - // ie. length is the length of the full TLV encoding - it's not just the length of the value - return $current + ['length' => $start - $current['start']]; - } - - /** - * ASN.1 Map - * - * Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format. - * - * "Special" mappings may be applied on a per tag-name basis via $special. - * - * @param array $decoded - * @param array $mapping - * @param array $special - * @return array - * @access public - */ - public static function asn1map($decoded, $mapping, $special = []) - { - if (isset($mapping['explicit']) && is_array($decoded['content'])) { - $decoded = $decoded['content'][0]; - } - - switch (true) { - case $mapping['type'] == self::TYPE_ANY: - $intype = $decoded['type']; - // !isset(self::ANY_MAP[$intype]) produces a fatal error on PHP 5.6 - if (isset($decoded['constant']) || !array_key_exists($intype, self::ANY_MAP) || (ord(self::$encoded[$decoded['start']]) & 0x20)) { - return new Element(substr(self::$encoded, $decoded['start'], $decoded['length'])); - } - $inmap = self::ANY_MAP[$intype]; - if (is_string($inmap)) { - return [$inmap => self::asn1map($decoded, ['type' => $intype] + $mapping, $special)]; - } - break; - case $mapping['type'] == self::TYPE_CHOICE: - foreach ($mapping['children'] as $key => $option) { - switch (true) { - case isset($option['constant']) && $option['constant'] == $decoded['constant']: - case !isset($option['constant']) && $option['type'] == $decoded['type']: - $value = self::asn1map($decoded, $option, $special); - break; - case !isset($option['constant']) && $option['type'] == self::TYPE_CHOICE: - $v = self::asn1map($decoded, $option, $special); - if (isset($v)) { - $value = $v; - } - } - if (isset($value)) { - if (isset($special[$key])) { - $value = call_user_func($special[$key], $value); - } - return [$key => $value]; - } - } - return null; - case isset($mapping['implicit']): - case isset($mapping['explicit']): - case $decoded['type'] == $mapping['type']: - break; - default: - // if $decoded['type'] and $mapping['type'] are both strings, but different types of strings, - // let it through - switch (true) { - case $decoded['type'] < 18: // self::TYPE_NUMERIC_STRING == 18 - case $decoded['type'] > 30: // self::TYPE_BMP_STRING == 30 - case $mapping['type'] < 18: - case $mapping['type'] > 30: - return null; - } - } - - if (isset($mapping['implicit'])) { - $decoded['type'] = $mapping['type']; - } - - switch ($decoded['type']) { - case self::TYPE_SEQUENCE: - $map = []; - - // ignore the min and max - if (isset($mapping['min']) && isset($mapping['max'])) { - $child = $mapping['children']; - foreach ($decoded['content'] as $content) { - if (($map[] = self::asn1map($content, $child, $special)) === null) { - return null; - } - } - - return $map; - } - - $n = count($decoded['content']); - $i = 0; - - foreach ($mapping['children'] as $key => $child) { - $maymatch = $i < $n; // Match only existing input. - if ($maymatch) { - $temp = $decoded['content'][$i]; - - if ($child['type'] != self::TYPE_CHOICE) { - // Get the mapping and input class & constant. - $childClass = $tempClass = self::CLASS_UNIVERSAL; - $constant = null; - if (isset($temp['constant'])) { - $tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC; - } - if (isset($child['class'])) { - $childClass = $child['class']; - $constant = $child['cast']; - } elseif (isset($child['constant'])) { - $childClass = self::CLASS_CONTEXT_SPECIFIC; - $constant = $child['constant']; - } - - if (isset($constant) && isset($temp['constant'])) { - // Can only match if constants and class match. - $maymatch = $constant == $temp['constant'] && $childClass == $tempClass; - } else { - // Can only match if no constant expected and type matches or is generic. - $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false; - } - } - } - - if ($maymatch) { - // Attempt submapping. - $candidate = self::asn1map($temp, $child, $special); - $maymatch = $candidate !== null; - } - - if ($maymatch) { - // Got the match: use it. - if (isset($special[$key])) { - $candidate = call_user_func($special[$key], $candidate); - } - $map[$key] = $candidate; - $i++; - } elseif (isset($child['default'])) { - switch ($child['type']) { - case ASN1::TYPE_INTEGER: - $map[$key] = new BigInteger($child['default']); - break; - //case ASN1::TYPE_BOOLEAN: - default: - $map[$key] = $child['type']; - } - } elseif (!isset($child['optional'])) { - return null; // Syntax error. - } - } - - // Fail mapping if all input items have not been consumed. - return $i < $n ? null: $map; - - // the main diff between sets and sequences is the encapsulation of the foreach in another for loop - case self::TYPE_SET: - $map = []; - - // ignore the min and max - if (isset($mapping['min']) && isset($mapping['max'])) { - $child = $mapping['children']; - foreach ($decoded['content'] as $content) { - if (($map[] = self::asn1map($content, $child, $special)) === null) { - return null; - } - } - - return $map; - } - - for ($i = 0; $i < count($decoded['content']); $i++) { - $temp = $decoded['content'][$i]; - $tempClass = self::CLASS_UNIVERSAL; - if (isset($temp['constant'])) { - $tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC; - } - - foreach ($mapping['children'] as $key => $child) { - if (isset($map[$key])) { - continue; - } - $maymatch = true; - if ($child['type'] != self::TYPE_CHOICE) { - $childClass = self::CLASS_UNIVERSAL; - $constant = null; - if (isset($child['class'])) { - $childClass = $child['class']; - $constant = $child['cast']; - } elseif (isset($child['constant'])) { - $childClass = self::CLASS_CONTEXT_SPECIFIC; - $constant = $child['constant']; - } - - if (isset($constant) && isset($temp['constant'])) { - // Can only match if constants and class match. - $maymatch = $constant == $temp['constant'] && $childClass == $tempClass; - } else { - // Can only match if no constant expected and type matches or is generic. - $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false; - } - } - - if ($maymatch) { - // Attempt submapping. - $candidate = self::asn1map($temp, $child, $special); - $maymatch = $candidate !== null; - } - - if (!$maymatch) { - break; - } - - // Got the match: use it. - if (isset($special[$key])) { - $candidate = call_user_func($special[$key], $candidate); - } - $map[$key] = $candidate; - break; - } - } - - foreach ($mapping['children'] as $key => $child) { - if (!isset($map[$key])) { - if (isset($child['default'])) { - $map[$key] = $child['default']; - } elseif (!isset($child['optional'])) { - return null; - } - } - } - return $map; - case self::TYPE_OBJECT_IDENTIFIER: - return isset(self::$oids[$decoded['content']]) ? self::$oids[$decoded['content']] : $decoded['content']; - case self::TYPE_UTC_TIME: - case self::TYPE_GENERALIZED_TIME: - if (isset($mapping['implicit'])) { - $decoded['content'] = self::decodeTime($decoded['content'], $decoded['type']); - } - return @date(self::$format, $decoded['content']); - case self::TYPE_BIT_STRING: - if (isset($mapping['mapping'])) { - $offset = ord($decoded['content'][0]); - $size = (strlen($decoded['content']) - 1) * 8 - $offset; - /* - From X.680-0207.pdf#page=46 (21.7): - - "When a "NamedBitList" is used in defining a bitstring type ASN.1 encoding rules are free to add (or remove) - arbitrarily any trailing 0 bits to (or from) values that are being encoded or decoded. Application designers should - therefore ensure that different semantics are not associated with such values which differ only in the number of trailing - 0 bits." - */ - $bits = count($mapping['mapping']) == $size ? [] : array_fill(0, count($mapping['mapping']) - $size, false); - for ($i = strlen($decoded['content']) - 1; $i > 0; $i--) { - $current = ord($decoded['content'][$i]); - for ($j = $offset; $j < 8; $j++) { - $bits[] = (bool) ($current & (1 << $j)); - } - $offset = 0; - } - $values = []; - $map = array_reverse($mapping['mapping']); - foreach ($map as $i => $value) { - if ($bits[$i]) { - $values[] = $value; - } - } - return $values; - } - case self::TYPE_OCTET_STRING: - return $decoded['content']; - case self::TYPE_NULL: - return ''; - case self::TYPE_BOOLEAN: - return $decoded['content']; - case self::TYPE_NUMERIC_STRING: - case self::TYPE_PRINTABLE_STRING: - case self::TYPE_TELETEX_STRING: - case self::TYPE_VIDEOTEX_STRING: - case self::TYPE_IA5_STRING: - case self::TYPE_GRAPHIC_STRING: - case self::TYPE_VISIBLE_STRING: - case self::TYPE_GENERAL_STRING: - case self::TYPE_UNIVERSAL_STRING: - case self::TYPE_UTF8_STRING: - case self::TYPE_BMP_STRING: - return $decoded['content']; - case self::TYPE_INTEGER: - case self::TYPE_ENUMERATED: - $temp = $decoded['content']; - if (isset($mapping['implicit'])) { - $temp = new BigInteger($decoded['content'], -256); - } - if (isset($mapping['mapping'])) { - $temp = (int) $temp->toString(); - return isset($mapping['mapping'][$temp]) ? - $mapping['mapping'][$temp] : - false; - } - return $temp; - } - } - - /** - * ASN.1 Encode - * - * DER-encodes an ASN.1 semantic mapping ($mapping). Some libraries would probably call this function - * an ASN.1 compiler. - * - * "Special" mappings can be applied via $special. - * - * @param string $source - * @param string $mapping - * @param int $idx - * @return string - * @access public - */ - public static function encodeDER($source, $mapping, $special = []) - { - self::$location = []; - return self::encode_der($source, $mapping, null, $special); - } - - /** - * ASN.1 Encode (Helper function) - * - * @param string $source - * @param string $mapping - * @param int $idx - * @return string - * @throws \RuntimeException if the input has an error in it - * @access private - */ - private static function encode_der($source, $mapping, $idx = null, $special = []) - { - if ($source instanceof Element) { - return $source->element; - } - - // do not encode (implicitly optional) fields with value set to default - if (isset($mapping['default']) && $source === $mapping['default']) { - return ''; - } - - if (isset($idx)) { - if (isset($special[$idx])) { - $source = call_user_func($special[$idx], $source); - } - self::$location[] = $idx; - } - - $tag = $mapping['type']; - - switch ($tag) { - case self::TYPE_SET: // Children order is not important, thus process in sequence. - case self::TYPE_SEQUENCE: - $tag|= 0x20; // set the constructed bit - - // ignore the min and max - if (isset($mapping['min']) && isset($mapping['max'])) { - $value = []; - $child = $mapping['children']; - - foreach ($source as $content) { - $temp = self::encode_der($content, $child, null, $special); - if ($temp === false) { - return false; - } - $value[]= $temp; - } - /* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared - as octet strings with the shorter components being padded at their trailing end with 0-octets. - NOTE - The padding octets are for comparison purposes only and do not appear in the encodings." - - -- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ - if ($mapping['type'] == self::TYPE_SET) { - sort($value); - } - $value = implode($value, ''); - break; - } - - $value = ''; - foreach ($mapping['children'] as $key => $child) { - if (!array_key_exists($key, $source)) { - if (!isset($child['optional'])) { - return false; - } - continue; - } - - $temp = self::encode_der($source[$key], $child, $key, $special); - if ($temp === false) { - return false; - } - - // An empty child encoding means it has been optimized out. - // Else we should have at least one tag byte. - if ($temp === '') { - continue; - } - - // if isset($child['constant']) is true then isset($child['optional']) should be true as well - if (isset($child['constant'])) { - /* - From X.680-0207.pdf#page=58 (30.6): - - "The tagging construction specifies explicit tagging if any of the following holds: - ... - c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or - AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or - an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)." - */ - if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']); - $temp = $subtag . self::encodeLength(strlen($temp)) . $temp; - } else { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']); - $temp = $subtag . substr($temp, 1); - } - } - $value.= $temp; - } - break; - case self::TYPE_CHOICE: - $temp = false; - - foreach ($mapping['children'] as $key => $child) { - if (!isset($source[$key])) { - continue; - } - - $temp = self::encode_der($source[$key], $child, $key, $special); - if ($temp === false) { - return false; - } - - // An empty child encoding means it has been optimized out. - // Else we should have at least one tag byte. - if ($temp === '') { - continue; - } - - $tag = ord($temp[0]); - - // if isset($child['constant']) is true then isset($child['optional']) should be true as well - if (isset($child['constant'])) { - if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']); - $temp = $subtag . self::encodeLength(strlen($temp)) . $temp; - } else { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']); - $temp = $subtag . substr($temp, 1); - } - } - } - - if (isset($idx)) { - array_pop(self::$location); - } - - if ($temp && isset($mapping['cast'])) { - $temp[0] = chr(($mapping['class'] << 6) | ($tag & 0x20) | $mapping['cast']); - } - - return $temp; - case self::TYPE_INTEGER: - case self::TYPE_ENUMERATED: - if (!isset($mapping['mapping'])) { - if (is_numeric($source)) { - $source = new BigInteger($source); - } - $value = $source->toBytes(true); - } else { - $value = array_search($source, $mapping['mapping']); - if ($value === false) { - return false; - } - $value = new BigInteger($value); - $value = $value->toBytes(true); - } - if (!strlen($value)) { - $value = chr(0); - } - break; - case self::TYPE_UTC_TIME: - case self::TYPE_GENERALIZED_TIME: - $format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y'; - $format.= 'mdHis'; - $value = @gmdate($format, strtotime($source)) . 'Z'; - break; - case self::TYPE_BIT_STRING: - if (isset($mapping['mapping'])) { - $bits = array_fill(0, count($mapping['mapping']), 0); - $size = 0; - for ($i = 0; $i < count($mapping['mapping']); $i++) { - if (in_array($mapping['mapping'][$i], $source)) { - $bits[$i] = 1; - $size = $i; - } - } - - if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) { - $size = $mapping['min'] - 1; - } - - $offset = 8 - (($size + 1) & 7); - $offset = $offset !== 8 ? $offset : 0; - - $value = chr($offset); - - for ($i = $size + 1; $i < count($mapping['mapping']); $i++) { - unset($bits[$i]); - } - - $bits = implode('', array_pad($bits, $size + $offset + 1, 0)); - $bytes = explode(' ', rtrim(chunk_split($bits, 8, ' '))); - foreach ($bytes as $byte) { - $value.= chr(bindec($byte)); - } - - break; - } - case self::TYPE_OCTET_STRING: - /* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit, - the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven. - - -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */ - $value = $source; - break; - case self::TYPE_OBJECT_IDENTIFIER: - if (!preg_match('#(?:\d+\.)+#', $source)) { - $oid = isset(self::$reverseOIDs[$source]) ? self::$reverseOIDs[$source] : false; - } else { - $oid = $source; - } - if ($oid === false) { - throw new \RuntimeException('Invalid OID'); - } - $value = ''; - $parts = explode('.', $oid); - $value = chr(40 * $parts[0] + $parts[1]); - for ($i = 2; $i < count($parts); $i++) { - $temp = ''; - if (!$parts[$i]) { - $temp = "\0"; - } else { - while ($parts[$i]) { - $temp = chr(0x80 | ($parts[$i] & 0x7F)) . $temp; - $parts[$i] >>= 7; - } - $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F); - } - $value.= $temp; - } - break; - case self::TYPE_ANY: - $loc = self::$location; - if (isset($idx)) { - array_pop(self::$location); - } - - switch (true) { - case !isset($source): - return self::encode_der(null, ['type' => self::TYPE_NULL] + $mapping, null, $special); - case is_int($source): - case $source instanceof BigInteger: - return self::encode_der($source, ['type' => self::TYPE_INTEGER] + $mapping, null, $special); - case is_float($source): - return self::encode_der($source, ['type' => self::TYPE_REAL] + $mapping, null, $special); - case is_bool($source): - return self::encode_der($source, ['type' => self::TYPE_BOOLEAN] + $mapping, null, $special); - case is_array($source) && count($source) == 1: - $typename = implode('', array_keys($source)); - $outtype = array_search($typename, self::ANY_MAP, true); - if ($outtype !== false) { - return self::encode_der($source[$typename], ['type' => $outtype] + $mapping, null, $special); - } - } - - $filters = self::$filters; - foreach ($loc as $part) { - if (!isset($filters[$part])) { - $filters = false; - break; - } - $filters = $filters[$part]; - } - if ($filters === false) { - throw new \RuntimeException('No filters defined for ' . implode('/', $loc)); - } - return self::encode_der($source, $filters + $mapping, null, $special); - case self::TYPE_NULL: - $value = ''; - break; - case self::TYPE_NUMERIC_STRING: - case self::TYPE_TELETEX_STRING: - case self::TYPE_PRINTABLE_STRING: - case self::TYPE_UNIVERSAL_STRING: - case self::TYPE_UTF8_STRING: - case self::TYPE_BMP_STRING: - case self::TYPE_IA5_STRING: - case self::TYPE_VISIBLE_STRING: - case self::TYPE_VIDEOTEX_STRING: - case self::TYPE_GRAPHIC_STRING: - case self::TYPE_GENERAL_STRING: - $value = $source; - break; - case self::TYPE_BOOLEAN: - $value = $source ? "\xFF" : "\x00"; - break; - default: - throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', self::$location)); - } - - if (isset($idx)) { - array_pop(self::$location); - } - - if (isset($mapping['cast'])) { - if (isset($mapping['explicit']) || $mapping['type'] == self::TYPE_CHOICE) { - $value = chr($tag) . self::encodeLength(strlen($value)) . $value; - $tag = ($mapping['class'] << 6) | 0x20 | $mapping['cast']; - } else { - $tag = ($mapping['class'] << 6) | (ord($temp[0]) & 0x20) | $mapping['cast']; - } - } - - return chr($tag) . self::encodeLength(strlen($value)) . $value; - } - - /** - * BER-decode the time - * - * Called by _decode_ber() and in the case of implicit tags asn1map(). - * - * @access private - * @param string $content - * @param int $tag - * @return string - */ - private static function decodeTime($content, $tag) - { - /* UTCTime: - http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 - http://www.obj-sys.com/asn1tutorial/node15.html - - GeneralizedTime: - http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2 - http://www.obj-sys.com/asn1tutorial/node14.html */ - - $pattern = $tag == self::TYPE_UTC_TIME ? - '#^(..)(..)(..)(..)(..)(..)?(.*)$#' : - '#(....)(..)(..)(..)(..)(..).*([Z+-].*)$#'; - - preg_match($pattern, $content, $matches); - - list(, $year, $month, $day, $hour, $minute, $second, $timezone) = $matches; - - if ($tag == self::TYPE_UTC_TIME) { - $year = $year >= 50 ? "19$year" : "20$year"; - } - - if ($timezone == 'Z') { - $mktime = 'gmmktime'; - $timezone = 0; - } elseif (preg_match('#([+-])(\d\d)(\d\d)#', $timezone, $matches)) { - $mktime = 'gmmktime'; - $timezone = 60 * $matches[3] + 3600 * $matches[2]; - if ($matches[1] == '-') { - $timezone = -$timezone; - } - } else { - $mktime = 'mktime'; - $timezone = 0; - } - - return @$mktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year) + $timezone; - } - - /** - * Set the time format - * - * Sets the time / date format for asn1map(). - * - * @access public - * @param string $format - */ - public static function setTimeFormat($format) - { - self::$format = $format; - } - - /** - * Load OIDs - * - * Load the relevant OIDs for a particular ASN.1 semantic mapping. - * Previously loaded OIDs are retained. - * - * @access public - * @param array $oids - */ - public static function loadOIDs($oids) - { - self::$oids+= $oids; - self::$reverseOIDs = array_flip(self::$oids); - } - - /** - * Set filters - * - * See \phpseclib\File\X509, etc, for an example. - * Previously loaded filters are not retained. - * - * @access public - * @param array $filters - */ - public static function setFilters($filters) - { - self::$filters = $filters; - } - - /** - * String type conversion - * - * This is a lazy conversion, dealing only with character size. - * No real conversion table is used. - * - * @param string $in - * @param int $from - * @param int $to - * @return string - * @access public - */ - public static function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING) - { - // isset(self::STRING_TYPE_SIZE[$from] returns a fatal error on PHP 5.6 - if (!array_key_exists($from, self::STRING_TYPE_SIZE) || !array_key_exists($to, self::STRING_TYPE_SIZE)) { - return false; - } - $insize = self::STRING_TYPE_SIZE[$from]; - $outsize = self::STRING_TYPE_SIZE[$to]; - $inlength = strlen($in); - $out = ''; - - for ($i = 0; $i < $inlength;) { - if ($inlength - $i < $insize) { - return false; - } - - // Get an input character as a 32-bit value. - $c = ord($in[$i++]); - switch (true) { - case $insize == 4: - $c = ($c << 8) | ord($in[$i++]); - $c = ($c << 8) | ord($in[$i++]); - case $insize == 2: - $c = ($c << 8) | ord($in[$i++]); - case $insize == 1: - break; - case ($c & 0x80) == 0x00: - break; - case ($c & 0x40) == 0x00: - return false; - default: - $bit = 6; - do { - if ($bit > 25 || $i >= $inlength || (ord($in[$i]) & 0xC0) != 0x80) { - return false; - } - $c = ($c << 6) | (ord($in[$i++]) & 0x3F); - $bit += 5; - $mask = 1 << $bit; - } while ($c & $bit); - $c &= $mask - 1; - break; - } - - // Convert and append the character to output string. - $v = ''; - switch (true) { - case $outsize == 4: - $v .= chr($c & 0xFF); - $c >>= 8; - $v .= chr($c & 0xFF); - $c >>= 8; - case $outsize == 2: - $v .= chr($c & 0xFF); - $c >>= 8; - case $outsize == 1: - $v .= chr($c & 0xFF); - $c >>= 8; - if ($c) { - return false; - } - break; - case ($c & 0x80000000) != 0: - return false; - case $c >= 0x04000000: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x04000000; - case $c >= 0x00200000: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x00200000; - case $c >= 0x00010000: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x00010000; - case $c >= 0x00000800: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x00000800; - case $c >= 0x00000080: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x000000C0; - default: - $v .= chr($c); - break; - } - $out .= strrev($v); - } - return $out; - } - - /** - * Extract raw BER from Base64 encoding - * - * @access private - * @param string $str - * @return string - */ - public static function extractBER($str) - { - /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them - * above and beyond the ceritificate. - * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: - * - * Bag Attributes - * localKeyID: 01 00 00 00 - * subject=/O=organization/OU=org unit/CN=common name - * issuer=/O=organization/CN=common name - */ - $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); - // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff - $temp = preg_replace('#-+[^-]+-+#', '', $temp); - // remove new lines - $temp = str_replace(["\r", "\n", ' '], '', $temp); - $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false; - return $temp != false ? $temp : $str; - } - - /** - * DER-decode 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 paragraph 8.1.3} for more information. - * - * @access public - * @param string $string - * @return int - */ - public static function decodeLength(&$string) - { - $length = ord(Strings::shift($string)); - if ($length & 0x80) { // definite length, long form - $length&= 0x7F; - $temp = Strings::shift($string, $length); - list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); - } - return $length; - } - - /** - * 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 paragraph 8.1.3} for more information. - * - * @access public - * @param int $length - * @return string - */ - public static function encodeLength($length) - { - if ($length <= 0x7F) { - return chr($length); - } - - $temp = ltrim(pack('N', $length), chr(0)); - return pack('Ca*', 0x80 | strlen($temp), $temp); - } - - /** - * Returns the OID corresponding to a name - * - * What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if - * no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version - * of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able - * to work from version to version. - * - * This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that - * what's being passed to it already is an OID and return that instead. A few examples. - * - * getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1' - * getOID('id-sha256') == '2.16.840.1.101.3.4.2.1' - * getOID('zzz') == 'zzz' - * - * @access public - * @return string - */ - static function getOID($name) - { - return isset(self::$reverseOIDs[$name]) ? self::$reverseOIDs[$name] : $name; - } -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Element.php b/lib/phpaes/phpseclib/File/ASN1/Element.php deleted file mode 100644 index 048104e601..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Element.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1; - -/** - * ASN.1 Raw Element - * - * An ASN.1 ANY mapping will return an ASN1\Element object. Use of this object - * will also bypass the normal encoding rules in ASN1::encodeDER() - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -class Element -{ - /** - * Raw element value - * - * @var string - * @access private - */ - public $element; - - /** - * Constructor - * - * @param string $encoded - * @return \phpseclib\File\ASN1\Element - * @access public - */ - public function __construct($encoded) - { - $this->element = $encoded; - } -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AccessDescription.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AccessDescription.php deleted file mode 100644 index 4e1d91b115..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AccessDescription.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AccessDescription - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AccessDescription -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'accessMethod' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'accessLocation' => GeneralName::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AdministrationDomainName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AdministrationDomainName.php deleted file mode 100644 index 911ed13050..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AdministrationDomainName.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AdministrationDomainName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AdministrationDomainName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - // if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or - // (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC - 'class' => ASN1::CLASS_APPLICATION, - 'cast' => 2, - 'children' => [ - 'numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], - 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php deleted file mode 100644 index f2ed617c1f..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AlgorithmIdentifier - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AlgorithmIdentifier -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'algorithm' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'parameters' => [ - 'type' => ASN1::TYPE_ANY, - 'optional' => true - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AnotherName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AnotherName.php deleted file mode 100644 index f00b397461..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AnotherName.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AnotherName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AnotherName -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type-id' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'value' => [ - 'type' => ASN1::TYPE_ANY, - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Attribute.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Attribute.php deleted file mode 100644 index cf657fa9d6..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Attribute.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Attribute - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Attribute -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type' => AttributeType::MAP, - 'value'=> [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => -1, - 'children' => AttributeValue::MAP - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeType.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeType.php deleted file mode 100644 index 354ed10e5c..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeType.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AttributeType - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AttributeType -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php deleted file mode 100644 index 4982e5e46b..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AttributeTypeAndValue - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AttributeTypeAndValue -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type' => AttributeType::MAP, - 'value'=> AttributeValue::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeValue.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeValue.php deleted file mode 100644 index 10b8ad094a..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AttributeValue.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AttributeValue - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AttributeValue -{ - const MAP = ['type' => ASN1::TYPE_ANY]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Attributes.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Attributes.php deleted file mode 100644 index 2614ef452a..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Attributes.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Attributes - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Attributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => -1, - 'children' => Attribute::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php deleted file mode 100644 index 8fc7bfe7a3..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AuthorityInfoAccessSyntax - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AuthorityInfoAccessSyntax -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => AccessDescription::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php b/lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php deleted file mode 100644 index 634d3a42fe..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * AuthorityKeyIdentifier - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class AuthorityKeyIdentifier -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'keyIdentifier' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + KeyIdentifier::MAP, - 'authorityCertIssuer' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + GeneralNames::MAP, - 'authorityCertSerialNumber' => [ - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ] + CertificateSerialNumber::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/BaseDistance.php b/lib/phpaes/phpseclib/File/ASN1/Maps/BaseDistance.php deleted file mode 100644 index cdeb566567..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/BaseDistance.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * BaseDistance - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class BaseDistance -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/BasicConstraints.php b/lib/phpaes/phpseclib/File/ASN1/Maps/BasicConstraints.php deleted file mode 100644 index 4fd2c6375f..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/BasicConstraints.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * BasicConstraints - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class BasicConstraints -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'cA' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'optional' => true, - 'default' => false - ], - 'pathLenConstraint' => [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php b/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php deleted file mode 100644 index 6b81a18cfa..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * BuiltInDomainDefinedAttribute - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class BuiltInDomainDefinedAttribute -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type' => ['type' => ASN1::TYPE_PRINTABLE_STRING], - 'value' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php b/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php deleted file mode 100644 index 82d18354e1..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * BuiltInDomainDefinedAttributes - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class BuiltInDomainDefinedAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => 4, // ub-domain-defined-attributes - 'children' => BuiltInDomainDefinedAttribute::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php b/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php deleted file mode 100644 index 1b5816743e..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php +++ /dev/null @@ -1,71 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * BuiltInStandardAttributes - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class BuiltInStandardAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'country-name' => ['optional' => true] + CountryName::MAP, - 'administration-domain-name' => ['optional' => true] + AdministrationDomainName::MAP, - 'network-address' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + NetworkAddress::MAP, - 'terminal-identifier' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + TerminalIdentifier::MAP, - 'private-domain-name' => [ - 'constant' => 2, - 'optional' => true, - 'explicit' => true - ] + PrivateDomainName::MAP, - 'organization-name' => [ - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] + OrganizationName::MAP, - 'numeric-user-identifier' => [ - 'constant' => 4, - 'optional' => true, - 'implicit' => true - ] + NumericUserIdentifier::MAP, - 'personal-name' => [ - 'constant' => 5, - 'optional' => true, - 'implicit' => true - ] + PersonalName::MAP, - 'organizational-unit-names' => [ - 'constant' => 6, - 'optional' => true, - 'implicit' => true - ] + OrganizationalUnitNames::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CPSuri.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CPSuri.php deleted file mode 100644 index 96ad09af4b..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CPSuri.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CPSuri - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CPSuri -{ - const MAP = ['type' => ASN1::TYPE_IA5_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php deleted file mode 100644 index a06d474cc6..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CRLDistributionPoints - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CRLDistributionPoints -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => DistributionPoint::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CRLNumber.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CRLNumber.php deleted file mode 100644 index 83eebd83fa..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CRLNumber.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CRLNumber - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CRLNumber -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CRLReason.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CRLReason.php deleted file mode 100644 index ae5475e877..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CRLReason.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CRLReason - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CRLReason -{ - const MAP = [ - 'type' => ASN1::TYPE_ENUMERATED, - 'mapping' => [ - 'unspecified', - 'keyCompromise', - 'cACompromise', - 'affiliationChanged', - 'superseded', - 'cessationOfOperation', - 'certificateHold', - // Value 7 is not used. - 8 => 'removeFromCRL', - 'privilegeWithdrawn', - 'aACompromise' - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CertPolicyId.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CertPolicyId.php deleted file mode 100644 index c8fac468f6..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CertPolicyId.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CertPolicyId - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CertPolicyId -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Certificate.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Certificate.php deleted file mode 100644 index 0b6bcd71d4..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Certificate.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Certificate - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Certificate -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'tbsCertificate' => TBSCertificate::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateIssuer.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateIssuer.php deleted file mode 100644 index 51696784ab..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateIssuer.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CertificateIssuer - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CertificateIssuer -{ - const MAP = GeneralNames::MAP; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateList.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateList.php deleted file mode 100644 index 2ce3872ac9..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateList.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CertificateList - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CertificateList -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'tbsCertList' => TBSCertList::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificatePolicies.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CertificatePolicies.php deleted file mode 100644 index 65bd8a44ab..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificatePolicies.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CertificatePolicies - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CertificatePolicies -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => PolicyInformation::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php deleted file mode 100644 index c9cc70dbe8..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CertificateSerialNumber - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CertificateSerialNumber -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequest.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequest.php deleted file mode 100644 index 97ff23c77e..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequest.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CertificationRequest - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CertificationRequest -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'certificationRequestInfo' => CertificationRequestInfo::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php deleted file mode 100644 index f1f62aa439..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CertificationRequestInfo - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CertificationRequestInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['v1'] - ], - 'subject' => Name::MAP, - 'subjectPKInfo' => SubjectPublicKeyInfo::MAP, - 'attributes' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + Attributes::MAP, - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/CountryName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/CountryName.php deleted file mode 100644 index 98e7a88759..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/CountryName.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * CountryName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class CountryName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - // if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or - // (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC - 'class' => ASN1::CLASS_APPLICATION, - 'cast' => 1, - 'children' => [ - 'x121-dcc-code' => ['type' => ASN1::TYPE_NUMERIC_STRING], - 'iso-3166-alpha2-code' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DSAParams.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DSAParams.php deleted file mode 100644 index c3941edae0..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DSAParams.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DSAParams - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DSAParams -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'p' => ['type' => ASN1::TYPE_INTEGER], - 'q' => ['type' => ASN1::TYPE_INTEGER], - 'g' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DSAPrivateKey.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DSAPrivateKey.php deleted file mode 100644 index 0617417859..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DSAPrivateKey.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DSAPrivateKey - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DSAPrivateKey -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => ['type' => ASN1::TYPE_INTEGER], - 'p' => ['type' => ASN1::TYPE_INTEGER], - 'q' => ['type' => ASN1::TYPE_INTEGER], - 'g' => ['type' => ASN1::TYPE_INTEGER], - 'y' => ['type' => ASN1::TYPE_INTEGER], - 'x' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} \ No newline at end of file diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DSAPublicKey.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DSAPublicKey.php deleted file mode 100644 index abe808d77d..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DSAPublicKey.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DSAPublicKey - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DSAPublicKey -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DigestInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DigestInfo.php deleted file mode 100644 index d326e343c8..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DigestInfo.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DigestInfo - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DigestInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'digestAlgorithm' => AlgorithmIdentifier::MAP, - 'digest' => ['type' => ASN1::TYPE_OCTET_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DirectoryString.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DirectoryString.php deleted file mode 100644 index 555aee242e..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DirectoryString.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DirectoryString - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DirectoryString -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'teletexString' => ['type' => ASN1::TYPE_TELETEX_STRING], - 'printableString' => ['type' => ASN1::TYPE_PRINTABLE_STRING], - 'universalString' => ['type' => ASN1::TYPE_UNIVERSAL_STRING], - 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING], - 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DisplayText.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DisplayText.php deleted file mode 100644 index 1e3f60f93e..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DisplayText.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DisplayText - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DisplayText -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'ia5String' => ['type' => ASN1::TYPE_IA5_STRING], - 'visibleString' => ['type' => ASN1::TYPE_VISIBLE_STRING], - 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING], - 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPoint.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPoint.php deleted file mode 100644 index 110ad45998..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPoint.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DistributionPoint - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DistributionPoint -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'distributionPoint' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] + DistributionPointName::MAP, - 'reasons' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + ReasonFlags::MAP, - 'cRLIssuer' => [ - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ] + GeneralNames::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPointName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPointName.php deleted file mode 100644 index 8ea5ba059b..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DistributionPointName.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DistributionPointName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DistributionPointName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'fullName' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + GeneralNames::MAP, - 'nameRelativeToCRLIssuer' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + RelativeDistinguishedName::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/DssSigValue.php b/lib/phpaes/phpseclib/File/ASN1/Maps/DssSigValue.php deleted file mode 100644 index 05eda2c381..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/DssSigValue.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * DssSigValue - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class DssSigValue -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'r' => ['type' => ASN1::TYPE_INTEGER], - 's' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/EDIPartyName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/EDIPartyName.php deleted file mode 100644 index 3ac07e9d47..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/EDIPartyName.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * EDIPartyName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class EDIPartyName -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'nameAssigner' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + DirectoryString::MAP, - // partyName is technically required but \phpseclib\File\ASN1 doesn't currently support non-optional constants and - // setting it to optional gets the job done in any event. - 'partyName' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + DirectoryString::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedData.php b/lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedData.php deleted file mode 100644 index 79e361c8e8..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedData.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * EncryptedData - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class EncryptedData -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php deleted file mode 100644 index ca8d559014..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * EncryptedPrivateKeyInfo - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class EncryptedPrivateKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'encryptionAlgorithm' => AlgorithmIdentifier::MAP, - 'encryptedData' => EncryptedData::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php b/lib/phpaes/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php deleted file mode 100644 index 9a257c5e22..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * ExtKeyUsageSyntax - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class ExtKeyUsageSyntax -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => KeyPurposeId::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Extension.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Extension.php deleted file mode 100644 index d59e2d3c2c..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Extension.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Extension - * - * A certificate using system MUST reject the certificate if it encounters - * a critical extension it does not recognize; however, a non-critical - * extension may be ignored if it is not recognized. - * - * http://tools.ietf.org/html/rfc5280#section-4.2 - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Extension -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'extnId' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'critical' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'optional' => true, - 'default' => false - ], - 'extnValue' => ['type' => ASN1::TYPE_OCTET_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttribute.php b/lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttribute.php deleted file mode 100644 index cf537f639e..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttribute.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * ExtensionAttribute - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class ExtensionAttribute -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'extension-attribute-type' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ], - 'extension-attribute-value' => [ - 'type' => ASN1::TYPE_ANY, - 'constant' => 1, - 'optional' => true, - 'explicit' => true - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttributes.php b/lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttributes.php deleted file mode 100644 index 60189d8bd8..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/ExtensionAttributes.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * ExtensionAttributes - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class ExtensionAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => 256, // ub-extension-attributes - 'children' => ExtensionAttribute::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Extensions.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Extensions.php deleted file mode 100644 index 152316ded3..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Extensions.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Extensions - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Extensions -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - // technically, it's MAX, but we'll assume anything < 0 is MAX - 'max' => -1, - // if 'children' isn't an array then 'min' and 'max' must be defined - 'children' => Extension::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralName.php deleted file mode 100644 index 38e007905d..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralName.php +++ /dev/null @@ -1,84 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * GeneralName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class GeneralName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'otherName' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + AnotherName::MAP, - 'rfc822Name' => [ - 'type' => ASN1::TYPE_IA5_STRING, - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ], - 'dNSName' => [ - 'type' => ASN1::TYPE_IA5_STRING, - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ], - 'x400Address' => [ - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] + ORAddress::MAP, - 'directoryName' => [ - 'constant' => 4, - 'optional' => true, - 'explicit' => true - ] + Name::MAP, - 'ediPartyName' => [ - 'constant' => 5, - 'optional' => true, - 'implicit' => true - ] + EDIPartyName::MAP, - 'uniformResourceIdentifier' => [ - 'type' => ASN1::TYPE_IA5_STRING, - 'constant' => 6, - 'optional' => true, - 'implicit' => true - ], - 'iPAddress' => [ - 'type' => ASN1::TYPE_OCTET_STRING, - 'constant' => 7, - 'optional' => true, - 'implicit' => true - ], - 'registeredID' => [ - 'type' => ASN1::TYPE_OBJECT_IDENTIFIER, - 'constant' => 8, - 'optional' => true, - 'implicit' => true - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralNames.php b/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralNames.php deleted file mode 100644 index 263e2a2d8a..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralNames.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * GeneralNames - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class GeneralNames -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => GeneralName::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtree.php b/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtree.php deleted file mode 100644 index 6b42f03435..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtree.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * GeneralSubtree - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class GeneralSubtree -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'base' => GeneralName::MAP, - 'minimum' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true, - 'default' => '0' - ] + BaseDistance::MAP, - 'maximum' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true, - ] + BaseDistance::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtrees.php b/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtrees.php deleted file mode 100644 index 4d3a948e14..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/GeneralSubtrees.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * GeneralSubtrees - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class GeneralSubtrees -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => GeneralSubtree::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/HoldInstructionCode.php b/lib/phpaes/phpseclib/File/ASN1/Maps/HoldInstructionCode.php deleted file mode 100644 index fe4b991a69..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/HoldInstructionCode.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * HoldInstructionCode - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class HoldInstructionCode -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/InvalidityDate.php b/lib/phpaes/phpseclib/File/ASN1/Maps/InvalidityDate.php deleted file mode 100644 index e776b5fbe6..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/InvalidityDate.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * InvalidityDate - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class InvalidityDate -{ - const MAP = ['type' => ASN1::TYPE_GENERALIZED_TIME]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/IssuerAltName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/IssuerAltName.php deleted file mode 100644 index 7d52663634..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/IssuerAltName.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * IssuerAltName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class IssuerAltName -{ - const MAP = GeneralNames::MAP; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php b/lib/phpaes/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php deleted file mode 100644 index 15c22501ae..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * IssuingDistributionPoint - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class IssuingDistributionPoint -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'distributionPoint' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] + DistributionPointName::MAP, - 'onlyContainsUserCerts' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 1, - 'optional' => true, - 'default' => false, - 'implicit' => true - ], - 'onlyContainsCACerts' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 2, - 'optional' => true, - 'default' => false, - 'implicit' => true - ], - 'onlySomeReasons' => [ - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] + ReasonFlags::MAP, - 'indirectCRL' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 4, - 'optional' => true, - 'default' => false, - 'implicit' => true - ], - 'onlyContainsAttributeCerts' =>[ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 5, - 'optional' => true, - 'default' => false, - 'implicit' => true - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/KeyIdentifier.php b/lib/phpaes/phpseclib/File/ASN1/Maps/KeyIdentifier.php deleted file mode 100644 index caf16d85bd..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/KeyIdentifier.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * KeyIdentifier - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class KeyIdentifier -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/KeyPurposeId.php b/lib/phpaes/phpseclib/File/ASN1/Maps/KeyPurposeId.php deleted file mode 100644 index b401d7eba5..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/KeyPurposeId.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * KeyPurposeId - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class KeyPurposeId -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/KeyUsage.php b/lib/phpaes/phpseclib/File/ASN1/Maps/KeyUsage.php deleted file mode 100644 index a743def69a..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/KeyUsage.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * KeyUsage - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class KeyUsage -{ - const MAP = [ - 'type' => ASN1::TYPE_BIT_STRING, - 'mapping' => [ - 'digitalSignature', - 'nonRepudiation', - 'keyEncipherment', - 'dataEncipherment', - 'keyAgreement', - 'keyCertSign', - 'cRLSign', - 'encipherOnly', - 'decipherOnly' - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Name.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Name.php deleted file mode 100644 index 2241974397..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Name.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Name - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Name -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'rdnSequence' => RDNSequence::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/NameConstraints.php b/lib/phpaes/phpseclib/File/ASN1/Maps/NameConstraints.php deleted file mode 100644 index 0f3d8c46f0..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/NameConstraints.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * NameConstraints - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class NameConstraints -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'permittedSubtrees' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + GeneralSubtrees::MAP, - 'excludedSubtrees' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + GeneralSubtrees::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/NetworkAddress.php b/lib/phpaes/phpseclib/File/ASN1/Maps/NetworkAddress.php deleted file mode 100644 index 2edab3c84d..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/NetworkAddress.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * NetworkAddress - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class NetworkAddress -{ - const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/NoticeReference.php b/lib/phpaes/phpseclib/File/ASN1/Maps/NoticeReference.php deleted file mode 100644 index 66aa93b6b2..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/NoticeReference.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * NoticeReference - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class NoticeReference -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'organization' => DisplayText::MAP, - 'noticeNumbers' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => 200, - 'children' => ['type' => ASN1::TYPE_INTEGER] - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php b/lib/phpaes/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php deleted file mode 100644 index 9ed3d71789..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * NumericUserIdentifier - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class NumericUserIdentifier -{ - const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/ORAddress.php b/lib/phpaes/phpseclib/File/ASN1/Maps/ORAddress.php deleted file mode 100644 index e3119a461e..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/ORAddress.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * ORAddress - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class ORAddress -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'built-in-standard-attributes' => BuiltInStandardAttributes::MAP, - 'built-in-domain-defined-attributes' => ['optional' => true] + BuiltInDomainDefinedAttributes::MAP, - 'extension-attributes' => ['optional' => true] + ExtensionAttributes::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationName.php deleted file mode 100644 index 04dd9d1b49..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationName.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * OrganizationName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class OrganizationName -{ - const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php b/lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php deleted file mode 100644 index 8a36c98891..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * OrganizationalUnitNames - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class OrganizationalUnitNames -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => 4, // ub-organizational-units - 'children' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php deleted file mode 100644 index 1ff4bc511c..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * OtherPrimeInfo - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class OtherPrimeInfo -{ - // version must be multi if otherPrimeInfos present - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'prime' => ['type' => ASN1::TYPE_INTEGER], // ri - 'exponent' => ['type' => ASN1::TYPE_INTEGER], // di - 'coefficient' => ['type' => ASN1::TYPE_INTEGER] // ti - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php b/lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php deleted file mode 100644 index 3a4ebd2d2b..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * OtherPrimeInfos - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class OtherPrimeInfos -{ - // version must be multi if otherPrimeInfos present - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => OtherPrimeInfo::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PBEParameter.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PBEParameter.php deleted file mode 100644 index 174a84d86d..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PBEParameter.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PBEParameter - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PBEParameter -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'salt' => ['type' => ASN1::TYPE_OCTET_STRING], - 'iterationCount' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PBES2params.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PBES2params.php deleted file mode 100644 index 3c50fe92f8..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PBES2params.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PBES2params - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PBES2params -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'keyDerivationFunc'=> AlgorithmIdentifier::MAP, - 'encryptionScheme' => AlgorithmIdentifier::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PBKDF2params.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PBKDF2params.php deleted file mode 100644 index 3d0d4501f5..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PBKDF2params.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PBKDF2params - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PBKDF2params -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - // technically, this is a CHOICE in RFC2898 but the other "choice" is, currently, more of a placeholder - // in the RFC - 'salt'=> ['type' => ASN1::TYPE_OCTET_STRING], - 'iterationCount'=> ['type' => ASN1::TYPE_INTEGER], - 'keyLength' => [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ], - 'prf' => AlgorithmIdentifier::MAP + ['optional' => true] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PBMAC1params.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PBMAC1params.php deleted file mode 100644 index ec46ebde21..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PBMAC1params.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PBMAC1params - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PBMAC1params -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'keyDerivationFunc'=> AlgorithmIdentifier::MAP, - 'messageAuthScheme'=> AlgorithmIdentifier::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PKCS9String.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PKCS9String.php deleted file mode 100644 index 9cbceae8e9..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PKCS9String.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PKCS9String - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PKCS9String -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'ia5String' => ['type' => ASN1::TYPE_IA5_STRING], - 'directoryString' => DirectoryString::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PersonalName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PersonalName.php deleted file mode 100644 index c308bfdb35..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PersonalName.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PersonalName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PersonalName -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'children' => [ - 'surname' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ], - 'given-name' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ], - 'initials' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ], - 'generation-qualifier' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyInformation.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyInformation.php deleted file mode 100644 index 7d89f43be8..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyInformation.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PolicyInformation - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PolicyInformation -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'policyIdentifier' => CertPolicyId::MAP, - 'policyQualifiers' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 0, - 'max' => -1, - 'optional' => true, - 'children' => PolicyQualifierInfo::MAP - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyMappings.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyMappings.php deleted file mode 100644 index eaa5b49719..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyMappings.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PolicyMappings - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PolicyMappings -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'issuerDomainPolicy' => CertPolicyId::MAP, - 'subjectDomainPolicy' => CertPolicyId::MAP - ] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierId.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierId.php deleted file mode 100644 index e657d2ce62..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierId.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PolicyQualifierId - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PolicyQualifierId -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php deleted file mode 100644 index 83fc872eff..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PolicyQualifierInfo - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PolicyQualifierInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'policyQualifierId' => PolicyQualifierId::MAP, - 'qualifier' => ['type' => ASN1::TYPE_ANY] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PostalAddress.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PostalAddress.php deleted file mode 100644 index 2a0e446dea..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PostalAddress.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PostalAddress - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PostalAddress -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'optional' => true, - 'min' => 1, - 'max' => -1, - 'children' => DirectoryString::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateDomainName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateDomainName.php deleted file mode 100644 index 16ffc53916..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateDomainName.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PrivateDomainName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PrivateDomainName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], - 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKey.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKey.php deleted file mode 100644 index e8e4409a28..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKey.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PrivateKey - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PrivateKey -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php deleted file mode 100644 index 04b6a22e01..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PrivateKeyInfo - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PrivateKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['v1'] - ], - 'privateKeyAlgorithm'=> AlgorithmIdentifier::MAP, - 'privateKey' => PrivateKey::MAP, - 'attributes' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + Attributes::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php deleted file mode 100644 index 3d994199ed..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PrivateKeyUsagePeriod - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PrivateKeyUsagePeriod -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'notBefore' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true, - 'type' => ASN1::TYPE_GENERALIZED_TIME], - 'notAfter' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true, - 'type' => ASN1::TYPE_GENERALIZED_TIME] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php deleted file mode 100644 index 18a0e7d32c..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PublicKeyAndChallenge - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PublicKeyAndChallenge -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'spki' => SubjectPublicKeyInfo::MAP, - 'challenge' => ['type' => ASN1::TYPE_IA5_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyInfo.php deleted file mode 100644 index 8f8b896623..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/PublicKeyInfo.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * PublicKeyInfo - * - * this format is not formally defined anywhere but is none-the-less the form you - * get when you do "openssl rsa -in private.pem -outform PEM -pubout" - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class PublicKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'publicKeyAlgorithm'=> AlgorithmIdentifier::MAP, - 'publicKey' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/RC2CBCParameter.php b/lib/phpaes/phpseclib/File/ASN1/Maps/RC2CBCParameter.php deleted file mode 100644 index 59254c0e5f..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/RC2CBCParameter.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * RC2CBCParameter - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class RC2CBCParameter -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'rc2ParametersVersion'=> [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ], - 'iv'=> ['type' => ASN1::TYPE_OCTET_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/RDNSequence.php b/lib/phpaes/phpseclib/File/ASN1/Maps/RDNSequence.php deleted file mode 100644 index e9197d642f..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/RDNSequence.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * RDNSequence - * - * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare, - * but they can be useful at times when either there is no unique attribute in the entry or you - * want to ensure that the entry's DN contains some useful identifying information. - * - * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class RDNSequence -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - // RDNSequence does not define a min or a max, which means it doesn't have one - 'min' => 0, - 'max' => -1, - 'children' => RelativeDistinguishedName::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/RSAPrivateKey.php b/lib/phpaes/phpseclib/File/ASN1/Maps/RSAPrivateKey.php deleted file mode 100644 index a7f06a497a..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/RSAPrivateKey.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * RSAPrivateKey - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class RSAPrivateKey -{ - // version must be multi if otherPrimeInfos present - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['two-prime', 'multi'] - ], - 'modulus' => ['type' => ASN1::TYPE_INTEGER], // n - 'publicExponent' => ['type' => ASN1::TYPE_INTEGER], // e - 'privateExponent' => ['type' => ASN1::TYPE_INTEGER], // d - 'prime1' => ['type' => ASN1::TYPE_INTEGER], // p - 'prime2' => ['type' => ASN1::TYPE_INTEGER], // q - 'exponent1' => ['type' => ASN1::TYPE_INTEGER], // d mod (p-1) - 'exponent2' => ['type' => ASN1::TYPE_INTEGER], // d mod (q-1) - 'coefficient' => ['type' => ASN1::TYPE_INTEGER], // (inverse of q) mod p - 'otherPrimeInfos' => OtherPrimeInfos::MAP + ['optional' => true] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/RSAPublicKey.php b/lib/phpaes/phpseclib/File/ASN1/Maps/RSAPublicKey.php deleted file mode 100644 index 15a0da7511..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/RSAPublicKey.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * RSAPublicKey - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class RSAPublicKey -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'modulus' => ['type' => ASN1::TYPE_INTEGER], - 'publicExponent' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/ReasonFlags.php b/lib/phpaes/phpseclib/File/ASN1/Maps/ReasonFlags.php deleted file mode 100644 index 4ba69dfdc9..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/ReasonFlags.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * ReasonFlags - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class ReasonFlags -{ - const MAP = [ - 'type' => ASN1::TYPE_BIT_STRING, - 'mapping' => [ - 'unused', - 'keyCompromise', - 'cACompromise', - 'affiliationChanged', - 'superseded', - 'cessationOfOperation', - 'certificateHold', - 'privilegeWithdrawn', - 'aACompromise' - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php deleted file mode 100644 index f903458699..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * RelativeDistinguishedName - * - * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare, - * but they can be useful at times when either there is no unique attribute in the entry or you - * want to ensure that the entry's DN contains some useful identifying information. - * - * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class RelativeDistinguishedName -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => -1, - 'children' => AttributeTypeAndValue::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/RevokedCertificate.php b/lib/phpaes/phpseclib/File/ASN1/Maps/RevokedCertificate.php deleted file mode 100644 index f5b9c02b60..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/RevokedCertificate.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * RevokedCertificate - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class RevokedCertificate -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'userCertificate' => CertificateSerialNumber::MAP, - 'revocationDate' => Time::MAP, - 'crlEntryExtensions' => [ - 'optional' => true - ] + Extensions::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php b/lib/phpaes/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php deleted file mode 100644 index b7e3efbdcd..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * SignedPublicKeyAndChallenge - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class SignedPublicKeyAndChallenge -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'publicKeyAndChallenge' => PublicKeyAndChallenge::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectAltName.php b/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectAltName.php deleted file mode 100644 index 65ecbf7a7a..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectAltName.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * SubjectAltName - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class SubjectAltName -{ - const MAP = GeneralNames::MAP; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php b/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php deleted file mode 100644 index bba456a669..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * SubjectDirectoryAttributes - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class SubjectDirectoryAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => Attribute::MAP - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php b/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php deleted file mode 100644 index 2ccd9076cd..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * SubjectPublicKeyInfo - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class SubjectPublicKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'algorithm' => AlgorithmIdentifier::MAP, - 'subjectPublicKey' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertList.php b/lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertList.php deleted file mode 100644 index df9549a33f..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertList.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * TBSCertList - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class TBSCertList -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['v1', 'v2', 'v3'], - 'optional' => true, - 'default' => 'v2' - ], - 'signature' => AlgorithmIdentifier::MAP, - 'issuer' => Name::MAP, - 'thisUpdate' => Time::MAP, - 'nextUpdate' => [ - 'optional' => true - ] + Time::MAP, - 'revokedCertificates' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'optional' => true, - 'min' => 0, - 'max' => -1, - 'children' => RevokedCertificate::MAP - ], - 'crlExtensions' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] + Extensions::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertificate.php b/lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertificate.php deleted file mode 100644 index b05674464b..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/TBSCertificate.php +++ /dev/null @@ -1,69 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * TBSCertificate - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class TBSCertificate -{ - // assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm']) - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - // technically, default implies optional, but we'll define it as being optional, none-the-less, just to - // reenforce that fact - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'constant' => 0, - 'optional' => true, - 'explicit' => true, - 'mapping' => ['v1', 'v2', 'v3'], - 'default' => 'v1' - ], - 'serialNumber' => CertificateSerialNumber::MAP, - 'signature' => AlgorithmIdentifier::MAP, - 'issuer' => Name::MAP, - 'validity' => Validity::MAP, - 'subject' => Name::MAP, - 'subjectPublicKeyInfo' => SubjectPublicKeyInfo::MAP, - // implicit means that the T in the TLV structure is to be rewritten, regardless of the type - 'issuerUniqueID' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + UniqueIdentifier::MAP, - 'subjectUniqueID' => [ - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ] + UniqueIdentifier::MAP, - // doesn't use the EXPLICIT keyword but if - // it's not IMPLICIT, it's EXPLICIT - 'extensions' => [ - 'constant' => 3, - 'optional' => true, - 'explicit' => true - ] + Extensions::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/TerminalIdentifier.php b/lib/phpaes/phpseclib/File/ASN1/Maps/TerminalIdentifier.php deleted file mode 100644 index be191dfdb0..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/TerminalIdentifier.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * TerminalIdentifier - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class TerminalIdentifier -{ - const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Time.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Time.php deleted file mode 100644 index 6b1389a39c..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Time.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Time - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Time -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'utcTime' => ['type' => ASN1::TYPE_UTC_TIME], - 'generalTime' => ['type' => ASN1::TYPE_GENERALIZED_TIME] - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/UniqueIdentifier.php b/lib/phpaes/phpseclib/File/ASN1/Maps/UniqueIdentifier.php deleted file mode 100644 index 68e46babfe..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/UniqueIdentifier.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * UniqueIdentifier - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class UniqueIdentifier -{ - const MAP = ['type' => ASN1::TYPE_BIT_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/UserNotice.php b/lib/phpaes/phpseclib/File/ASN1/Maps/UserNotice.php deleted file mode 100644 index 296670ef32..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/UserNotice.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * UserNotice - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class UserNotice -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'noticeRef' => [ - 'optional' => true, - 'implicit' => true - ] + NoticeReference::MAP, - 'explicitText' => [ - 'optional' => true, - 'implicit' => true - ] + DisplayText::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/Validity.php b/lib/phpaes/phpseclib/File/ASN1/Maps/Validity.php deleted file mode 100644 index 65199bdadc..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/Validity.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * Validity - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class Validity -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'notBefore' => Time::MAP, - 'notAfter' => Time::MAP - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php b/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php deleted file mode 100644 index 88e3a54acb..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * netscape_ca_policy_url - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class netscape_ca_policy_url -{ - const MAP = ['type' => ASN1::TYPE_IA5_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_cert_type.php b/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_cert_type.php deleted file mode 100644 index 833e40bcf1..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_cert_type.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * netscape_cert_type - * - * mapping is from - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class netscape_cert_type -{ - const MAP = [ - 'type' => ASN1::TYPE_BIT_STRING, - 'mapping' => [ - 'SSLClient', - 'SSLServer', - 'Email', - 'ObjectSigning', - 'Reserved', - 'SSLCA', - 'EmailCA', - 'ObjectSigningCA' - ] - ]; -} diff --git a/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_comment.php b/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_comment.php deleted file mode 100644 index 266d6e7687..0000000000 --- a/lib/phpaes/phpseclib/File/ASN1/Maps/netscape_comment.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File\ASN1\Maps; - -use phpseclib\File\ASN1; - -/** - * netscape_comment - * - * @package ASN1 - * @author Jim Wigginton - * @access public - */ -abstract class netscape_comment -{ - const MAP = ['type' => ASN1::TYPE_IA5_STRING]; -} diff --git a/lib/phpaes/phpseclib/File/X509.php b/lib/phpaes/phpseclib/File/X509.php deleted file mode 100644 index 7740de7cb7..0000000000 --- a/lib/phpaes/phpseclib/File/X509.php +++ /dev/null @@ -1,3719 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\File; - -use ParagonIE\ConstantTime\Base64; -use ParagonIE\ConstantTime\Hex; -use phpseclib\Crypt\Hash; -use phpseclib\Crypt\Random; -use phpseclib\Crypt\RSA; -use phpseclib\Exception\UnsupportedAlgorithmException; -use phpseclib\File\ASN1\Element; -use phpseclib\Math\BigInteger; -use phpseclib\File\ASN1\Maps; - -/** - * Pure-PHP X.509 Parser - * - * @package X509 - * @author Jim Wigginton - * @access public - */ -class X509 -{ - /** - * Flag to only accept signatures signed by certificate authorities - * - * Not really used anymore but retained all the same to suppress E_NOTICEs from old installs - * - * @access public - */ - const VALIDATE_SIGNATURE_BY_CA = 1; - - /**#@+ - * @access public - * @see \phpseclib\File\X509::getDN() - */ - /** - * Return internal array representation - */ - const DN_ARRAY = 0; - /** - * Return string - */ - const DN_STRING = 1; - /** - * Return ASN.1 name string - */ - const DN_ASN1 = 2; - /** - * Return OpenSSL compatible array - */ - const DN_OPENSSL = 3; - /** - * Return canonical ASN.1 RDNs string - */ - const DN_CANON = 4; - /** - * Return name hash for file indexing - */ - const DN_HASH = 5; - /**#@-*/ - - /**#@+ - * @access public - * @see \phpseclib\File\X509::saveX509() - * @see \phpseclib\File\X509::saveCSR() - * @see \phpseclib\File\X509::saveCRL() - */ - /** - * Save as PEM - * - * ie. a base64-encoded PEM with a header and a footer - */ - const FORMAT_PEM = 0; - /** - * Save as DER - */ - const FORMAT_DER = 1; - /** - * Save as a SPKAC - * - * Only works on CSRs. Not currently supported. - */ - const FORMAT_SPKAC = 2; - /** - * Auto-detect the format - * - * Used only by the load*() functions - */ - const FORMAT_AUTO_DETECT = 3; - /**#@-*/ - - /** - * Attribute value disposition. - * If disposition is >= 0, this is the index of the target value. - */ - const ATTR_ALL = -1; // All attribute values (array). - const ATTR_APPEND = -2; // Add a value. - const ATTR_REPLACE = -3; // Clear first, then add a value. - - /** - * Distinguished Name - * - * @var array - * @access private - */ - private $dn; - - /** - * Public key - * - * @var string - * @access private - */ - private $publicKey; - - /** - * Private key - * - * @var string - * @access private - */ - private $privateKey; - - /** - * Object identifiers for X.509 certificates - * - * @var array - * @access private - * @link http://en.wikipedia.org/wiki/Object_identifier - */ - private $oids; - - /** - * The certificate authorities - * - * @var array - * @access private - */ - private $CAs; - - /** - * The currently loaded certificate - * - * @var array - * @access private - */ - private $currentCert; - - /** - * The signature subject - * - * There's no guarantee \phpseclib\File\X509 is going to re-encode an X.509 cert in the same way it was originally - * encoded so we take save the portion of the original cert that the signature would have made for. - * - * @var string - * @access private - */ - private $signatureSubject; - - /** - * Certificate Start Date - * - * @var string - * @access private - */ - private $startDate; - - /** - * Certificate End Date - * - * @var string - * @access private - */ - private $endDate; - - /** - * Serial Number - * - * @var string - * @access private - */ - private $serialNumber; - - /** - * Key Identifier - * - * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and - * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}. - * - * @var string - * @access private - */ - private $currentKeyIdentifier; - - /** - * CA Flag - * - * @var bool - * @access private - */ - private $caFlag = false; - - /** - * SPKAC Challenge - * - * @var string - * @access private - */ - private $challenge; - - /** - * OIDs loaded - * - * @var bool - * @access private - */ - private static $oidsLoaded = false; - - /** - * Default Constructor. - * - * @return \phpseclib\File\X509 - * @access public - */ - public function __construct() - { - // Explicitly Tagged Module, 1988 Syntax - // http://tools.ietf.org/html/rfc5280#appendix-A.1 - - if (!self::$oidsLoaded) { - // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2 - ASN1::loadOIDs([ - '1.3.6.1.5.5.7' => 'id-pkix', - '1.3.6.1.5.5.7.1' => 'id-pe', - '1.3.6.1.5.5.7.2' => 'id-qt', - '1.3.6.1.5.5.7.3' => 'id-kp', - '1.3.6.1.5.5.7.48' => 'id-ad', - '1.3.6.1.5.5.7.2.1' => 'id-qt-cps', - '1.3.6.1.5.5.7.2.2' => 'id-qt-unotice', - '1.3.6.1.5.5.7.48.1' =>'id-ad-ocsp', - '1.3.6.1.5.5.7.48.2' => 'id-ad-caIssuers', - '1.3.6.1.5.5.7.48.3' => 'id-ad-timeStamping', - '1.3.6.1.5.5.7.48.5' => 'id-ad-caRepository', - '2.5.4' => 'id-at', - '2.5.4.41' => 'id-at-name', - '2.5.4.4' => 'id-at-surname', - '2.5.4.42' => 'id-at-givenName', - '2.5.4.43' => 'id-at-initials', - '2.5.4.44' => 'id-at-generationQualifier', - '2.5.4.3' => 'id-at-commonName', - '2.5.4.7' => 'id-at-localityName', - '2.5.4.8' => 'id-at-stateOrProvinceName', - '2.5.4.10' => 'id-at-organizationName', - '2.5.4.11' => 'id-at-organizationalUnitName', - '2.5.4.12' => 'id-at-title', - '2.5.4.13' => 'id-at-description', - '2.5.4.46' => 'id-at-dnQualifier', - '2.5.4.6' => 'id-at-countryName', - '2.5.4.5' => 'id-at-serialNumber', - '2.5.4.65' => 'id-at-pseudonym', - '2.5.4.17' => 'id-at-postalCode', - '2.5.4.9' => 'id-at-streetAddress', - '2.5.4.45' => 'id-at-uniqueIdentifier', - '2.5.4.72' => 'id-at-role', - '2.5.4.16' => 'id-at-postalAddress', - - '0.9.2342.19200300.100.1.25' => 'id-domainComponent', - '1.2.840.113549.1.9' => 'pkcs-9', - '1.2.840.113549.1.9.1' => 'pkcs-9-at-emailAddress', - '2.5.29' => 'id-ce', - '2.5.29.35' => 'id-ce-authorityKeyIdentifier', - '2.5.29.14' => 'id-ce-subjectKeyIdentifier', - '2.5.29.15' => 'id-ce-keyUsage', - '2.5.29.16' => 'id-ce-privateKeyUsagePeriod', - '2.5.29.32' => 'id-ce-certificatePolicies', - '2.5.29.32.0' => 'anyPolicy', - - '2.5.29.33' => 'id-ce-policyMappings', - '2.5.29.17' => 'id-ce-subjectAltName', - '2.5.29.18' => 'id-ce-issuerAltName', - '2.5.29.9' => 'id-ce-subjectDirectoryAttributes', - '2.5.29.19' => 'id-ce-basicConstraints', - '2.5.29.30' => 'id-ce-nameConstraints', - '2.5.29.36' => 'id-ce-policyConstraints', - '2.5.29.31' => 'id-ce-cRLDistributionPoints', - '2.5.29.37' => 'id-ce-extKeyUsage', - '2.5.29.37.0' => 'anyExtendedKeyUsage', - '1.3.6.1.5.5.7.3.1' => 'id-kp-serverAuth', - '1.3.6.1.5.5.7.3.2' => 'id-kp-clientAuth', - '1.3.6.1.5.5.7.3.3' => 'id-kp-codeSigning', - '1.3.6.1.5.5.7.3.4' => 'id-kp-emailProtection', - '1.3.6.1.5.5.7.3.8' => 'id-kp-timeStamping', - '1.3.6.1.5.5.7.3.9' => 'id-kp-OCSPSigning', - '2.5.29.54' => 'id-ce-inhibitAnyPolicy', - '2.5.29.46' => 'id-ce-freshestCRL', - '1.3.6.1.5.5.7.1.1' => 'id-pe-authorityInfoAccess', - '1.3.6.1.5.5.7.1.11' => 'id-pe-subjectInfoAccess', - '2.5.29.20' => 'id-ce-cRLNumber', - '2.5.29.28' => 'id-ce-issuingDistributionPoint', - '2.5.29.27' => 'id-ce-deltaCRLIndicator', - '2.5.29.21' => 'id-ce-cRLReasons', - '2.5.29.29' => 'id-ce-certificateIssuer', - '2.5.29.23' => 'id-ce-holdInstructionCode', - '1.2.840.10040.2' => 'holdInstruction', - '1.2.840.10040.2.1' => 'id-holdinstruction-none', - '1.2.840.10040.2.2' => 'id-holdinstruction-callissuer', - '1.2.840.10040.2.3' => 'id-holdinstruction-reject', - '2.5.29.24' => 'id-ce-invalidityDate', - - '1.2.840.113549.2.2' => 'md2', - '1.2.840.113549.2.5' => 'md5', - '1.3.14.3.2.26' => 'id-sha1', - '1.2.840.10040.4.1' => 'id-dsa', - '1.2.840.10040.4.3' => 'id-dsa-with-sha1', - '1.2.840.113549.1.1' => 'pkcs-1', - '1.2.840.113549.1.1.1' => 'rsaEncryption', - '1.2.840.113549.1.1.2' => 'md2WithRSAEncryption', - '1.2.840.113549.1.1.4' => 'md5WithRSAEncryption', - '1.2.840.113549.1.1.5' => 'sha1WithRSAEncryption', - '1.2.840.10046.2.1' => 'dhpublicnumber', - '2.16.840.1.101.2.1.1.22' => 'id-keyExchangeAlgorithm', - '1.2.840.10045' => 'ansi-X9-62', - '1.2.840.10045.4' => 'id-ecSigType', - '1.2.840.10045.4.1' => 'ecdsa-with-SHA1', - '1.2.840.10045.1' => 'id-fieldType', - '1.2.840.10045.1.1' => 'prime-field', - '1.2.840.10045.1.2' => 'characteristic-two-field', - '1.2.840.10045.1.2.3' => 'id-characteristic-two-basis', - '1.2.840.10045.1.2.3.1' => 'gnBasis', - '1.2.840.10045.1.2.3.2' => 'tpBasis', - '1.2.840.10045.1.2.3.3' => 'ppBasis', - '1.2.840.10045.2' => 'id-publicKeyType', - '1.2.840.10045.2.1' => 'id-ecPublicKey', - '1.2.840.10045.3' => 'ellipticCurve', - '1.2.840.10045.3.0' => 'c-TwoCurve', - '1.2.840.10045.3.0.1' => 'c2pnb163v1', - '1.2.840.10045.3.0.2' => 'c2pnb163v2', - '1.2.840.10045.3.0.3' => 'c2pnb163v3', - '1.2.840.10045.3.0.4' => 'c2pnb176w1', - '1.2.840.10045.3.0.5' => 'c2pnb191v1', - '1.2.840.10045.3.0.6' => 'c2pnb191v2', - '1.2.840.10045.3.0.7' => 'c2pnb191v3', - '1.2.840.10045.3.0.8' => 'c2pnb191v4', - '1.2.840.10045.3.0.9' => 'c2pnb191v5', - '1.2.840.10045.3.0.10' => 'c2pnb208w1', - '1.2.840.10045.3.0.11' => 'c2pnb239v1', - '1.2.840.10045.3.0.12' => 'c2pnb239v2', - '1.2.840.10045.3.0.13' => 'c2pnb239v3', - '1.2.840.10045.3.0.14' => 'c2pnb239v4', - '1.2.840.10045.3.0.15' => 'c2pnb239v5', - '1.2.840.10045.3.0.16' => 'c2pnb272w1', - '1.2.840.10045.3.0.17' => 'c2pnb304w1', - '1.2.840.10045.3.0.18' => 'c2pnb359v1', - '1.2.840.10045.3.0.19' => 'c2pnb368w1', - '1.2.840.10045.3.0.20' => 'c2pnb431r1', - '1.2.840.10045.3.1' => 'primeCurve', - '1.2.840.10045.3.1.1' => 'prime192v1', - '1.2.840.10045.3.1.2' => 'prime192v2', - '1.2.840.10045.3.1.3' => 'prime192v3', - '1.2.840.10045.3.1.4' => 'prime239v1', - '1.2.840.10045.3.1.5' => 'prime239v2', - '1.2.840.10045.3.1.6' => 'prime239v3', - '1.2.840.10045.3.1.7' => 'prime256v1', - '1.2.840.113549.1.1.7' => 'id-RSAES-OAEP', - '1.2.840.113549.1.1.9' => 'id-pSpecified', - '1.2.840.113549.1.1.10' => 'id-RSASSA-PSS', - '1.2.840.113549.1.1.8' => 'id-mgf1', - '1.2.840.113549.1.1.14' => 'sha224WithRSAEncryption', - '1.2.840.113549.1.1.11' => 'sha256WithRSAEncryption', - '1.2.840.113549.1.1.12' => 'sha384WithRSAEncryption', - '1.2.840.113549.1.1.13' => 'sha512WithRSAEncryption', - '2.16.840.1.101.3.4.2.4' => 'id-sha224', - '2.16.840.1.101.3.4.2.1' => 'id-sha256', - '2.16.840.1.101.3.4.2.2' => 'id-sha384', - '2.16.840.1.101.3.4.2.3' => 'id-sha512', - '1.2.643.2.2.4' => 'id-GostR3411-94-with-GostR3410-94', - '1.2.643.2.2.3' => 'id-GostR3411-94-with-GostR3410-2001', - '1.2.643.2.2.20' => 'id-GostR3410-2001', - '1.2.643.2.2.19' => 'id-GostR3410-94', - // Netscape Object Identifiers from "Netscape Certificate Extensions" - '2.16.840.1.113730' => 'netscape', - '2.16.840.1.113730.1' => 'netscape-cert-extension', - '2.16.840.1.113730.1.1' => 'netscape-cert-type', - '2.16.840.1.113730.1.13' => 'netscape-comment', - '2.16.840.1.113730.1.8' => 'netscape-ca-policy-url', - // the following are X.509 extensions not supported by phpseclib - '1.3.6.1.5.5.7.1.12' => 'id-pe-logotype', - '1.2.840.113533.7.65.0' => 'entrustVersInfo', - '2.16.840.1.113733.1.6.9' => 'verisignPrivate', - // for Certificate Signing Requests - // see http://tools.ietf.org/html/rfc2985 - '1.2.840.113549.1.9.2' => 'pkcs-9-at-unstructuredName', // PKCS #9 unstructured name - '1.2.840.113549.1.9.7' => 'pkcs-9-at-challengePassword', // Challenge password for certificate revocations - '1.2.840.113549.1.9.14' => 'pkcs-9-at-extensionRequest' // Certificate extension request - ]); - } - } - - /** - * Load X.509 certificate - * - * Returns an associative array describing the X.509 cert or a false if the cert failed to load - * - * @param string $cert - * @param int $mode - * @access public - * @return mixed - */ - public function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT) - { - if (is_array($cert) && isset($cert['tbsCertificate'])) { - unset($this->currentCert); - unset($this->currentKeyIdentifier); - $this->dn = $cert['tbsCertificate']['subject']; - if (!isset($this->dn)) { - return false; - } - $this->currentCert = $cert; - - $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); - $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; - - unset($this->signatureSubject); - - return $cert; - } - - if ($mode != self::FORMAT_DER) { - $newcert = ASN1::extractBER($cert); - if ($mode == self::FORMAT_PEM && $cert == $newcert) { - return false; - } - $cert = $newcert; - } - - if ($cert === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($cert); - - if (!empty($decoded)) { - $x509 = ASN1::asn1map($decoded[0], Maps\Certificate::MAP); - } - if (!isset($x509) || $x509 === false) { - $this->currentCert = false; - return false; - } - - $this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - if ($this->isSubArrayValid($x509, 'tbsCertificate/extensions')) { - $this->mapInExtensions($x509, 'tbsCertificate/extensions'); - } - $this->mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence'); - $this->mapInDNs($x509, 'tbsCertificate/subject/rdnSequence'); - - $key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']; - $key = $this->reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key); - - $this->currentCert = $x509; - $this->dn = $x509['tbsCertificate']['subject']; - - $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); - $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; - - return $x509; - } - - /** - * Save X.509 certificate - * - * @param array $cert - * @param int $format optional - * @access public - * @return string - */ - public function saveX509($cert, $format = self::FORMAT_PEM) - { - if (!is_array($cert) || !isset($cert['tbsCertificate'])) { - return false; - } - - switch (true) { - // "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()" - case !($algorithm = $this->subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')): - case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']): - break; - default: - switch ($algorithm) { - case 'rsaEncryption': - $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] - = Base64::encode("\0" . Base64::decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']))); - /* "[For RSA keys] the parameters field MUST have ASN.1 type NULL for this algorithm identifier." - -- https://tools.ietf.org/html/rfc3279#section-2.3.1 - - given that and the fact that RSA keys appear ot be the only key type for which the parameters field can be blank, - it seems like perhaps the ASN.1 description ought not say the parameters field is OPTIONAL, but whatever. - */ - $cert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = null; - // https://tools.ietf.org/html/rfc3279#section-2.2.1 - $cert['signatureAlgorithm']['parameters'] = null; - $cert['tbsCertificate']['signature']['parameters'] = null; - } - } - - $filters = []; - $type_utf8_string = ['type' => ASN1::TYPE_UTF8_STRING]; - $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string; - $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string; - $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string; - $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string; - $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string; - $filters['signatureAlgorithm']['parameters'] = $type_utf8_string; - $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string; - //$filters['policyQualifiers']['qualifier'] = $type_utf8_string; - $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string; - $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string; - - /* in the case of policyQualifiers/qualifier, the type has to be \phpseclib\File\ASN1::TYPE_IA5_STRING. - \phpseclib\File\ASN1::TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random - characters. - */ - $filters['policyQualifiers']['qualifier'] - = ['type' => ASN1::TYPE_IA5_STRING]; - - ASN1::setFilters($filters); - - $this->mapOutExtensions($cert, 'tbsCertificate/extensions'); - $this->mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence'); - $this->mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence'); - - $cert = ASN1::encodeDER($cert, Maps\Certificate::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $cert; - // case self::FORMAT_PEM: - default: - return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(Base64::encode($cert), 64) . '-----END CERTIFICATE-----'; - } - } - - /** - * Map extension values from octet string to extension-specific internal - * format. - * - * @param array ref $root - * @param string $path - * @access private - */ - private function mapInExtensions(&$root, $path) - { - $extensions = &$this->subArrayUnchecked($root, $path); - - if ($extensions) { - for ($i = 0; $i < count($extensions); $i++) { - $id = $extensions[$i]['extnId']; - $value = &$extensions[$i]['extnValue']; - $decoded = ASN1::decodeBER($value); - /* [extnValue] contains the DER encoding of an ASN.1 value - corresponding to the extension type identified by extnID */ - $map = $this->getMapping($id); - if (!is_bool($map)) { - $mapped = ASN1::asn1map($decoded[0], $map, ['iPAddress' => [$this, 'decodeIP']]); - $value = $mapped === false ? $decoded[0] : $mapped; - - if ($id == 'id-ce-certificatePolicies') { - for ($j = 0; $j < count($value); $j++) { - if (!isset($value[$j]['policyQualifiers'])) { - continue; - } - for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) { - $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId']; - $map = $this->getMapping($subid); - $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier']; - if ($map !== false) { - $decoded = ASN1::decodeBER($subvalue); - $mapped = ASN1::asn1map($decoded[0], $map); - $subvalue = $mapped === false ? $decoded[0] : $mapped; - } - } - } - } - } - } - } - } - - /** - * Map extension values from extension-specific internal format to - * octet string. - * - * @param array ref $root - * @param string $path - * @access private - */ - private function mapOutExtensions(&$root, $path) - { - $extensions = &$this->subArray($root, $path); - - if (is_array($extensions)) { - $size = count($extensions); - for ($i = 0; $i < $size; $i++) { - if ($extensions[$i] instanceof Element) { - continue; - } - - $id = $extensions[$i]['extnId']; - $value = &$extensions[$i]['extnValue']; - - switch ($id) { - case 'id-ce-certificatePolicies': - for ($j = 0; $j < count($value); $j++) { - if (!isset($value[$j]['policyQualifiers'])) { - continue; - } - for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) { - $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId']; - $map = $this->getMapping($subid); - $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier']; - if ($map !== false) { - // by default \phpseclib\File\ASN1 will try to render qualifier as a \phpseclib\File\ASN1::TYPE_IA5_STRING since it's - // actual type is \phpseclib\File\ASN1::TYPE_ANY - $subvalue = new Element(ASN1::encodeDER($subvalue, $map)); - } - } - } - break; - case 'id-ce-authorityKeyIdentifier': // use 00 as the serial number instead of an empty string - if (isset($value['authorityCertSerialNumber'])) { - if ($value['authorityCertSerialNumber']->toBytes() == '') { - $temp = chr((ASN1::CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0"; - $value['authorityCertSerialNumber'] = new Element($temp); - } - } - } - - /* [extnValue] contains the DER encoding of an ASN.1 value - corresponding to the extension type identified by extnID */ - $map = $this->getMapping($id); - if (is_bool($map)) { - if (!$map) { - //user_error($id . ' is not a currently supported extension'); - unset($extensions[$i]); - } - } else { - $value = ASN1::encodeDER($value, $map, ['iPAddress' => [$this, 'encodeIP']]); - } - } - } - } - - /** - * Map attribute values from ANY type to attribute-specific internal - * format. - * - * @param array ref $root - * @param string $path - * @access private - */ - private function mapInAttributes(&$root, $path) - { - $attributes = &$this->subArray($root, $path); - - if (is_array($attributes)) { - for ($i = 0; $i < count($attributes); $i++) { - $id = $attributes[$i]['type']; - /* $value contains the DER encoding of an ASN.1 value - corresponding to the attribute type identified by type */ - $map = $this->getMapping($id); - if (is_array($attributes[$i]['value'])) { - $values = &$attributes[$i]['value']; - for ($j = 0; $j < count($values); $j++) { - $value = ASN1::encodeDER($values[$j], Maps\AttributeValue::MAP); - $decoded = ASN1::decodeBER($value); - if (!is_bool($map)) { - $mapped = ASN1::asn1map($decoded[0], $map); - if ($mapped !== false) { - $values[$j] = $mapped; - } - if ($id == 'pkcs-9-at-extensionRequest' && $this->isSubArrayValid($values, $j)) { - $this->mapInExtensions($values, $j); - } - } elseif ($map) { - $values[$j] = $value; - } - } - } - } - } - } - - /** - * Map attribute values from attribute-specific internal format to - * ANY type. - * - * @param array ref $root - * @param string $path - * @access private - */ - private function mapOutAttributes(&$root, $path) - { - $attributes = &$this->subArray($root, $path); - - if (is_array($attributes)) { - $size = count($attributes); - for ($i = 0; $i < $size; $i++) { - /* [value] contains the DER encoding of an ASN.1 value - corresponding to the attribute type identified by type */ - $id = $attributes[$i]['type']; - $map = $this->getMapping($id); - if ($map === false) { - //user_error($id . ' is not a currently supported attribute', E_USER_NOTICE); - unset($attributes[$i]); - } elseif (is_array($attributes[$i]['value'])) { - $values = &$attributes[$i]['value']; - for ($j = 0; $j < count($values); $j++) { - switch ($id) { - case 'pkcs-9-at-extensionRequest': - $this->mapOutExtensions($values, $j); - break; - } - - if (!is_bool($map)) { - $temp = ASN1::encodeDER($values[$j], $map); - $decoded = ASN1::decodeBER($temp); - $values[$j] = ASN1::asn1map($decoded[0], Maps\AttributeValue::MAP); - } - } - } - } - } - } - - /** - * Map DN values from ANY type to DN-specific internal - * format. - * - * @param array ref $root - * @param string $path - * @access private - */ - private function mapInDNs(&$root, $path) - { - $dns = &$this->subArray($root, $path); - - if (is_array($dns)) { - for ($i = 0; $i < count($dns); $i++) { - for ($j = 0; $j < count($dns[$i]); $j++) { - $type = $dns[$i][$j]['type']; - $value = &$dns[$i][$j]['value']; - if (is_object($value) && $value instanceof Element) { - $map = $this->getMapping($type); - if (!is_bool($map)) { - $decoded = ASN1::decodeBER($value); - $value = ASN1::asn1map($decoded[0], $map); - } - } - } - } - } - } - - /** - * Map DN values from DN-specific internal format to - * ANY type. - * - * @param array ref $root - * @param string $path - * @access private - */ - private function mapOutDNs(&$root, $path) - { - $dns = &$this->subArray($root, $path); - - if (is_array($dns)) { - $size = count($dns); - for ($i = 0; $i < $size; $i++) { - for ($j = 0; $j < count($dns[$i]); $j++) { - $type = $dns[$i][$j]['type']; - $value = &$dns[$i][$j]['value']; - if (is_object($value) && $value instanceof Element) { - continue; - } - - $map = $this->getMapping($type); - if (!is_bool($map)) { - $value = new Element(ASN1::encodeDER($value, $map)); - } - } - } - } - } - - /** - * Associate an extension ID to an extension mapping - * - * @param string $extnId - * @access private - * @return mixed - */ - private function getMapping($extnId) - { - if (!is_string($extnId)) { // eg. if it's a \phpseclib\File\ASN1\Element object - return true; - } - - switch ($extnId) { - case 'id-ce-keyUsage': - return Maps\KeyUsage::MAP; - case 'id-ce-basicConstraints': - return Maps\BasicConstraints::MAP; - case 'id-ce-subjectKeyIdentifier': - return Maps\KeyIdentifier::MAP; - case 'id-ce-cRLDistributionPoints': - return Maps\CRLDistributionPoints::MAP; - case 'id-ce-authorityKeyIdentifier': - return Maps\AuthorityKeyIdentifier::MAP; - case 'id-ce-certificatePolicies': - return Maps\CertificatePolicies::MAP; - case 'id-ce-extKeyUsage': - return Maps\ExtKeyUsageSyntax::MAP; - case 'id-pe-authorityInfoAccess': - return Maps\AuthorityInfoAccessSyntax::MAP; - case 'id-ce-subjectAltName': - return Maps\SubjectAltName::MAP; - case 'id-ce-subjectDirectoryAttributes': - return Maps\SubjectDirectoryAttributes::MAP; - case 'id-ce-privateKeyUsagePeriod': - return Maps\PrivateKeyUsagePeriod::MAP; - case 'id-ce-issuerAltName': - return Maps\IssuerAltName::MAP; - case 'id-ce-policyMappings': - return Maps\PolicyMappings::MAP; - case 'id-ce-nameConstraints': - return Maps\NameConstraints::MAP; - - case 'netscape-cert-type': - return Maps\netscape_cert_type::MAP; - case 'netscape-comment': - return Maps\netscape_comment::MAP; - case 'netscape-ca-policy-url': - return Maps\netscape_ca_policy_url::MAP; - - // since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets - // back around to asn1map() and we don't want it decoded again. - //case 'id-qt-cps': - // return Maps\CPSuri::MAP; - case 'id-qt-unotice': - return Maps\UserNotice::MAP; - - // the following OIDs are unsupported but we don't want them to give notices when calling saveX509(). - case 'id-pe-logotype': // http://www.ietf.org/rfc/rfc3709.txt - case 'entrustVersInfo': - // http://support.microsoft.com/kb/287547 - case '1.3.6.1.4.1.311.20.2': // szOID_ENROLL_CERTTYPE_EXTENSION - case '1.3.6.1.4.1.311.21.1': // szOID_CERTSRV_CA_VERSION - // "SET Secure Electronic Transaction Specification" - // http://www.maithean.com/docs/set_bk3.pdf - case '2.23.42.7.0': // id-set-hashedRootKey - // "Certificate Transparency" - // https://tools.ietf.org/html/rfc6962 - case '1.3.6.1.4.1.11129.2.4.2': - return true; - - // CSR attributes - case 'pkcs-9-at-unstructuredName': - return Maps\PKCS9String::MAP; - case 'pkcs-9-at-challengePassword': - return Maps\DirectoryString::MAP; - case 'pkcs-9-at-extensionRequest': - return Maps\Extensions::MAP; - - // CRL extensions. - case 'id-ce-cRLNumber': - return Maps\CRLNumber::MAP; - case 'id-ce-deltaCRLIndicator': - return Maps\CRLNumber::MAP; - case 'id-ce-issuingDistributionPoint': - return Maps\IssuingDistributionPoint::MAP; - case 'id-ce-freshestCRL': - return Maps\CRLDistributionPoints::MAP; - case 'id-ce-cRLReasons': - return Maps\CRLReason::MAP; - case 'id-ce-invalidityDate': - return Maps\InvalidityDate::MAP; - case 'id-ce-certificateIssuer': - return Maps\CertificateIssuer::MAP; - case 'id-ce-holdInstructionCode': - return Maps\HoldInstructionCode::MAP; - case 'id-at-postalAddress': - return Maps\PostalAddress::MAP; - } - - return false; - } - - /** - * Load an X.509 certificate as a certificate authority - * - * @param string $cert - * @access public - * @return bool - */ - public function loadCA($cert) - { - $olddn = $this->dn; - $oldcert = $this->currentCert; - $oldsigsubj = $this->signatureSubject; - $oldkeyid = $this->currentKeyIdentifier; - - $cert = $this->loadX509($cert); - if (!$cert) { - $this->dn = $olddn; - $this->currentCert = $oldcert; - $this->signatureSubject = $oldsigsubj; - $this->currentKeyIdentifier = $oldkeyid; - - return false; - } - - /* From RFC5280 "PKIX Certificate and CRL Profile": - - If the keyUsage extension is present, then the subject public key - MUST NOT be used to verify signatures on certificates or CRLs unless - the corresponding keyCertSign or cRLSign bit is set. */ - //$keyUsage = $this->getExtension('id-ce-keyUsage'); - //if ($keyUsage && !in_array('keyCertSign', $keyUsage)) { - // return false; - //} - - /* From RFC5280 "PKIX Certificate and CRL Profile": - - The cA boolean indicates whether the certified public key may be used - to verify certificate signatures. If the cA boolean is not asserted, - then the keyCertSign bit in the key usage extension MUST NOT be - asserted. If the basic constraints extension is not present in a - version 3 certificate, or the extension is present but the cA boolean - is not asserted, then the certified public key MUST NOT be used to - verify certificate signatures. */ - //$basicConstraints = $this->getExtension('id-ce-basicConstraints'); - //if (!$basicConstraints || !$basicConstraints['cA']) { - // return false; - //} - - $this->CAs[] = $cert; - - $this->dn = $olddn; - $this->currentCert = $oldcert; - $this->signatureSubject = $oldsigsubj; - - return true; - } - - /** - * Validate an X.509 certificate against a URL - * - * From RFC2818 "HTTP over TLS": - * - * Matching is performed using the matching rules specified by - * [RFC2459]. If more than one identity of a given type is present in - * the certificate (e.g., more than one dNSName name, a match in any one - * of the set is considered acceptable.) Names may contain the wildcard - * character * which is considered to match any single domain name - * component or component fragment. E.g., *.a.com matches foo.a.com but - * not bar.foo.a.com. f*.com matches foo.com but not bar.com. - * - * @param string $url - * @access public - * @return bool - */ - public function validateURL($url) - { - if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { - return false; - } - - $components = parse_url($url); - if (!isset($components['host'])) { - return false; - } - - if ($names = $this->getExtension('id-ce-subjectAltName')) { - foreach ($names as $key => $value) { - $value = str_replace(['.', '*'], ['\.', '[^.]*'], $value); - switch ($key) { - case 'dNSName': - /* From RFC2818 "HTTP over TLS": - - If a subjectAltName extension of type dNSName is present, that MUST - be used as the identity. Otherwise, the (most specific) Common Name - field in the Subject field of the certificate MUST be used. Although - the use of the Common Name is existing practice, it is deprecated and - Certification Authorities are encouraged to use the dNSName instead. */ - if (preg_match('#^' . $value . '$#', $components['host'])) { - return true; - } - break; - case 'iPAddress': - /* From RFC2818 "HTTP over TLS": - - In some cases, the URI is specified as an IP address rather than a - hostname. In this case, the iPAddress subjectAltName must be present - in the certificate and must exactly match the IP in the URI. */ - if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) { - return true; - } - } - } - return false; - } - - if ($value = $this->getDNProp('id-at-commonName')) { - $value = str_replace(['.', '*'], ['\.', '[^.]*'], $value[0]); - return preg_match('#^' . $value . '$#', $components['host']); - } - - return false; - } - - /** - * Validate a date - * - * If $date isn't defined it is assumed to be the current date. - * - * @param int $date optional - * @access public - */ - public function validateDate($date = null) - { - if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { - return false; - } - - if (!isset($date)) { - $date = time(); - } - - $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore']; - $notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime']; - - $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter']; - $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime']; - - switch (true) { - case $date < @strtotime($notBefore): - case $date > @strtotime($notAfter): - return false; - } - - return true; - } - - /** - * Validate a signature - * - * Works on X.509 certs, CSR's and CRL's. - * Returns true if the signature is verified, false if it is not correct or null on error - * - * By default returns false for self-signed certs. Call validateSignature(false) to make this support - * self-signed. - * - * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}. - * - * @param bool $caonly optional - * @access public - * @return mixed - */ - public function validateSignature($caonly = true) - { - if (!is_array($this->currentCert) || !isset($this->signatureSubject)) { - return null; - } - - /* TODO: - "emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")." - -- http://tools.ietf.org/html/rfc5280#section-4.1.2.6 - - implement pathLenConstraint in the id-ce-basicConstraints extension */ - - switch (true) { - case isset($this->currentCert['tbsCertificate']): - // self-signed cert - switch (true) { - case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']: - case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING): - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier'); - switch (true) { - case !is_array($authorityKey): - case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - $signingCert = $this->currentCert; // working cert - } - } - - if (!empty($this->CAs)) { - for ($i = 0; $i < count($this->CAs); $i++) { - // even if the cert is a self-signed one we still want to see if it's a CA; - // if not, we'll conditionally return an error - $ca = $this->CAs[$i]; - switch (true) { - case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']: - case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']): - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); - switch (true) { - case !is_array($authorityKey): - case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - $signingCert = $ca; // working cert - break 3; - } - } - } - if (count($this->CAs) == $i && $caonly) { - return false; - } - } elseif (!isset($signingCert) || $caonly) { - return false; - } - return $this->validateSignatureHelper( - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - case isset($this->currentCert['certificationRequestInfo']): - return $this->validateSignatureHelper( - $this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'], - $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - case isset($this->currentCert['publicKeyAndChallenge']): - return $this->validateSignatureHelper( - $this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'], - $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - case isset($this->currentCert['tbsCertList']): - if (!empty($this->CAs)) { - for ($i = 0; $i < count($this->CAs); $i++) { - $ca = $this->CAs[$i]; - switch (true) { - case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']: - case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']): - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); - switch (true) { - case !is_array($authorityKey): - case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - $signingCert = $ca; // working cert - break 3; - } - } - } - } - if (!isset($signingCert)) { - return false; - } - return $this->validateSignatureHelper( - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - default: - return false; - } - } - - /** - * Validates a signature - * - * Returns true if the signature is verified and false if it is not correct. - * If the algorithms are unsupposed an exception is thrown. - * - * @param string $publicKeyAlgorithm - * @param string $publicKey - * @param string $signatureAlgorithm - * @param string $signature - * @param string $signatureSubject - * @access private - * @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @return bool - */ - private function validateSignatureHelper($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject) - { - switch ($publicKeyAlgorithm) { - case 'rsaEncryption': - $rsa = new RSA(); - $rsa->load($publicKey); - - switch ($signatureAlgorithm) { - case 'md2WithRSAEncryption': - case 'md5WithRSAEncryption': - case 'sha1WithRSAEncryption': - case 'sha224WithRSAEncryption': - case 'sha256WithRSAEncryption': - case 'sha384WithRSAEncryption': - case 'sha512WithRSAEncryption': - $rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm)); - if (!@$rsa->verify($signatureSubject, $signature, RSA::PADDING_PKCS1)) { - return false; - } - break; - default: - throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); - } - break; - default: - throw new UnsupportedAlgorithmException('Public key algorithm unsupported'); - } - - return true; - } - - /** - * Reformat public keys - * - * Reformats a public key to a format supported by phpseclib (if applicable) - * - * @param string $algorithm - * @param string $key - * @access private - * @return string - */ - private function reformatKey($algorithm, $key) - { - switch ($algorithm) { - case 'rsaEncryption': - return - "-----BEGIN RSA PUBLIC KEY-----\r\n" . - // subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits - // in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox - // uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do. - chunk_split(Base64::encode(substr($key, 1)), 64) . - '-----END RSA PUBLIC KEY-----'; - default: - return $key; - } - } - - /** - * Decodes an IP address - * - * Takes in a base64 encoded "blob" and returns a human readable IP address - * - * @param string $ip - * @access private - * @return string - */ - public function decodeIP($ip) - { - return inet_ntop($ip); - } - - /** - * Encodes an IP address - * - * Takes a human readable IP address into a base64-encoded "blob" - * - * @param string $ip - * @access private - * @return string - */ - public function encodeIP($ip) - { - return inet_pton($ip); - } - - /** - * "Normalizes" a Distinguished Name property - * - * @param string $propName - * @access private - * @return mixed - */ - private function translateDNProp($propName) - { - switch (strtolower($propName)) { - case 'id-at-countryname': - case 'countryname': - case 'c': - return 'id-at-countryName'; - case 'id-at-organizationname': - case 'organizationname': - case 'o': - return 'id-at-organizationName'; - case 'id-at-dnqualifier': - case 'dnqualifier': - return 'id-at-dnQualifier'; - case 'id-at-commonname': - case 'commonname': - case 'cn': - return 'id-at-commonName'; - case 'id-at-stateorprovincename': - case 'stateorprovincename': - case 'state': - case 'province': - case 'provincename': - case 'st': - return 'id-at-stateOrProvinceName'; - case 'id-at-localityname': - case 'localityname': - case 'l': - return 'id-at-localityName'; - case 'id-emailaddress': - case 'emailaddress': - return 'pkcs-9-at-emailAddress'; - case 'id-at-serialnumber': - case 'serialnumber': - return 'id-at-serialNumber'; - case 'id-at-postalcode': - case 'postalcode': - return 'id-at-postalCode'; - case 'id-at-streetaddress': - case 'streetaddress': - return 'id-at-streetAddress'; - case 'id-at-name': - case 'name': - return 'id-at-name'; - case 'id-at-givenname': - case 'givenname': - return 'id-at-givenName'; - case 'id-at-surname': - case 'surname': - case 'sn': - return 'id-at-surname'; - case 'id-at-initials': - case 'initials': - return 'id-at-initials'; - case 'id-at-generationqualifier': - case 'generationqualifier': - return 'id-at-generationQualifier'; - case 'id-at-organizationalunitname': - case 'organizationalunitname': - case 'ou': - return 'id-at-organizationalUnitName'; - case 'id-at-pseudonym': - case 'pseudonym': - return 'id-at-pseudonym'; - case 'id-at-title': - case 'title': - return 'id-at-title'; - case 'id-at-description': - case 'description': - return 'id-at-description'; - case 'id-at-role': - case 'role': - return 'id-at-role'; - case 'id-at-uniqueidentifier': - case 'uniqueidentifier': - case 'x500uniqueidentifier': - return 'id-at-uniqueIdentifier'; - case 'postaladdress': - case 'id-at-postaladdress': - return 'id-at-postalAddress'; - default: - return false; - } - } - - /** - * Set a Distinguished Name property - * - * @param string $propName - * @param mixed $propValue - * @param string $type optional - * @access public - * @return bool - */ - public function setDNProp($propName, $propValue, $type = 'utf8String') - { - if (empty($this->dn)) { - $this->dn = ['rdnSequence' => []]; - } - - if (($propName = $this->translateDNProp($propName)) === false) { - return false; - } - - foreach ((array) $propValue as $v) { - if (!is_array($v) && isset($type)) { - $v = [$type => $v]; - } - $this->dn['rdnSequence'][] = [ - [ - 'type' => $propName, - 'value'=> $v - ] - ]; - } - - return true; - } - - /** - * Remove Distinguished Name properties - * - * @param string $propName - * @access public - */ - public function removeDNProp($propName) - { - if (empty($this->dn)) { - return; - } - - if (($propName = $this->translateDNProp($propName)) === false) { - return; - } - - $dn = &$this->dn['rdnSequence']; - $size = count($dn); - for ($i = 0; $i < $size; $i++) { - if ($dn[$i][0]['type'] == $propName) { - unset($dn[$i]); - } - } - - $dn = array_values($dn); - } - - /** - * Get Distinguished Name properties - * - * @param string $propName - * @param array $dn optional - * @param bool $withType optional - * @return mixed - * @access public - */ - public function getDNProp($propName, $dn = null, $withType = false) - { - if (!isset($dn)) { - $dn = $this->dn; - } - - if (empty($dn)) { - return false; - } - - if (($propName = $this->translateDNProp($propName)) === false) { - return false; - } - - $filters = []; - $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $this->mapOutDNs($dn, 'rdnSequence'); - $dn = $dn['rdnSequence']; - $result = []; - for ($i = 0; $i < count($dn); $i++) { - if ($dn[$i][0]['type'] == $propName) { - $v = $dn[$i][0]['value']; - if (!$withType) { - if (is_array($v)) { - foreach ($v as $type => $s) { - $type = array_search($type, ASN1::ANY_MAP); - if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) { - $s = ASN1::convert($s, $type); - if ($s !== false) { - $v = $s; - break; - } - } - } - if (is_array($v)) { - $v = array_pop($v); // Always strip data type. - } - } elseif (is_object($v) && $v instanceof Element) { - $map = $this->getMapping($propName); - if (!is_bool($map)) { - $decoded = ASN1::decodeBER($v); - $v = ASN1::asn1map($decoded[0], $map); - } - } - } - $result[] = $v; - } - } - - return $result; - } - - /** - * Set a Distinguished Name - * - * @param mixed $dn - * @param bool $merge optional - * @param string $type optional - * @access public - * @return bool - */ - public function setDN($dn, $merge = false, $type = 'utf8String') - { - if (!$merge) { - $this->dn = null; - } - - if (is_array($dn)) { - if (isset($dn['rdnSequence'])) { - $this->dn = $dn; // No merge here. - return true; - } - - // handles stuff generated by openssl_x509_parse() - foreach ($dn as $prop => $value) { - if (!$this->setDNProp($prop, $value, $type)) { - return false; - } - } - return true; - } - - // handles everything else - $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE); - for ($i = 1; $i < count($results); $i+=2) { - $prop = trim($results[$i], ', =/'); - $value = $results[$i + 1]; - if (!$this->setDNProp($prop, $value, $type)) { - return false; - } - } - - return true; - } - - /** - * Get the Distinguished Name for a certificates subject - * - * @param mixed $format optional - * @param array $dn optional - * @access public - * @return bool - */ - public function getDN($format = self::DN_ARRAY, $dn = null) - { - if (!isset($dn)) { - $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn; - } - - switch ((int) $format) { - case self::DN_ARRAY: - return $dn; - case self::DN_ASN1: - $filters = []; - $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $this->mapOutDNs($dn, 'rdnSequence'); - return ASN1::encodeDER($dn, Maps\Name::MAP); - case self::DN_CANON: - // No SEQUENCE around RDNs and all string values normalized as - // trimmed lowercase UTF-8 with all spacing as one blank. - // constructed RDNs will not be canonicalized - $filters = []; - $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $result = ''; - $this->mapOutDNs($dn, 'rdnSequence'); - foreach ($dn['rdnSequence'] as $rdn) { - foreach ($rdn as $i => $attr) { - $attr = &$rdn[$i]; - if (is_array($attr['value'])) { - foreach ($attr['value'] as $type => $v) { - $type = array_search($type, ASN1::ANY_MAP, true); - if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) { - $v = ASN1::convert($v, $type); - if ($v !== false) { - $v = preg_replace('/\s+/', ' ', $v); - $attr['value'] = strtolower(trim($v)); - break; - } - } - } - } - } - $result .= ASN1::encodeDER($rdn, Maps\RelativeDistinguishedName::MAP); - } - return $result; - case self::DN_HASH: - $dn = $this->getDN(self::DN_CANON, $dn); - $hash = new Hash('sha1'); - $hash = $hash->hash($dn); - extract(unpack('Vhash', $hash)); - return strtolower(Hex::encode(pack('N', $hash))); - } - - // Default is to return a string. - $start = true; - $output = ''; - - $result = []; - $filters = []; - $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $this->mapOutDNs($dn, 'rdnSequence'); - - foreach ($dn['rdnSequence'] as $field) { - $prop = $field[0]['type']; - $value = $field[0]['value']; - - $delim = ', '; - switch ($prop) { - case 'id-at-countryName': - $desc = 'C'; - break; - case 'id-at-stateOrProvinceName': - $desc = 'ST'; - break; - case 'id-at-organizationName': - $desc = 'O'; - break; - case 'id-at-organizationalUnitName': - $desc = 'OU'; - break; - case 'id-at-commonName': - $desc = 'CN'; - break; - case 'id-at-localityName': - $desc = 'L'; - break; - case 'id-at-surname': - $desc = 'SN'; - break; - case 'id-at-uniqueIdentifier': - $delim = '/'; - $desc = 'x500UniqueIdentifier'; - break; - case 'id-at-postalAddress': - $delim = '/'; - $desc = 'postalAddress'; - break; - default: - $delim = '/'; - $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop); - } - - if (!$start) { - $output.= $delim; - } - if (is_array($value)) { - foreach ($value as $type => $v) { - $type = array_search($type, ASN1::ANY_MAP, true); - if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) { - $v = ASN1::convert($v, $type); - if ($v !== false) { - $value = $v; - break; - } - } - } - if (is_array($value)) { - $value = array_pop($value); // Always strip data type. - } - } elseif (is_object($value) && $value instanceof Element) { - $callback = function($x) { return '\x' . bin2hex($x[0]); }; - $value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element)); - } - $output.= $desc . '=' . $value; - $result[$desc] = isset($result[$desc]) ? - array_merge((array) $dn[$prop], [$value]) : - $value; - $start = false; - } - - return $format == self::DN_OPENSSL ? $result : $output; - } - - /** - * Get the Distinguished Name for a certificate/crl issuer - * - * @param int $format optional - * @access public - * @return mixed - */ - public function getIssuerDN($format = self::DN_ARRAY) - { - switch (true) { - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']); - case isset($this->currentCert['tbsCertList']): - return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']); - } - - return false; - } - - /** - * Get the Distinguished Name for a certificate/csr subject - * Alias of getDN() - * - * @param int $format optional - * @access public - * @return mixed - */ - public function getSubjectDN($format = self::DN_ARRAY) - { - switch (true) { - case !empty($this->dn): - return $this->getDN($format); - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']); - case isset($this->currentCert['certificationRequestInfo']): - return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']); - } - - return false; - } - - /** - * Get an individual Distinguished Name property for a certificate/crl issuer - * - * @param string $propName - * @param bool $withType optional - * @access public - * @return mixed - */ - public function getIssuerDNProp($propName, $withType = false) - { - switch (true) { - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType); - case isset($this->currentCert['tbsCertList']): - return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType); - } - - return false; - } - - /** - * Get an individual Distinguished Name property for a certificate/csr subject - * - * @param string $propName - * @param bool $withType optional - * @access public - * @return mixed - */ - public function getSubjectDNProp($propName, $withType = false) - { - switch (true) { - case !empty($this->dn): - return $this->getDNProp($propName, null, $withType); - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType); - case isset($this->currentCert['certificationRequestInfo']): - return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType); - } - - return false; - } - - /** - * Get the certificate chain for the current cert - * - * @access public - * @return mixed - */ - public function getChain() - { - $chain = [$this->currentCert]; - - if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { - return false; - } - if (empty($this->CAs)) { - return $chain; - } - while (true) { - $currentCert = $chain[count($chain) - 1]; - for ($i = 0; $i < count($this->CAs); $i++) { - $ca = $this->CAs[$i]; - if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) { - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); - switch (true) { - case !is_array($authorityKey): - case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - if ($currentCert === $ca) { - break 3; - } - $chain[] = $ca; - break 2; - } - } - } - if ($i == count($this->CAs)) { - break; - } - } - foreach ($chain as $key => $value) { - $chain[$key] = new X509(); - $chain[$key]->loadX509($value); - } - return $chain; - } - - /** - * Set public key - * - * Key needs to be a \phpseclib\Crypt\RSA object - * - * @param object $key - * @access public - * @return bool - */ - public function setPublicKey($key) - { - $key->setPublicKey(); - $this->publicKey = $key; - } - - /** - * Set private key - * - * Key needs to be a \phpseclib\Crypt\RSA object - * - * @param object $key - * @access public - */ - public function setPrivateKey($key) - { - $this->privateKey = $key; - } - - /** - * Set challenge - * - * Used for SPKAC CSR's - * - * @param string $challenge - * @access public - */ - public function setChallenge($challenge) - { - $this->challenge = $challenge; - } - - /** - * Gets the public key - * - * Returns a \phpseclib\Crypt\RSA object or a false. - * - * @access public - * @return mixed - */ - public function getPublicKey() - { - if (isset($this->publicKey)) { - return $this->publicKey; - } - - if (isset($this->currentCert) && is_array($this->currentCert)) { - foreach (['tbsCertificate/subjectPublicKeyInfo', 'certificationRequestInfo/subjectPKInfo'] as $path) { - $keyinfo = $this->subArray($this->currentCert, $path); - if (!empty($keyinfo)) { - break; - } - } - } - if (empty($keyinfo)) { - return false; - } - - $key = $keyinfo['subjectPublicKey']; - - switch ($keyinfo['algorithm']['algorithm']) { - case 'rsaEncryption': - $publicKey = new RSA(); - $publicKey->load($key); - $publicKey->setPublicKey(); - break; - default: - return false; - } - - return $publicKey; - } - - /** - * Load a Certificate Signing Request - * - * @param string $csr - * @access public - * @return mixed - */ - public function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT) - { - if (is_array($csr) && isset($csr['certificationRequestInfo'])) { - unset($this->currentCert); - unset($this->currentKeyIdentifier); - unset($this->signatureSubject); - $this->dn = $csr['certificationRequestInfo']['subject']; - if (!isset($this->dn)) { - return false; - } - - $this->currentCert = $csr; - return $csr; - } - - // see http://tools.ietf.org/html/rfc2986 - - if ($mode != self::FORMAT_DER) { - $newcsr = ASN1::extractBER($csr); - if ($mode == self::FORMAT_PEM && $csr == $newcsr) { - return false; - } - $csr = $newcsr; - } - $orig = $csr; - - if ($csr === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($csr); - - if (empty($decoded)) { - $this->currentCert = false; - return false; - } - - $csr = ASN1::asn1map($decoded[0], Maps\CertificationRequest::MAP); - if (!isset($csr) || $csr === false) { - $this->currentCert = false; - return false; - } - - $this->mapInAttributes($csr, 'certificationRequestInfo/attributes'); - $this->mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence'); - - $this->dn = $csr['certificationRequestInfo']['subject']; - - $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - $algorithm = &$csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm']; - $key = &$csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']; - $key = $this->reformatKey($algorithm, $key); - - switch ($algorithm) { - case 'rsaEncryption': - $this->publicKey = new RSA(); - $this->publicKey->load($key); - $this->publicKey->setPublicKey(); - break; - default: - $this->publicKey = null; - } - - $this->currentKeyIdentifier = null; - $this->currentCert = $csr; - - return $csr; - } - - /** - * Save CSR request - * - * @param array $csr - * @param int $format optional - * @access public - * @return string - */ - public function saveCSR($csr, $format = self::FORMAT_PEM) - { - if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) { - return false; - } - - switch (true) { - case !($algorithm = $this->subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')): - case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']): - break; - default: - switch ($algorithm) { - case 'rsaEncryption': - $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'] - = Base64::encode("\0" . Base64::decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']))); - $csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['parameters'] = null; - $csr['signatureAlgorithm']['parameters'] = null; - $csr['certificationRequestInfo']['signature']['parameters'] = null; - } - } - - $filters = []; - $filters['certificationRequestInfo']['subject']['rdnSequence']['value'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - - ASN1::setFilters($filters); - - $this->mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence'); - $this->mapOutAttributes($csr, 'certificationRequestInfo/attributes'); - $csr = ASN1::encodeDER($csr, Maps\CertificationRequest::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $csr; - // case self::FORMAT_PEM: - default: - return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(Base64::encode($csr), 64) . '-----END CERTIFICATE REQUEST-----'; - } - } - - /** - * Load a SPKAC CSR - * - * SPKAC's are produced by the HTML5 keygen element: - * - * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen - * - * @param string $csr - * @access public - * @return mixed - */ - public function loadSPKAC($spkac) - { - if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) { - unset($this->currentCert); - unset($this->currentKeyIdentifier); - unset($this->signatureSubject); - $this->currentCert = $spkac; - return $spkac; - } - - // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge - - // OpenSSL produces SPKAC's that are preceded by the string SPKAC= - $temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac); - $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false; - if ($temp != false) { - $spkac = $temp; - } - $orig = $spkac; - - if ($spkac === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($spkac); - - if (empty($decoded)) { - $this->currentCert = false; - return false; - } - - $spkac = ASN1::asn1map($decoded[0], Maps\SignedPublicKeyAndChallenge::MAP); - - if (!isset($spkac) || $spkac === false) { - $this->currentCert = false; - return false; - } - - $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - $algorithm = &$spkac['publicKeyAndChallenge']['spki']['algorithm']['algorithm']; - $key = &$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']; - $key = $this->reformatKey($algorithm, $key); - - switch ($algorithm) { - case 'rsaEncryption': - $this->publicKey = new RSA(); - $this->publicKey->load($key); - $this->publicKey->setPublicKey(); - break; - default: - $this->publicKey = null; - } - - $this->currentKeyIdentifier = null; - $this->currentCert = $spkac; - - return $spkac; - } - - /** - * Save a SPKAC CSR request - * - * @param array $csr - * @param int $format optional - * @access public - * @return string - */ - public function saveSPKAC($spkac, $format = self::FORMAT_PEM) - { - if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) { - return false; - } - - $algorithm = $this->subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm'); - switch (true) { - case !$algorithm: - case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']): - break; - default: - switch ($algorithm) { - case 'rsaEncryption': - $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'] - = Base64::encode("\0" . Base64::decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']))); - } - } - - $spkac = ASN1::encodeDER($spkac, Maps\SignedPublicKeyAndChallenge::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $spkac; - // case self::FORMAT_PEM: - default: - // OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much - // no other SPKAC decoders phpseclib will use that same format - return 'SPKAC=' . Base64::encode($spkac); - } - } - - /** - * Load a Certificate Revocation List - * - * @param string $crl - * @access public - * @return mixed - */ - public function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT) - { - if (is_array($crl) && isset($crl['tbsCertList'])) { - $this->currentCert = $crl; - unset($this->signatureSubject); - return $crl; - } - - if ($mode != self::FORMAT_DER) { - $newcrl = ASN1::extractBER($crl); - if ($mode == self::FORMAT_PEM && $crl == $newcrl) { - return false; - } - $crl = $newcrl; - } - $orig = $crl; - - if ($crl === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($crl); - - if (empty($decoded)) { - $this->currentCert = false; - return false; - } - - $crl = ASN1::asn1map($decoded[0], Maps\CertificateList::MAP); - if (!isset($crl) || $crl === false) { - $this->currentCert = false; - return false; - } - - $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - $this->mapInDNs($crl, 'tbsCertList/issuer/rdnSequence'); - if ($this->isSubArrayValid($crl, 'tbsCertList/crlExtensions')) { - $this->mapInExtensions($crl, 'tbsCertList/crlExtensions'); - } - if ($this->isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) { - $rclist_ref = &$this->subArrayUnchecked($crl, 'tbsCertList/revokedCertificates'); - if ($rclist_ref) { - $rclist = $crl['tbsCertList']['revokedCertificates']; - foreach ($rclist as $i => $extension) { - if ($this->isSubArrayValid($rclist, "$i/crlEntryExtensions")) { - $this->mapInExtensions($rclist_ref, "$i/crlEntryExtensions"); - } - } - } - } - - $this->currentKeyIdentifier = null; - $this->currentCert = $crl; - - return $crl; - } - - /** - * Save Certificate Revocation List. - * - * @param array $crl - * @param int $format optional - * @access public - * @return string - */ - public function saveCRL($crl, $format = self::FORMAT_PEM) - { - if (!is_array($crl) || !isset($crl['tbsCertList'])) { - return false; - } - - $filters = []; - $filters['tbsCertList']['issuer']['rdnSequence']['value'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - $filters['tbsCertList']['signature']['parameters'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - $filters['signatureAlgorithm']['parameters'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - - if (empty($crl['tbsCertList']['signature']['parameters'])) { - $filters['tbsCertList']['signature']['parameters'] - = ['type' => ASN1::TYPE_NULL]; - } - - if (empty($crl['signatureAlgorithm']['parameters'])) { - $filters['signatureAlgorithm']['parameters'] - = ['type' => ASN1::TYPE_NULL]; - } - - ASN1::setFilters($filters); - - $this->mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence'); - $this->mapOutExtensions($crl, 'tbsCertList/crlExtensions'); - $rclist = &$this->subArray($crl, 'tbsCertList/revokedCertificates'); - if (is_array($rclist)) { - foreach ($rclist as $i => $extension) { - $this->mapOutExtensions($rclist, "$i/crlEntryExtensions"); - } - } - - $crl = ASN1::encodeDER($crl, Maps\CertificateList::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $crl; - // case self::FORMAT_PEM: - default: - return "-----BEGIN X509 CRL-----\r\n" . chunk_split(Base64::encode($crl), 64) . '-----END X509 CRL-----'; - } - } - - /** - * Helper function to build a time field according to RFC 3280 section - * - 4.1.2.5 Validity - * - 5.1.2.4 This Update - * - 5.1.2.5 Next Update - * - 5.1.2.6 Revoked Certificates - * by choosing utcTime iff year of date given is before 2050 and generalTime else. - * - * @param string $date in format date('D, d M Y H:i:s O') - * @access private - * @return array - */ - private function timeField($date) - { - $year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this - if ($year < 2050) { - return ['utcTime' => $date]; - } else { - return ['generalTime' => $date]; - } - } - - /** - * Sign an X.509 certificate - * - * $issuer's private key needs to be loaded. - * $subject can be either an existing X.509 cert (if you want to resign it), - * a CSR or something with the DN and public key explicitly set. - * - * @param \phpseclib\File\X509 $issuer - * @param \phpseclib\File\X509 $subject - * @param string $signatureAlgorithm optional - * @access public - * @return mixed - */ - public function sign($issuer, $subject, $signatureAlgorithm = 'sha256WithRSAEncryption') - { - if (!is_object($issuer->privateKey) || empty($issuer->dn)) { - return false; - } - - if (isset($subject->publicKey) && !($subjectPublicKey = $subject->formatSubjectPublicKey())) { - return false; - } - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; - - if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) { - $this->currentCert = $subject->currentCert; - $this->currentCert['tbsCertificate']['signature']['algorithm'] = $signatureAlgorithm; - $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; - - if (!empty($this->startDate)) { - $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->timeField($this->startDate); - } - if (!empty($this->endDate)) { - $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->timeField($this->endDate); - } - if (!empty($this->serialNumber)) { - $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber; - } - if (!empty($subject->dn)) { - $this->currentCert['tbsCertificate']['subject'] = $subject->dn; - } - if (!empty($subject->publicKey)) { - $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey; - } - $this->removeExtension('id-ce-authorityKeyIdentifier'); - if (isset($subject->domains)) { - $this->removeExtension('id-ce-subjectAltName'); - } - } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) { - return false; - } else { - if (!isset($subject->publicKey)) { - return false; - } - - $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); - $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year')); - /* "The serial number MUST be a positive integer" - "Conforming CAs MUST NOT use serialNumber values longer than 20 octets." - -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2 - - for the integer to be positive the leading bit needs to be 0 hence the - application of a bitmap - */ - $serialNumber = !empty($this->serialNumber) ? - $this->serialNumber : - new BigInteger(Random::string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256); - - $this->currentCert = [ - 'tbsCertificate' => - array( - 'version' => 'v3', - 'serialNumber' => $serialNumber, // $this->setserialNumber() - 'signature' => array('algorithm' => $signatureAlgorithm), - 'issuer' => false, // this is going to be overwritten later - 'validity' => [ - 'notBefore' => $this->timeField($startDate), // $this->setStartDate() - 'notAfter' => $this->timeField($endDate) // $this->setEndDate() - ], - 'subject' => $subject->dn, - 'subjectPublicKeyInfo' => $subjectPublicKey - ), - 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], - 'signature' => false // this is going to be overwritten later - ]; - - // Copy extensions from CSR. - $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0); - - if (!empty($csrexts)) { - $this->currentCert['tbsCertificate']['extensions'] = $csrexts; - } - } - - $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn; - - if (isset($issuer->currentKeyIdentifier)) { - $this->setExtension('id-ce-authorityKeyIdentifier', [ - //'authorityCertIssuer' => array( - // array( - // 'directoryName' => $issuer->dn - // ) - //), - 'keyIdentifier' => $issuer->currentKeyIdentifier - ]); - //$extensions = &$this->currentCert['tbsCertificate']['extensions']; - //if (isset($issuer->serialNumber)) { - // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; - //} - //unset($extensions); - } - - if (isset($subject->currentKeyIdentifier)) { - $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier); - } - - $altName = []; - - if (isset($subject->domains) && count($subject->domains) > 1) { - $altName = array_map(['\phpseclib\File\X509', 'dnsName'], $subject->domains); - } - - if (isset($subject->ipAddresses) && count($subject->ipAddresses)) { - // should an IP address appear as the CN if no domain name is specified? idk - //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1); - $ipAddresses = []; - foreach ($subject->ipAddresses as $ipAddress) { - $encoded = $subject->ipAddress($ipAddress); - if ($encoded !== false) { - $ipAddresses[] = $encoded; - } - } - if (count($ipAddresses)) { - $altName = array_merge($altName, $ipAddresses); - } - } - - if (!empty($altName)) { - $this->setExtension('id-ce-subjectAltName', $altName); - } - - if ($this->caFlag) { - $keyUsage = $this->getExtension('id-ce-keyUsage'); - if (!$keyUsage) { - $keyUsage = []; - } - - $this->setExtension( - 'id-ce-keyUsage', - array_values(array_unique(array_merge($keyUsage, ['cRLSign', 'keyCertSign']))) - ); - - $basicConstraints = $this->getExtension('id-ce-basicConstraints'); - if (!$basicConstraints) { - $basicConstraints = []; - } - - $this->setExtension( - 'id-ce-basicConstraints', - array_unique(array_merge(['cA' => true], $basicConstraints)), - true - ); - - if (!isset($subject->currentKeyIdentifier)) { - $this->setExtension('id-ce-subjectKeyIdentifier', $this->computeKeyIdentifier($this->currentCert), false, false); - } - } - - // resync $this->signatureSubject - // save $tbsCertificate in case there are any \phpseclib\File\ASN1\Element objects in it - $tbsCertificate = $this->currentCert['tbsCertificate']; - $this->loadX509($this->saveX509($this->currentCert)); - - $result = $this->signHelper($issuer->privateKey, $signatureAlgorithm); - $result['tbsCertificate'] = $tbsCertificate; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * Sign a CSR - * - * @access public - * @return mixed - */ - public function signCSR($signatureAlgorithm = 'sha1WithRSAEncryption') - { - if (!is_object($this->privateKey) || empty($this->dn)) { - return false; - } - - $origPublicKey = $this->publicKey; - $class = get_class($this->privateKey); - $this->publicKey = new $class(); - $this->publicKey->load($this->privateKey->getPublicKey()); - $this->publicKey->setPublicKey(); - if (!($publicKey = $this->formatSubjectPublicKey())) { - return false; - } - $this->publicKey = $origPublicKey; - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; - - if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) { - $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; - if (!empty($this->dn)) { - $this->currentCert['certificationRequestInfo']['subject'] = $this->dn; - } - $this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey; - } else { - $this->currentCert = [ - 'certificationRequestInfo' => - [ - 'version' => 'v1', - 'subject' => $this->dn, - 'subjectPKInfo' => $publicKey - ], - 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], - 'signature' => false // this is going to be overwritten later - ]; - } - - // resync $this->signatureSubject - // save $certificationRequestInfo in case there are any \phpseclib\File\ASN1\Element objects in it - $certificationRequestInfo = $this->currentCert['certificationRequestInfo']; - $this->loadCSR($this->saveCSR($this->currentCert)); - - $result = $this->signHelper($this->privateKey, $signatureAlgorithm); - $result['certificationRequestInfo'] = $certificationRequestInfo; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * Sign a SPKAC - * - * @access public - * @return mixed - */ - public function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption') - { - if (!is_object($this->privateKey)) { - return false; - } - - $origPublicKey = $this->publicKey; - $class = get_class($this->privateKey); - $this->publicKey = new $class(); - $this->publicKey->load($this->privateKey->getPublicKey()); - $this->publicKey->setPublicKey(); - $publicKey = $this->formatSubjectPublicKey(); - if (!$publicKey) { - return false; - } - $this->publicKey = $origPublicKey; - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; - - // re-signing a SPKAC seems silly but since everything else supports re-signing why not? - if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) { - $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; - $this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey; - if (!empty($this->challenge)) { - // the bitwise AND ensures that the output is a valid IA5String - $this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("\x7F", strlen($this->challenge)); - } - } else { - $this->currentCert = [ - 'publicKeyAndChallenge' => - [ - 'spki' => $publicKey, - // quoting , - // "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified." - // both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way - // we could alternatively do this instead if we ignored the specs: - // Random::string(8) & str_repeat("\x7F", 8) - 'challenge' => !empty($this->challenge) ? $this->challenge : '' - ], - 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], - 'signature' => false // this is going to be overwritten later - ]; - } - - // resync $this->signatureSubject - // save $publicKeyAndChallenge in case there are any \phpseclib\File\ASN1\Element objects in it - $publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge']; - $this->loadSPKAC($this->saveSPKAC($this->currentCert)); - - $result = $this->signHelper($this->privateKey, $signatureAlgorithm); - $result['publicKeyAndChallenge'] = $publicKeyAndChallenge; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * Sign a CRL - * - * $issuer's private key needs to be loaded. - * - * @param \phpseclib\File\X509 $issuer - * @param \phpseclib\File\X509 $crl - * @param string $signatureAlgorithm optional - * @access public - * @return mixed - */ - public function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption') - { - if (!is_object($issuer->privateKey) || empty($issuer->dn)) { - return false; - } - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; - $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); - - if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) { - $this->currentCert = $crl->currentCert; - $this->currentCert['tbsCertList']['signature']['algorithm'] = $signatureAlgorithm; - $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; - } else { - $this->currentCert = [ - 'tbsCertList' => - [ - 'version' => 'v2', - 'signature' => ['algorithm' => $signatureAlgorithm], - 'issuer' => false, // this is going to be overwritten later - 'thisUpdate' => $this->timeField($thisUpdate) // $this->setStartDate() - ], - 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], - 'signature' => false // this is going to be overwritten later - ]; - } - - $tbsCertList = &$this->currentCert['tbsCertList']; - $tbsCertList['issuer'] = $issuer->dn; - $tbsCertList['thisUpdate'] = $this->timeField($thisUpdate); - - if (!empty($this->endDate)) { - $tbsCertList['nextUpdate'] = $this->timeField($this->endDate); // $this->setEndDate() - } else { - unset($tbsCertList['nextUpdate']); - } - - if (!empty($this->serialNumber)) { - $crlNumber = $this->serialNumber; - } else { - $crlNumber = $this->getExtension('id-ce-cRLNumber'); - // "The CRL number is a non-critical CRL extension that conveys a - // monotonically increasing sequence number for a given CRL scope and - // CRL issuer. This extension allows users to easily determine when a - // particular CRL supersedes another CRL." - // -- https://tools.ietf.org/html/rfc5280#section-5.2.3 - $crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null; - } - - $this->removeExtension('id-ce-authorityKeyIdentifier'); - $this->removeExtension('id-ce-issuerAltName'); - - // Be sure version >= v2 if some extension found. - $version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0; - if (!$version) { - if (!empty($tbsCertList['crlExtensions'])) { - $version = 1; // v2. - } elseif (!empty($tbsCertList['revokedCertificates'])) { - foreach ($tbsCertList['revokedCertificates'] as $cert) { - if (!empty($cert['crlEntryExtensions'])) { - $version = 1; // v2. - } - } - } - - if ($version) { - $tbsCertList['version'] = $version; - } - } - - // Store additional extensions. - if (!empty($tbsCertList['version'])) { // At least v2. - if (!empty($crlNumber)) { - $this->setExtension('id-ce-cRLNumber', $crlNumber); - } - - if (isset($issuer->currentKeyIdentifier)) { - $this->setExtension('id-ce-authorityKeyIdentifier', [ - //'authorityCertIssuer' => array( - // ] - // 'directoryName' => $issuer->dn - // ] - //), - 'keyIdentifier' => $issuer->currentKeyIdentifier - ]); - //$extensions = &$tbsCertList['crlExtensions']; - //if (isset($issuer->serialNumber)) { - // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; - //} - //unset($extensions); - } - - $issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert); - - if ($issuerAltName !== false) { - $this->setExtension('id-ce-issuerAltName', $issuerAltName); - } - } - - if (empty($tbsCertList['revokedCertificates'])) { - unset($tbsCertList['revokedCertificates']); - } - - unset($tbsCertList); - - // resync $this->signatureSubject - // save $tbsCertList in case there are any \phpseclib\File\ASN1\Element objects in it - $tbsCertList = $this->currentCert['tbsCertList']; - $this->loadCRL($this->saveCRL($this->currentCert)); - - $result = $this->signHelper($issuer->privateKey, $signatureAlgorithm); - $result['tbsCertList'] = $tbsCertList; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * X.509 certificate signing helper function. - * - * @param object $key - * @param \phpseclib\File\X509 $subject - * @param string $signatureAlgorithm - * @access public - * @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @return mixed - */ - private function signHelper($key, $signatureAlgorithm) - { - if ($key instanceof RSA) { - switch ($signatureAlgorithm) { - case 'md2WithRSAEncryption': - case 'md5WithRSAEncryption': - case 'sha1WithRSAEncryption': - case 'sha224WithRSAEncryption': - case 'sha256WithRSAEncryption': - case 'sha384WithRSAEncryption': - case 'sha512WithRSAEncryption': - $key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm)); - - $this->currentCert['signature'] = "\0" . $key->sign($this->signatureSubject, RSA::PADDING_PKCS1); - return $this->currentCert; - default: - throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); - } - } - - throw new UnsupportedAlgorithmException('Unsupported public key algorithm'); - } - - /** - * Set certificate start date - * - * @param string $date - * @access public - */ - public function setStartDate($date) - { - $this->startDate = @date('D, d M Y H:i:s O', @strtotime($date)); - } - - /** - * Set certificate end date - * - * @param string $date - * @access public - */ - public function setEndDate($date) - { - /* - To indicate that a certificate has no well-defined expiration date, - the notAfter SHOULD be assigned the GeneralizedTime value of - 99991231235959Z. - - -- http://tools.ietf.org/html/rfc5280#section-4.1.2.5 - */ - if (strtolower($date) == 'lifetime') { - $temp = '99991231235959Z'; - $temp = chr(ASN1::TYPE_GENERALIZED_TIME) . Functions::encodeLength(strlen($temp)) . $temp; - $this->endDate = new Element($temp); - } else { - $this->endDate = @date('D, d M Y H:i:s O', @strtotime($date)); - } - } - - /** - * Set Serial Number - * - * @param string $serial - * @param $base optional - * @access public - */ - public function setSerialNumber($serial, $base = -256) - { - $this->serialNumber = new BigInteger($serial, $base); - } - - /** - * Turns the certificate into a certificate authority - * - * @access public - */ - public function makeCA() - { - $this->caFlag = true; - } - - /** - * Check for validity of subarray - * - * This is intended for use in conjunction with _subArrayUnchecked(), - * implementing the checks included in _subArray() but without copying - * a potentially large array by passing its reference by-value to is_array(). - * - * @param array $root - * @param string $path - * @return boolean - * @access private - */ - private function isSubArrayValid($root, $path) - { - if (!is_array($root)) { - return false; - } - - foreach (explode('/', $path) as $i) { - if (!is_array($root)) { - return false; - } - - if (!isset($root[$i])) { - return true; - } - - $root = $root[$i]; - } - - return true; - } - - /** - * Get a reference to a subarray - * - * This variant of _subArray() does no is_array() checking, - * so $root should be checked with _isSubArrayValid() first. - * - * This is here for performance reasons: - * Passing a reference (i.e. $root) by-value (i.e. to is_array()) - * creates a copy. If $root is an especially large array, this is expensive. - * - * @param array $root - * @param string $path absolute path with / as component separator - * @param bool $create optional - * @access private - * @return array|false - */ - private function &subArrayUnchecked(&$root, $path, $create = false) - { - $false = false; - - foreach (explode('/', $path) as $i) { - if (!isset($root[$i])) { - if (!$create) { - return $false; - } - - $root[$i] = []; - } - - $root = &$root[$i]; - } - - return $root; - } - - /** - * Get a reference to a subarray - * - * @param array $root - * @param string $path absolute path with / as component separator - * @param bool $create optional - * @access private - * @return array|false - */ - private function &subArray(&$root, $path, $create = false) - { - $false = false; - - if (!is_array($root)) { - return $false; - } - - foreach (explode('/', $path) as $i) { - if (!is_array($root)) { - return $false; - } - - if (!isset($root[$i])) { - if (!$create) { - return $false; - } - - $root[$i] = []; - } - - $root = &$root[$i]; - } - - return $root; - } - - /** - * Get a reference to an extension subarray - * - * @param array $root - * @param string $path optional absolute path with / as component separator - * @param bool $create optional - * @access private - * @return array|false - */ - private function &extensions(&$root, $path = null, $create = false) - { - if (!isset($root)) { - $root = $this->currentCert; - } - - switch (true) { - case !empty($path): - case !is_array($root): - break; - case isset($root['tbsCertificate']): - $path = 'tbsCertificate/extensions'; - break; - case isset($root['tbsCertList']): - $path = 'tbsCertList/crlExtensions'; - break; - case isset($root['certificationRequestInfo']): - $pth = 'certificationRequestInfo/attributes'; - $attributes = &$this->subArray($root, $pth, $create); - - if (is_array($attributes)) { - foreach ($attributes as $key => $value) { - if ($value['type'] == 'pkcs-9-at-extensionRequest') { - $path = "$pth/$key/value/0"; - break 2; - } - } - if ($create) { - $key = count($attributes); - $attributes[] = ['type' => 'pkcs-9-at-extensionRequest', 'value' => []]; - $path = "$pth/$key/value/0"; - } - } - break; - } - - $extensions = &$this->subArray($root, $path, $create); - - if (!is_array($extensions)) { - $false = false; - return $false; - } - - return $extensions; - } - - /** - * Remove an Extension - * - * @param string $id - * @param string $path optional - * @access private - * @return bool - */ - private function removeExtensionHelper($id, $path = null) - { - $extensions = &$this->extensions($this->currentCert, $path); - - if (!is_array($extensions)) { - return false; - } - - $result = false; - foreach ($extensions as $key => $value) { - if ($value['extnId'] == $id) { - unset($extensions[$key]); - $result = true; - } - } - - $extensions = array_values($extensions); - return $result; - } - - /** - * Get an Extension - * - * Returns the extension if it exists and false if not - * - * @param string $id - * @param array $cert optional - * @param string $path optional - * @access private - * @return mixed - */ - private function getExtensionHelper($id, $cert = null, $path = null) - { - $extensions = $this->extensions($cert, $path); - - if (!is_array($extensions)) { - return false; - } - - foreach ($extensions as $key => $value) { - if ($value['extnId'] == $id) { - return $value['extnValue']; - } - } - - return false; - } - - /** - * Returns a list of all extensions in use - * - * @param array $cert optional - * @param string $path optional - * @access private - * @return array - */ - private function getExtensionsHelper($cert = null, $path = null) - { - $exts = $this->extensions($cert, $path); - $extensions = []; - - if (is_array($exts)) { - foreach ($exts as $extension) { - $extensions[] = $extension['extnId']; - } - } - - return $extensions; - } - - /** - * Set an Extension - * - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional - * @param string $path optional - * @access private - * @return bool - */ - private function setExtensionHelper($id, $value, $critical = false, $replace = true, $path = null) - { - $extensions = &$this->extensions($this->currentCert, $path, true); - - if (!is_array($extensions)) { - return false; - } - - $newext = ['extnId' => $id, 'critical' => $critical, 'extnValue' => $value]; - - foreach ($extensions as $key => $value) { - if ($value['extnId'] == $id) { - if (!$replace) { - return false; - } - - $extensions[$key] = $newext; - return true; - } - } - - $extensions[] = $newext; - return true; - } - - /** - * Remove a certificate, CSR or CRL Extension - * - * @param string $id - * @access public - * @return bool - */ - public function removeExtension($id) - { - return $this->removeExtensionHelper($id); - } - - /** - * Get a certificate, CSR or CRL Extension - * - * Returns the extension if it exists and false if not - * - * @param string $id - * @param array $cert optional - * @access public - * @return mixed - */ - public function getExtension($id, $cert = null) - { - return $this->getExtensionHelper($id, $cert); - } - - /** - * Returns a list of all extensions in use in certificate, CSR or CRL - * - * @param array $cert optional - * @access public - * @return array - */ - public function getExtensions($cert = null) - { - return $this->getExtensionsHelper($cert); - } - - /** - * Set a certificate, CSR or CRL Extension - * - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional - * @access public - * @return bool - */ - public function setExtension($id, $value, $critical = false, $replace = true) - { - return $this->setExtensionHelper($id, $value, $critical, $replace); - } - - /** - * Remove a CSR attribute. - * - * @param string $id - * @param int $disposition optional - * @access public - * @return bool - */ - public function removeAttribute($id, $disposition = self::ATTR_ALL) - { - $attributes = &$this->subArray($this->currentCert, 'certificationRequestInfo/attributes'); - - if (!is_array($attributes)) { - return false; - } - - $result = false; - foreach ($attributes as $key => $attribute) { - if ($attribute['type'] == $id) { - $n = count($attribute['value']); - switch (true) { - case $disposition == self::ATTR_APPEND: - case $disposition == self::ATTR_REPLACE: - return false; - case $disposition >= $n: - $disposition -= $n; - break; - case $disposition == self::ATTR_ALL: - case $n == 1: - unset($attributes[$key]); - $result = true; - break; - default: - unset($attributes[$key]['value'][$disposition]); - $attributes[$key]['value'] = array_values($attributes[$key]['value']); - $result = true; - break; - } - if ($result && $disposition != self::ATTR_ALL) { - break; - } - } - } - - $attributes = array_values($attributes); - return $result; - } - - /** - * Get a CSR attribute - * - * Returns the attribute if it exists and false if not - * - * @param string $id - * @param int $disposition optional - * @param array $csr optional - * @access public - * @return mixed - */ - public function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null) - { - if (empty($csr)) { - $csr = $this->currentCert; - } - - $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes'); - - if (!is_array($attributes)) { - return false; - } - - foreach ($attributes as $key => $attribute) { - if ($attribute['type'] == $id) { - $n = count($attribute['value']); - switch (true) { - case $disposition == self::ATTR_APPEND: - case $disposition == self::ATTR_REPLACE: - return false; - case $disposition == self::ATTR_ALL: - return $attribute['value']; - case $disposition >= $n: - $disposition -= $n; - break; - default: - return $attribute['value'][$disposition]; - } - } - } - - return false; - } - - /** - * Returns a list of all CSR attributes in use - * - * @param array $csr optional - * @access public - * @return array - */ - public function getAttributes($csr = null) - { - if (empty($csr)) { - $csr = $this->currentCert; - } - - $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes'); - $attrs = []; - - if (is_array($attributes)) { - foreach ($attributes as $attribute) { - $attrs[] = $attribute['type']; - } - } - - return $attrs; - } - - /** - * Set a CSR attribute - * - * @param string $id - * @param mixed $value - * @param bool $disposition optional - * @access public - * @return bool - */ - public function setAttribute($id, $value, $disposition = self::ATTR_ALL) - { - $attributes = &$this->subArray($this->currentCert, 'certificationRequestInfo/attributes', true); - - if (!is_array($attributes)) { - return false; - } - - switch ($disposition) { - case self::ATTR_REPLACE: - $disposition = self::ATTR_APPEND; - case self::ATTR_ALL: - $this->removeAttribute($id); - break; - } - - foreach ($attributes as $key => $attribute) { - if ($attribute['type'] == $id) { - $n = count($attribute['value']); - switch (true) { - case $disposition == self::ATTR_APPEND: - $last = $key; - break; - case $disposition >= $n: - $disposition -= $n; - break; - default: - $attributes[$key]['value'][$disposition] = $value; - return true; - } - } - } - - switch (true) { - case $disposition >= 0: - return false; - case isset($last): - $attributes[$last]['value'][] = $value; - break; - default: - $attributes[] = ['type' => $id, 'value' => $disposition == self::ATTR_ALL ? $value: [$value]]; - break; - } - - return true; - } - - /** - * Sets the subject key identifier - * - * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions. - * - * @param string $value - * @access public - */ - public function setKeyIdentifier($value) - { - if (empty($value)) { - unset($this->currentKeyIdentifier); - } else { - $this->currentKeyIdentifier = $value; - } - } - - /** - * Compute a public key identifier. - * - * Although key identifiers may be set to any unique value, this function - * computes key identifiers from public key according to the two - * recommended methods (4.2.1.2 RFC 3280). - * Highly polymorphic: try to accept all possible forms of key: - * - Key object - * - \phpseclib\File\X509 object with public or private key defined - * - Certificate or CSR array - * - \phpseclib\File\ASN1\Element object - * - PEM or DER string - * - * @param mixed $key optional - * @param int $method optional - * @access public - * @return string binary key identifier - */ - public function computeKeyIdentifier($key = null, $method = 1) - { - if (is_null($key)) { - $key = $this; - } - - switch (true) { - case is_string($key): - break; - case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']): - return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method); - case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']): - return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method); - case !is_object($key): - return false; - case $key instanceof Element: - // Assume the element is a bitstring-packed key. - $decoded = ASN1::decodeBER($key->element); - if (empty($decoded)) { - return false; - } - $raw = ASN1::asn1map($decoded[0], ['type' => ASN1::TYPE_BIT_STRING]); - if (empty($raw)) { - return false; - } - // If the key is private, compute identifier from its corresponding public key. - $key = new RSA(); - if (!$key->load($raw)) { - return false; // Not an unencrypted RSA key. - } - if ($key->getPrivateKey() !== false) { // If private. - return $this->computeKeyIdentifier($key, $method); - } - $key = $raw; // Is a public key. - break; - case $key instanceof X509: - if (isset($key->publicKey)) { - return $this->computeKeyIdentifier($key->publicKey, $method); - } - if (isset($key->privateKey)) { - return $this->computeKeyIdentifier($key->privateKey, $method); - } - if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) { - return $this->computeKeyIdentifier($key->currentCert, $method); - } - return false; - default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA). - $key = $key->getPublicKey('PKCS1'); - break; - } - - // If in PEM format, convert to binary. - $key = ASN1::extractBER($key); - - // Now we have the key string: compute its sha-1 sum. - $hash = new Hash('sha1'); - $hash = $hash->hash($key); - - if ($method == 2) { - $hash = substr($hash, -8); - $hash[0] = chr((ord($hash[0]) & 0x0F) | 0x40); - } - - return $hash; - } - - /** - * Format a public key as appropriate - * - * @access private - * @return array - */ - private function formatSubjectPublicKey() - { - if ($this->publicKey instanceof RSA) { - // the following two return statements do the same thing. i dunno.. i just prefer the later for some reason. - // the former is a good example of how to do fuzzing on the public key - //return new Element(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())); - return [ - 'algorithm' => array('algorithm' => 'rsaEncryption'), - 'subjectPublicKey' => $this->publicKey->getPublicKey('PKCS1') - ]; - } - - return false; - } - - /** - * Set the domain name's which the cert is to be valid for - * - * @access public - * @return array - */ - public function setDomain() - { - $this->domains = func_get_args(); - $this->removeDNProp('id-at-commonName'); - $this->setDNProp('id-at-commonName', $this->domains[0]); - } - - /** - * Set the IP Addresses's which the cert is to be valid for - * - * @access public - * @param string $ipAddress optional - */ - public function setIPAddress() - { - $this->ipAddresses = func_get_args(); - /* - if (!isset($this->domains)) { - $this->removeDNProp('id-at-commonName'); - $this->setDNProp('id-at-commonName', $this->ipAddresses[0]); - } - */ - } - - /** - * Helper function to build domain array - * - * @access private - * @param string $domain - * @return array - */ - private function dnsName($domain) - { - return ['dNSName' => $domain]; - } - - /** - * Helper function to build IP Address array - * - * (IPv6 is not currently supported) - * - * @access private - * @param string $address - * @return array - */ - private function iPAddress($address) - { - return ['iPAddress' => $address]; - } - - /** - * Get the index of a revoked certificate. - * - * @param array $rclist - * @param string $serial - * @param bool $create optional - * @access private - * @return int|false - */ - private function revokedCertificate(&$rclist, $serial, $create = false) - { - $serial = new BigInteger($serial); - - foreach ($rclist as $i => $rc) { - if (!($serial->compare($rc['userCertificate']))) { - return $i; - } - } - - if (!$create) { - return false; - } - - $i = count($rclist); - $rclist[] = ['userCertificate' => $serial, - 'revocationDate' => $this->timeField(@date('D, d M Y H:i:s O'))]; - return $i; - } - - /** - * Revoke a certificate. - * - * @param string $serial - * @param string $date optional - * @access public - * @return bool - */ - public function revoke($serial, $date = null) - { - if (isset($this->currentCert['tbsCertList'])) { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { - if ($this->revokedCertificate($rclist, $serial) === false) { // If not yet revoked - if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) { - if (!empty($date)) { - $rclist[$i]['revocationDate'] = $this->timeField($date); - } - - return true; - } - } - } - } - - return false; - } - - /** - * Unrevoke a certificate. - * - * @param string $serial - * @access public - * @return bool - */ - public function unrevoke($serial) - { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - unset($rclist[$i]); - $rclist = array_values($rclist); - return true; - } - } - - return false; - } - - /** - * Get a revoked certificate. - * - * @param string $serial - * @access public - * @return mixed - */ - public function getRevoked($serial) - { - if (is_array($rclist = $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $rclist[$i]; - } - } - - return false; - } - - /** - * List revoked certificates - * - * @param array $crl optional - * @access public - * @return array - */ - public function listRevoked($crl = null) - { - if (!isset($crl)) { - $crl = $this->currentCert; - } - - if (!isset($crl['tbsCertList'])) { - return false; - } - - $result = []; - - if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) { - foreach ($rclist as $rc) { - $result[] = $rc['userCertificate']->toString(); - } - } - - return $result; - } - - /** - * Remove a Revoked Certificate Extension - * - * @param string $serial - * @param string $id - * @access public - * @return bool - */ - public function removeRevokedCertificateExtension($serial, $id) - { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $this->removeExtensionHelper($id, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - - return false; - } - - /** - * Get a Revoked Certificate Extension - * - * Returns the extension if it exists and false if not - * - * @param string $serial - * @param string $id - * @param array $crl optional - * @access public - * @return mixed - */ - public function getRevokedCertificateExtension($serial, $id, $crl = null) - { - if (!isset($crl)) { - $crl = $this->currentCert; - } - - if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $this->getExtension($id, $crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - - return false; - } - - /** - * Returns a list of all extensions in use for a given revoked certificate - * - * @param string $serial - * @param array $crl optional - * @access public - * @return array - */ - public function getRevokedCertificateExtensions($serial, $crl = null) - { - if (!isset($crl)) { - $crl = $this->currentCert; - } - - if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $this->getExtensionsHelper($crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - - return false; - } - - /** - * Set a Revoked Certificate Extension - * - * @param string $serial - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional - * @access public - * @return bool - */ - public function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true) - { - if (isset($this->currentCert['tbsCertList'])) { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { - if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) { - return $this->setExtensionHelper($id, $value, $critical, $replace, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - } - - return false; - } -} diff --git a/lib/phpaes/phpseclib/Math/BigInteger.php b/lib/phpaes/phpseclib/Math/BigInteger.php deleted file mode 100644 index ed4c2c4031..0000000000 --- a/lib/phpaes/phpseclib/Math/BigInteger.php +++ /dev/null @@ -1,3886 +0,0 @@ -> and << cannot be used, nor can the modulo operator %, - * which only supports integers. Although this fact will slow this library down, the fact that such a high - * base is being used should more than compensate. - * - * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie. - * (new \phpseclib\Math\BigInteger(pow(2, 26)))->value = array(0, 1) - * - * Useful resources are as follows: - * - * - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)} - * - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)} - * - Java's BigInteger classes. See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip - * - * Here's an example of how to use this library: - * - * add($b); - * - * echo $c->toString(); // outputs 5 - * ?> - * - * - * @category Math - * @package BigInteger - * @author Jim Wigginton - * @copyright 2006 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib\Math; - -use ParagonIE\ConstantTime\Base64; -use ParagonIE\ConstantTime\Hex; -use phpseclib\Crypt\Random; -use phpseclib\File\ASN1; - -/** - * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256 - * numbers. - * - * @package BigInteger - * @author Jim Wigginton - * @access public - */ -class BigInteger -{ - /**#@+ - * Reduction constants - * - * @access private - * @see BigInteger::_reduce() - */ - /** - * @see BigInteger::_montgomery() - * @see BigInteger::_prepMontgomery() - */ - const MONTGOMERY = 0; - /** - * @see BigInteger::_barrett() - */ - const BARRETT = 1; - /** - * @see BigInteger::_mod2() - */ - const POWEROF2 = 2; - /** - * @see BigInteger::_remainder() - */ - const CLASSIC = 3; - /** - * @see BigInteger::__clone() - */ - const NONE = 4; - /**#@-*/ - - /**#@+ - * Array constants - * - * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and - * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them. - * - * @access private - */ - /** - * $result[self::VALUE] contains the value. - */ - const VALUE = 0; - /** - * $result[self::SIGN] contains the sign. - */ - const SIGN = 1; - /**#@-*/ - - /**#@+ - * @access private - * @see BigInteger::_montgomery() - * @see BigInteger::_barrett() - */ - /** - * Cache constants - * - * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. - */ - const VARIABLE = 0; - /** - * $cache[self::DATA] contains the cached data. - */ - const DATA = 1; - /**#@-*/ - - /**#@+ - * Mode constants. - * - * @access private - * @see BigInteger::__construct() - */ - /** - * To use the pure-PHP implementation - */ - const MODE_INTERNAL = 1; - /** - * To use the BCMath library - * - * (if enabled; otherwise, the internal implementation will be used) - */ - const MODE_BCMATH = 2; - /** - * To use the GMP library - * - * (if present; otherwise, either the BCMath or the internal implementation will be used) - */ - const MODE_GMP = 3; - /**#@-*/ - - /** - * Karatsuba Cutoff - * - * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication? - * - * @access private - */ - const KARATSUBA_CUTOFF = 25; - - /**#@+ - * Static properties used by the pure-PHP implementation. - * - * @see __construct() - */ - private static $base; - private static $baseFull; - private static $maxDigit; - private static $msb; - - /** - * $max10 in greatest $max10Len satisfying - * $max10 = 10**$max10Len <= 2**$base. - */ - private static $max10; - - /** - * $max10Len in greatest $max10Len satisfying - * $max10 = 10**$max10Len <= 2**$base. - */ - private static $max10Len; - private static $maxDigit2; - /**#@-*/ - - /** - * Holds the BigInteger's value. - * - * @var array - * @access private - */ - private $value; - - /** - * Holds the BigInteger's magnitude. - * - * @var bool - * @access private - */ - private $is_negative = false; - - /** - * Precision - * - * @see self::setPrecision() - * @access private - */ - private $precision = -1; - - /** - * Precision Bitmask - * - * @see self::setPrecision() - * @access private - */ - private $bitmask = false; - - /** - * Mode independent value used for serialization. - * - * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for - * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value, - * however, $this->hex is only calculated when $this->__sleep() is called. - * - * @see self::__sleep() - * @see self::__wakeup() - * @var string - * @access private - */ - private $hex; - - /** - * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers. - * - * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using - * two's compliment. The sole exception to this is -10, which is treated the same as 10 is. - * - * Here's an example: - * - * toString(); // outputs 50 - * ?> - * - * - * @param $x base-10 number or base-$base number if $base set. - * @param int $base - * @return \phpseclib\Math\BigInteger - * @access public - */ - public function __construct($x = 0, $base = 10) - { - if (!defined('MATH_BIGINTEGER_MODE')) { - switch (true) { - case extension_loaded('gmp'): - define('MATH_BIGINTEGER_MODE', self::MODE_GMP); - break; - case extension_loaded('bcmath'): - define('MATH_BIGINTEGER_MODE', self::MODE_BCMATH); - break; - default: - define('MATH_BIGINTEGER_MODE', self::MODE_INTERNAL); - } - } - - if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { - define('MATH_BIGINTEGER_OPENSSL_ENABLED', true); - } - - if (!defined('PHP_INT_SIZE')) { - define('PHP_INT_SIZE', 4); - } - - if (empty(self::$base) && MATH_BIGINTEGER_MODE == self::MODE_INTERNAL) { - switch (PHP_INT_SIZE) { - case 8: // use 64-bit integers if int size is 8 bytes - self::$base = 31; - self::$baseFull = 0x80000000; - self::$maxDigit = 0x7FFFFFFF; - self::$msb = 0x40000000; - self::$max10 = 1000000000; - self::$max10Len = 9; - self::$maxDigit2 = pow(2, 62); - break; - //case 4: // use 64-bit floats if int size is 4 bytes - default: - self::$base = 26; - self::$baseFull = 0x4000000; - self::$maxDigit = 0x3FFFFFF; - self::$msb = 0x2000000; - self::$max10 = 10000000; - self::$max10Len = 7; - self::$maxDigit2 = pow(2, 52); // pow() prevents truncation - } - } - - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - switch (true) { - case is_resource($x) && get_resource_type($x) == 'GMP integer': - // PHP 5.6 switched GMP from using resources to objects - case $x instanceof \GMP: - $this->value = $x; - return; - } - $this->value = gmp_init(0); - break; - case self::MODE_BCMATH: - $this->value = '0'; - break; - default: - $this->value = array(); - } - - // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48 - // '0' is the only value like this per http://php.net/empty - if (empty($x) && (abs($base) != 256 || $x !== '0')) { - return; - } - - switch ($base) { - case -256: - if (ord($x[0]) & 0x80) { - $x = ~$x; - $this->is_negative = true; - } - case 256: - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $sign = $this->is_negative ? '-' : ''; - $this->value = gmp_init($sign . '0x' . Hex::encode($x)); - break; - case self::MODE_BCMATH: - // round $len to the nearest 4 (thanks, DavidMJ!) - $len = (strlen($x) + 3) & 0xFFFFFFFC; - - $x = str_pad($x, $len, chr(0), STR_PAD_LEFT); - - for ($i = 0; $i < $len; $i+= 4) { - $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32 - $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0); - } - - if ($this->is_negative) { - $this->value = '-' . $this->value; - } - - break; - // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb) - default: - while (strlen($x)) { - $this->value[] = $this->_bytes2int($this->_base256_rshift($x, self::$base)); - } - } - - if ($this->is_negative) { - if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { - $this->is_negative = false; - } - $temp = $this->add(new static('-1')); - $this->value = $temp->value; - } - break; - case 16: - case -16: - if ($base > 0 && $x[0] == '-') { - $this->is_negative = true; - $x = substr($x, 1); - } - - $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x); - - $is_negative = false; - if ($base < 0 && hexdec($x[0]) >= 8) { - $this->is_negative = $is_negative = true; - $x = Hex::encode(~Hex::decode($x)); - } - - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = $this->is_negative ? '-0x' . $x : '0x' . $x; - $this->value = gmp_init($temp); - $this->is_negative = false; - break; - case self::MODE_BCMATH: - $x = (strlen($x) & 1) ? '0' . $x : $x; - $temp = new static(Hex::decode($x), 256); - $this->value = $this->is_negative ? '-' . $temp->value : $temp->value; - $this->is_negative = false; - break; - default: - $x = (strlen($x) & 1) ? '0' . $x : $x; - $temp = new static(Hex::decode($x), 256); - $this->value = $temp->value; - } - - if ($is_negative) { - $temp = $this->add(new static('-1')); - $this->value = $temp->value; - } - break; - case 10: - case -10: - // (?value = gmp_init($x); - break; - case self::MODE_BCMATH: - // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different - // results then doing it on '-1' does (modInverse does $x[0]) - $this->value = $x === '-' ? '0' : (string) $x; - break; - default: - $temp = new static(); - - $multiplier = new static(); - $multiplier->value = array(self::$max10); - - if ($x[0] == '-') { - $this->is_negative = true; - $x = substr($x, 1); - } - - $x = str_pad($x, strlen($x) + ((self::$max10Len - 1) * strlen($x)) % self::$max10Len, 0, STR_PAD_LEFT); - while (strlen($x)) { - $temp = $temp->multiply($multiplier); - $temp = $temp->add(new static($this->_int2bytes(substr($x, 0, self::$max10Len)), 256)); - $x = substr($x, self::$max10Len); - } - - $this->value = $temp->value; - } - break; - case 2: // base-2 support originally implemented by Lluis Pamies - thanks! - case -2: - if ($base > 0 && $x[0] == '-') { - $this->is_negative = true; - $x = substr($x, 1); - } - - $x = preg_replace('#^([01]*).*#', '$1', $x); - $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT); - - $str = '0x'; - while (strlen($x)) { - $part = substr($x, 0, 4); - $str.= dechex(bindec($part)); - $x = substr($x, 4); - } - - if ($this->is_negative) { - $str = '-' . $str; - } - - $temp = new static($str, 8 * $base); // ie. either -16 or +16 - $this->value = $temp->value; - $this->is_negative = $temp->is_negative; - - break; - default: - // base not supported, so we'll let $this == 0 - } - } - - /** - * Converts a BigInteger to a byte string (eg. base-256). - * - * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're - * saved as two's compliment. - * - * Here's an example: - * - * toBytes(); // outputs chr(65) - * ?> - * - * - * @param bool $twos_compliment - * @return string - * @access public - * @internal Converts a base-2**26 number to base-2**8 - */ - public function toBytes($twos_compliment = false) - { - if ($twos_compliment) { - $comparison = $this->compare(new static()); - if ($comparison == 0) { - return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; - } - - $temp = $comparison < 0 ? $this->add(new static(1)) : $this; - $bytes = $temp->toBytes(); - - if (empty($bytes)) { // eg. if the number we're trying to convert is -1 - $bytes = chr(0); - } - - if (ord($bytes[0]) & 0x80) { - $bytes = chr(0) . $bytes; - } - - return $comparison < 0 ? ~$bytes : $bytes; - } - - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - if (gmp_cmp($this->value, gmp_init(0)) == 0) { - return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; - } - - $temp = gmp_strval(gmp_abs($this->value), 16); - $temp = (strlen($temp) & 1) ? '0' . $temp : $temp; - $temp = Hex::decode($temp); - - return $this->precision > 0 ? - substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : - ltrim($temp, chr(0)); - case self::MODE_BCMATH: - if ($this->value === '0') { - return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; - } - - $value = ''; - $current = $this->value; - - if ($current[0] == '-') { - $current = substr($current, 1); - } - - while (bccomp($current, '0', 0) > 0) { - $temp = bcmod($current, '16777216'); - $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value; - $current = bcdiv($current, '16777216', 0); - } - - return $this->precision > 0 ? - substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : - ltrim($value, chr(0)); - } - - if (!count($this->value)) { - return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; - } - $result = self::_int2bytes($this->value[count($this->value) - 1]); - - for ($i = count($this->value) - 2; $i >= 0; --$i) { - self::_base256_lshift($result, self::$base); - $result = $result | str_pad(self::_int2bytes($this->value[$i]), strlen($result), chr(0), STR_PAD_LEFT); - } - - return $this->precision > 0 ? - str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) : - $result; - } - - /** - * Converts a BigInteger to a hex string (eg. base-16)). - * - * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're - * saved as two's compliment. - * - * Here's an example: - * - * toHex(); // outputs '41' - * ?> - * - * - * @param bool $twos_compliment - * @return string - * @access public - * @internal Converts a base-2**26 number to base-2**8 - */ - public function toHex($twos_compliment = false) - { - return Hex::encode($this->toBytes($twos_compliment)); - } - - /** - * Converts a BigInteger to a bit string (eg. base-2). - * - * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're - * saved as two's compliment. - * - * Here's an example: - * - * toBits(); // outputs '1000001' - * ?> - * - * - * @param bool $twos_compliment - * @return string - * @access public - * @internal Converts a base-2**26 number to base-2**2 - */ - public function toBits($twos_compliment = false) - { - $hex = $this->toHex($twos_compliment); - $bits = ''; - for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) { - $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits; - } - if ($start) { // hexdec('') == 0 - $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits; - } - $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0'); - - if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) { - return '0' . $result; - } - - return $result; - } - - /** - * Converts a BigInteger to a base-10 number. - * - * Here's an example: - * - * toString(); // outputs 50 - * ?> - * - * - * @return string - * @access public - * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10) - */ - public function toString() - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - return gmp_strval($this->value); - case self::MODE_BCMATH: - if ($this->value === '0') { - return '0'; - } - - return ltrim($this->value, '0'); - } - - if (!count($this->value)) { - return '0'; - } - - $temp = clone $this; - $temp->is_negative = false; - - $divisor = new static(); - $divisor->value = array(self::$max10); - $result = ''; - while (count($temp->value)) { - list($temp, $mod) = $temp->divide($divisor); - $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', self::$max10Len, '0', STR_PAD_LEFT) . $result; - } - $result = ltrim($result, '0'); - if (empty($result)) { - $result = '0'; - } - - if ($this->is_negative) { - $result = '-' . $result; - } - - return $result; - } - - /** - * __toString() magic method - * - * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call - * toString(). - * - * @access public - * @internal Implemented per a suggestion by Techie-Michael - thanks! - */ - public function __toString() - { - return $this->toString(); - } - - /** - * __sleep() magic method - * - * Will be called, automatically, when serialize() is called on a BigInteger object. - * - * @see self::__wakeup() - * @access public - */ - public function __sleep() - { - $this->hex = $this->toHex(true); - $vars = array('hex'); - if ($this->precision > 0) { - $vars[] = 'precision'; - } - return $vars; - } - - /** - * __wakeup() magic method - * - * Will be called, automatically, when unserialize() is called on a BigInteger object. - * - * @see self::__sleep() - * @access public - */ - public function __wakeup() - { - $temp = new static($this->hex, -16); - $this->value = $temp->value; - $this->is_negative = $temp->is_negative; - if ($this->precision > 0) { - // recalculate $this->bitmask - $this->setPrecision($this->precision); - } - } - - /** - * __debugInfo() magic method - * - * Will be called, automatically, when print_r() or var_dump() are called - * - * @access public - */ - public function __debugInfo() - { - $opts = array(); - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $engine = 'gmp'; - break; - case self::MODE_BCMATH: - $engine = 'bcmath'; - break; - case self::MODE_INTERNAL: - $engine = 'internal'; - $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit'; - } - if (MATH_BIGINTEGER_MODE != self::MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { - $opts[] = 'OpenSSL'; - } - if (!empty($opts)) { - $engine.= ' (' . implode($opts, ', ') . ')'; - } - return array( - 'value' => '0x' . $this->toHex(true), - 'engine' => $engine - ); - } - - /** - * Adds two BigIntegers. - * - * Here's an example: - * - * add($b); - * - * echo $c->toString(); // outputs 30 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $y - * @return \phpseclib\Math\BigInteger - * @access public - * @internal Performs base-2**52 addition - */ - public function add(BigInteger $y) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = new static(); - $temp->value = gmp_add($this->value, $y->value); - - return $this->_normalize($temp); - case self::MODE_BCMATH: - $temp = new static(); - $temp->value = bcadd($this->value, $y->value, 0); - - return $this->_normalize($temp); - } - - $temp = self::_add($this->value, $this->is_negative, $y->value, $y->is_negative); - - $result = new static(); - $result->value = $temp[self::VALUE]; - $result->is_negative = $temp[self::SIGN]; - - return $this->_normalize($result); - } - - /** - * Performs addition. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array - * @access private - */ - private static function _add($x_value, $x_negative, $y_value, $y_negative) - { - $x_size = count($x_value); - $y_size = count($y_value); - - if ($x_size == 0) { - return array( - self::VALUE => $y_value, - self::SIGN => $y_negative - ); - } elseif ($y_size == 0) { - return array( - self::VALUE => $x_value, - self::SIGN => $x_negative - ); - } - - // subtract, if appropriate - if ($x_negative != $y_negative) { - if ($x_value == $y_value) { - return array( - self::VALUE => array(), - self::SIGN => false - ); - } - - $temp = self::_subtract($x_value, false, $y_value, false); - $temp[self::SIGN] = self::_compare($x_value, false, $y_value, false) > 0 ? - $x_negative : $y_negative; - - return $temp; - } - - if ($x_size < $y_size) { - $size = $x_size; - $value = $y_value; - } else { - $size = $y_size; - $value = $x_value; - } - - $value[count($value)] = 0; // just in case the carry adds an extra digit - - $carry = 0; - for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) { - $sum = $x_value[$j] * self::$baseFull + $x_value[$i] + $y_value[$j] * self::$baseFull + $y_value[$i] + $carry; - $carry = $sum >= self::$maxDigit2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 - $sum = $carry ? $sum - self::$maxDigit2 : $sum; - - $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31); - - $value[$i] = (int) ($sum - self::$baseFull * $temp); // eg. a faster alternative to fmod($sum, 0x4000000) - $value[$j] = $temp; - } - - if ($j == $size) { // ie. if $y_size is odd - $sum = $x_value[$i] + $y_value[$i] + $carry; - $carry = $sum >= self::$baseFull; - $value[$i] = $carry ? $sum - self::$baseFull : $sum; - ++$i; // ie. let $i = $j since we've just done $value[$i] - } - - if ($carry) { - for (; $value[$i] == self::$maxDigit; ++$i) { - $value[$i] = 0; - } - ++$value[$i]; - } - - return array( - self::VALUE => self::_trim($value), - self::SIGN => $x_negative - ); - } - - /** - * Subtracts two BigIntegers. - * - * Here's an example: - * - * subtract($b); - * - * echo $c->toString(); // outputs -10 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $y - * @return \phpseclib\Math\BigInteger - * @access public - * @internal Performs base-2**52 subtraction - */ - public function subtract(BigInteger $y) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = new static(); - $temp->value = gmp_sub($this->value, $y->value); - - return $this->_normalize($temp); - case self::MODE_BCMATH: - $temp = new static(); - $temp->value = bcsub($this->value, $y->value, 0); - - return $this->_normalize($temp); - } - - $temp = self::_subtract($this->value, $this->is_negative, $y->value, $y->is_negative); - - $result = new static(); - $result->value = $temp[self::VALUE]; - $result->is_negative = $temp[self::SIGN]; - - return $this->_normalize($result); - } - - /** - * Performs subtraction. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array - * @access private - */ - private static function _subtract($x_value, $x_negative, $y_value, $y_negative) - { - $x_size = count($x_value); - $y_size = count($y_value); - - if ($x_size == 0) { - return array( - self::VALUE => $y_value, - self::SIGN => !$y_negative - ); - } elseif ($y_size == 0) { - return array( - self::VALUE => $x_value, - self::SIGN => $x_negative - ); - } - - // add, if appropriate (ie. -$x - +$y or +$x - -$y) - if ($x_negative != $y_negative) { - $temp = self::_add($x_value, false, $y_value, false); - $temp[self::SIGN] = $x_negative; - - return $temp; - } - - $diff = self::_compare($x_value, $x_negative, $y_value, $y_negative); - - if (!$diff) { - return array( - self::VALUE => array(), - self::SIGN => false - ); - } - - // switch $x and $y around, if appropriate. - if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) { - $temp = $x_value; - $x_value = $y_value; - $y_value = $temp; - - $x_negative = !$x_negative; - - $x_size = count($x_value); - $y_size = count($y_value); - } - - // at this point, $x_value should be at least as big as - if not bigger than - $y_value - - $carry = 0; - for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) { - $sum = $x_value[$j] * self::$baseFull + $x_value[$i] - $y_value[$j] * self::$baseFull - $y_value[$i] - $carry; - $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 - $sum = $carry ? $sum + self::$maxDigit2 : $sum; - - $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31); - - $x_value[$i] = (int) ($sum - self::$baseFull * $temp); - $x_value[$j] = $temp; - } - - if ($j == $y_size) { // ie. if $y_size is odd - $sum = $x_value[$i] - $y_value[$i] - $carry; - $carry = $sum < 0; - $x_value[$i] = $carry ? $sum + self::$baseFull : $sum; - ++$i; - } - - if ($carry) { - for (; !$x_value[$i]; ++$i) { - $x_value[$i] = self::$maxDigit; - } - --$x_value[$i]; - } - - return array( - self::VALUE => self::_trim($x_value), - self::SIGN => $x_negative - ); - } - - /** - * Multiplies two BigIntegers - * - * Here's an example: - * - * multiply($b); - * - * echo $c->toString(); // outputs 200 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $x - * @return \phpseclib\Math\BigInteger - * @access public - */ - public function multiply(BigInteger $x) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = new static(); - $temp->value = gmp_mul($this->value, $x->value); - - return $this->_normalize($temp); - case self::MODE_BCMATH: - $temp = new static(); - $temp->value = bcmul($this->value, $x->value, 0); - - return $this->_normalize($temp); - } - - $temp = self::_multiply($this->value, $this->is_negative, $x->value, $x->is_negative); - - $product = new static(); - $product->value = $temp[self::VALUE]; - $product->is_negative = $temp[self::SIGN]; - - return $this->_normalize($product); - } - - /** - * Performs multiplication. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array - * @access private - */ - private static function _multiply($x_value, $x_negative, $y_value, $y_negative) - { - //if ( $x_value == $y_value ) { - // return [ - // self::VALUE => $this->_square($x_value), - // self::SIGN => $x_sign != $y_value - // ]; - //} - - $x_length = count($x_value); - $y_length = count($y_value); - - if (!$x_length || !$y_length) { // a 0 is being multiplied - return array( - self::VALUE => array(), - self::SIGN => false - ); - } - - return array( - self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ? - self::_trim(self::_regularMultiply($x_value, $y_value)) : - self::_trim(self::_karatsuba($x_value, $y_value)), - self::SIGN => $x_negative != $y_negative - ); - } - - /** - * Performs long multiplication on two BigIntegers - * - * Modeled after 'multiply' in MutableBigInteger.java. - * - * @param array $x_value - * @param array $y_value - * @return array - * @access private - */ - private static function _regularMultiply($x_value, $y_value) - { - $x_length = count($x_value); - $y_length = count($y_value); - - if (!$x_length || !$y_length) { // a 0 is being multiplied - return array(); - } - - if ($x_length < $y_length) { - $temp = $x_value; - $x_value = $y_value; - $y_value = $temp; - - $x_length = count($x_value); - $y_length = count($y_value); - } - - $product_value = self::_array_repeat(0, $x_length + $y_length); - - // the following for loop could be removed if the for loop following it - // (the one with nested for loops) initially set $i to 0, but - // doing so would also make the result in one set of unnecessary adds, - // since on the outermost loops first pass, $product->value[$k] is going - // to always be 0 - - $carry = 0; - - for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0 - $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 - $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$j] = (int) ($temp - self::$baseFull * $carry); - } - - $product_value[$j] = $carry; - - // the above for loop is what the previous comment was talking about. the - // following for loop is the "one with nested for loops" - for ($i = 1; $i < $y_length; ++$i) { - $carry = 0; - - for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) { - $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; - $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$k] = (int) ($temp - self::$baseFull * $carry); - } - - $product_value[$k] = $carry; - } - - return $product_value; - } - - /** - * Performs Karatsuba multiplication on two BigIntegers - * - * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}. - * - * @param array $x_value - * @param array $y_value - * @return array - * @access private - */ - private static function _karatsuba($x_value, $y_value) - { - $m = min(count($x_value) >> 1, count($y_value) >> 1); - - if ($m < self::KARATSUBA_CUTOFF) { - return self::_regularMultiply($x_value, $y_value); - } - - $x1 = array_slice($x_value, $m); - $x0 = array_slice($x_value, 0, $m); - $y1 = array_slice($y_value, $m); - $y0 = array_slice($y_value, 0, $m); - - $z2 = self::_karatsuba($x1, $y1); - $z0 = self::_karatsuba($x0, $y0); - - $z1 = self::_add($x1, false, $x0, false); - $temp = self::_add($y1, false, $y0, false); - $z1 = self::_karatsuba($z1[self::VALUE], $temp[self::VALUE]); - $temp = self::_add($z2, false, $z0, false); - $z1 = self::_subtract($z1, false, $temp[self::VALUE], false); - - $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); - $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); - - $xy = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); - $xy = self::_add($xy[self::VALUE], $xy[self::SIGN], $z0, false); - - return $xy[self::VALUE]; - } - - /** - * Performs squaring - * - * @param array $x - * @return array - * @access private - */ - private static function _square($x = false) - { - return count($x) < 2 * self::KARATSUBA_CUTOFF ? - self::_trim(self::_baseSquare($x)) : - self::_trim(self::_karatsubaSquare($x)); - } - - /** - * Performs traditional squaring on two BigIntegers - * - * Squaring can be done faster than multiplying a number by itself can be. See - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} / - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information. - * - * @param array $value - * @return array - * @access private - */ - private static function _baseSquare($value) - { - if (empty($value)) { - return array(); - } - $square_value = self::_array_repeat(0, 2 * count($value)); - - for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) { - $i2 = $i << 1; - - $temp = $square_value[$i2] + $value[$i] * $value[$i]; - $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $square_value[$i2] = (int) ($temp - self::$baseFull * $carry); - - // note how we start from $i+1 instead of 0 as we do in multiplication. - for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) { - $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry; - $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $square_value[$k] = (int) ($temp - self::$baseFull * $carry); - } - - // the following line can yield values larger 2**15. at this point, PHP should switch - // over to floats. - $square_value[$i + $max_index + 1] = $carry; - } - - return $square_value; - } - - /** - * Performs Karatsuba "squaring" on two BigIntegers - * - * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}. - * - * @param array $value - * @return array - * @access private - */ - private static function _karatsubaSquare($value) - { - $m = count($value) >> 1; - - if ($m < self::KARATSUBA_CUTOFF) { - return self::_baseSquare($value); - } - - $x1 = array_slice($value, $m); - $x0 = array_slice($value, 0, $m); - - $z2 = self::_karatsubaSquare($x1); - $z0 = self::_karatsubaSquare($x0); - - $z1 = self::_add($x1, false, $x0, false); - $z1 = self::_karatsubaSquare($z1[self::VALUE]); - $temp = self::_add($z2, false, $z0, false); - $z1 = self::_subtract($z1, false, $temp[self::VALUE], false); - - $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); - $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); - - $xx = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); - $xx = self::_add($xx[self::VALUE], $xx[self::SIGN], $z0, false); - - return $xx[self::VALUE]; - } - - /** - * Divides two BigIntegers. - * - * Returns an array whose first element contains the quotient and whose second element contains the - * "common residue". If the remainder would be positive, the "common residue" and the remainder are the - * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder - * and the divisor (basically, the "common residue" is the first positive modulo). - * - * Here's an example: - * - * divide($b); - * - * echo $quotient->toString(); // outputs 0 - * echo "\r\n"; - * echo $remainder->toString(); // outputs 10 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $y - * @return array - * @access public - * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}. - */ - public function divide(BigInteger $y) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $quotient = new static(); - $remainder = new static(); - - list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value); - - if (gmp_sign($remainder->value) < 0) { - $remainder->value = gmp_add($remainder->value, gmp_abs($y->value)); - } - - return array($this->_normalize($quotient), $this->_normalize($remainder)); - case self::MODE_BCMATH: - $quotient = new static(); - $remainder = new static(); - - $quotient->value = bcdiv($this->value, $y->value, 0); - $remainder->value = bcmod($this->value, $y->value); - - if ($remainder->value[0] == '-') { - $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0); - } - - return array($this->_normalize($quotient), $this->_normalize($remainder)); - } - - if (count($y->value) == 1) { - list($q, $r) = $this->_divide_digit($this->value, $y->value[0]); - $quotient = new static(); - $remainder = new static(); - $quotient->value = $q; - $remainder->value = array($r); - $quotient->is_negative = $this->is_negative != $y->is_negative; - return array($this->_normalize($quotient), $this->_normalize($remainder)); - } - - static $zero; - if (!isset($zero)) { - $zero = new static(); - } - - $x = clone $this; - $y = clone $y; - - $x_sign = $x->is_negative; - $y_sign = $y->is_negative; - - $x->is_negative = $y->is_negative = false; - - $diff = $x->compare($y); - - if (!$diff) { - $temp = new static(); - $temp->value = array(1); - $temp->is_negative = $x_sign != $y_sign; - return array($this->_normalize($temp), $this->_normalize(new static())); - } - - if ($diff < 0) { - // if $x is negative, "add" $y. - if ($x_sign) { - $x = $y->subtract($x); - } - return array($this->_normalize(new static()), $this->_normalize($x)); - } - - // normalize $x and $y as described in HAC 14.23 / 14.24 - $msb = $y->value[count($y->value) - 1]; - for ($shift = 0; !($msb & self::$msb); ++$shift) { - $msb <<= 1; - } - $x->_lshift($shift); - $y->_lshift($shift); - $y_value = &$y->value; - - $x_max = count($x->value) - 1; - $y_max = count($y->value) - 1; - - $quotient = new static(); - $quotient_value = &$quotient->value; - $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1); - - static $temp, $lhs, $rhs; - if (!isset($temp)) { - $temp = new static(); - $lhs = new static(); - $rhs = new static(); - } - $temp_value = &$temp->value; - $rhs_value = &$rhs->value; - - // $temp = $y << ($x_max - $y_max-1) in base 2**26 - $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value); - - while ($x->compare($temp) >= 0) { - // calculate the "common residue" - ++$quotient_value[$x_max - $y_max]; - $x = $x->subtract($temp); - $x_max = count($x->value) - 1; - } - - for ($i = $x_max; $i >= $y_max + 1; --$i) { - $x_value = &$x->value; - $x_window = array( - isset($x_value[$i]) ? $x_value[$i] : 0, - isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0, - isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0 - ); - $y_window = array( - $y_value[$y_max], - ($y_max > 0) ? $y_value[$y_max - 1] : 0 - ); - - $q_index = $i - $y_max - 1; - if ($x_window[0] == $y_window[0]) { - $quotient_value[$q_index] = self::$maxDigit; - } else { - $quotient_value[$q_index] = $this->_safe_divide( - $x_window[0] * self::$baseFull + $x_window[1], - $y_window[0] - ); - } - - $temp_value = array($y_window[1], $y_window[0]); - - $lhs->value = array($quotient_value[$q_index]); - $lhs = $lhs->multiply($temp); - - $rhs_value = array($x_window[2], $x_window[1], $x_window[0]); - - while ($lhs->compare($rhs) > 0) { - --$quotient_value[$q_index]; - - $lhs->value = array($quotient_value[$q_index]); - $lhs = $lhs->multiply($temp); - } - - $adjust = $this->_array_repeat(0, $q_index); - $temp_value = array($quotient_value[$q_index]); - $temp = $temp->multiply($y); - $temp_value = &$temp->value; - $temp_value = array_merge($adjust, $temp_value); - - $x = $x->subtract($temp); - - if ($x->compare($zero) < 0) { - $temp_value = array_merge($adjust, $y_value); - $x = $x->add($temp); - - --$quotient_value[$q_index]; - } - - $x_max = count($x_value) - 1; - } - - // unnormalize the remainder - $x->_rshift($shift); - - $quotient->is_negative = $x_sign != $y_sign; - - // calculate the "common residue", if appropriate - if ($x_sign) { - $y->_rshift($shift); - $x = $y->subtract($x); - } - - return array($this->_normalize($quotient), $this->_normalize($x)); - } - - /** - * Divides a BigInteger by a regular integer - * - * abc / x = a00 / x + b0 / x + c / x - * - * @param array $dividend - * @param array $divisor - * @return array - * @access private - */ - private static function _divide_digit($dividend, $divisor) - { - $carry = 0; - $result = array(); - - for ($i = count($dividend) - 1; $i >= 0; --$i) { - $temp = self::$baseFull * $carry + $dividend[$i]; - $result[$i] = self::_safe_divide($temp, $divisor); - $carry = (int) ($temp - $divisor * $result[$i]); - } - - return array($result, $carry); - } - - /** - * Performs modular exponentiation. - * - * Here's an example: - * - * modPow($b, $c); - * - * echo $c->toString(); // outputs 10 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $n - * @return \phpseclib\Math\BigInteger - * @access public - * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and - * and although the approach involving repeated squaring does vastly better, it, too, is impractical - * for our purposes. The reason being that division - by far the most complicated and time-consuming - * of the basic operations (eg. +,-,*,/) - occurs multiple times within it. - * - * Modular reductions resolve this issue. Although an individual modular reduction takes more time - * then an individual division, when performed in succession (with the same modulo), they're a lot faster. - * - * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction, - * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the - * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because - * the product of two odd numbers is odd), but what about when RSA isn't used? - * - * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a - * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the - * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however, - * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and - * the other, a power of two - and recombine them, later. This is the method that this modPow function uses. - * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates. - */ - public function modPow(BigInteger $e, BigInteger $n) - { - $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs(); - - if ($e->compare(new static()) < 0) { - $e = $e->abs(); - - $temp = $this->modInverse($n); - if ($temp === false) { - return false; - } - - return $this->_normalize($temp->modPow($e, $n)); - } - - if (MATH_BIGINTEGER_MODE == self::MODE_GMP) { - $temp = new static(); - $temp->value = gmp_powm($this->value, $e->value, $n->value); - - return $this->_normalize($temp); - } - - if ($this->compare(new static()) < 0 || $this->compare($n) > 0) { - list(, $temp) = $this->divide($n); - return $temp->modPow($e, $n); - } - - if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { - $components = array( - 'modulus' => $n->toBytes(true), - 'publicExponent' => $e->toBytes(true) - ); - - $components = array( - 'modulus' => pack('Ca*a*', 2, ASN1::encodeLength(strlen($components['modulus'])), $components['modulus']), - 'publicExponent' => pack('Ca*a*', 2, ASN1::encodeLength(strlen($components['publicExponent'])), $components['publicExponent']) - ); - - $RSAPublicKey = pack( - 'Ca*a*a*', - 48, - ASN1::encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), - $components['modulus'], - $components['publicExponent'] - ); - - $rsaOID = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00"; // hex version of MA0GCSqGSIb3DQEBAQUA - $RSAPublicKey = chr(0) . $RSAPublicKey; - $RSAPublicKey = chr(3) . ASN1::encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey; - - $encapsulated = pack( - 'Ca*a*', - 48, - ASN1::encodeLength(strlen($rsaOID . $RSAPublicKey)), - $rsaOID . $RSAPublicKey - ); - - $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(Base64::encode($encapsulated)) . - '-----END PUBLIC KEY-----'; - - $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT); - - if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) { - return new static($result, 256); - } - } - - if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { - $temp = new static(); - $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); - - return $this->_normalize($temp); - } - - if (empty($e->value)) { - $temp = new static(); - $temp->value = array(1); - return $this->_normalize($temp); - } - - if ($e->value == array(1)) { - list(, $temp) = $this->divide($n); - return $this->_normalize($temp); - } - - if ($e->value == array(2)) { - $temp = new static(); - $temp->value = self::_square($this->value); - list(, $temp) = $temp->divide($n); - return $this->_normalize($temp); - } - - return $this->_normalize($this->_slidingWindow($e, $n, self::BARRETT)); - - // the following code, although not callable, can be run independently of the above code - // although the above code performed better in my benchmarks the following could might - // perform better under different circumstances. in lieu of deleting it it's just been - // made uncallable - - // is the modulo odd? - if ($n->value[0] & 1) { - return $this->_normalize($this->_slidingWindow($e, $n, self::MONTGOMERY)); - } - // if it's not, it's even - - // find the lowest set bit (eg. the max pow of 2 that divides $n) - for ($i = 0; $i < count($n->value); ++$i) { - if ($n->value[$i]) { - $temp = decbin($n->value[$i]); - $j = strlen($temp) - strrpos($temp, '1') - 1; - $j+= 26 * $i; - break; - } - } - // at this point, 2^$j * $n/(2^$j) == $n - - $mod1 = clone $n; - $mod1->_rshift($j); - $mod2 = new static(); - $mod2->value = array(1); - $mod2->_lshift($j); - - $part1 = ($mod1->value != array(1)) ? $this->_slidingWindow($e, $mod1, self::MONTGOMERY) : new static(); - $part2 = $this->_slidingWindow($e, $mod2, self::POWEROF2); - - $y1 = $mod2->modInverse($mod1); - $y2 = $mod1->modInverse($mod2); - - $result = $part1->multiply($mod2); - $result = $result->multiply($y1); - - $temp = $part2->multiply($mod1); - $temp = $temp->multiply($y2); - - $result = $result->add($temp); - list(, $result) = $result->divide($n); - - return $this->_normalize($result); - } - - /** - * Performs modular exponentiation. - * - * Alias for modPow(). - * - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $n - * @return \phpseclib\Math\BigInteger - * @access public - */ - public function powMod(BigInteger $e, BigInteger $n) - { - return $this->modPow($e, $n); - } - - /** - * Sliding Window k-ary Modular Exponentiation - * - * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} / - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims, - * however, this function performs a modular reduction after every multiplication and squaring operation. - * As such, this function has the same preconditions that the reductions being used do. - * - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $n - * @param int $mode - * @return \phpseclib\Math\BigInteger - * @access private - */ - private function _slidingWindow($e, $n, $mode) - { - static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function - //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1 - - $e_value = $e->value; - $e_length = count($e_value) - 1; - $e_bits = decbin($e_value[$e_length]); - for ($i = $e_length - 1; $i >= 0; --$i) { - $e_bits.= str_pad(decbin($e_value[$i]), self::$base, '0', STR_PAD_LEFT); - } - - $e_length = strlen($e_bits); - - // calculate the appropriate window size. - // $window_size == 3 if $window_ranges is between 25 and 81, for example. - for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) { - } - - $n_value = $n->value; - - // precompute $this^0 through $this^$window_size - $powers = array(); - $powers[1] = self::_prepareReduce($this->value, $n_value, $mode); - $powers[2] = self::_squareReduce($powers[1], $n_value, $mode); - - // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end - // in a 1. ie. it's supposed to be odd. - $temp = 1 << ($window_size - 1); - for ($i = 1; $i < $temp; ++$i) { - $i2 = $i << 1; - $powers[$i2 + 1] = self::_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode); - } - - $result = array(1); - $result = self::_prepareReduce($result, $n_value, $mode); - - for ($i = 0; $i < $e_length;) { - if (!$e_bits[$i]) { - $result = self::_squareReduce($result, $n_value, $mode); - ++$i; - } else { - for ($j = $window_size - 1; $j > 0; --$j) { - if (!empty($e_bits[$i + $j])) { - break; - } - } - - // eg. the length of substr($e_bits, $i, $j + 1) - for ($k = 0; $k <= $j; ++$k) { - $result = self::_squareReduce($result, $n_value, $mode); - } - - $result = self::_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode); - - $i += $j + 1; - } - } - - $temp = new static(); - $temp->value = self::_reduce($result, $n_value, $mode); - - return $temp; - } - - /** - * Modular reduction - * - * For most $modes this will return the remainder. - * - * @see self::_slidingWindow() - * @access private - * @param array $x - * @param array $n - * @param int $mode - * @return array - */ - private static function _reduce($x, $n, $mode) - { - switch ($mode) { - case self::MONTGOMERY: - return self::_montgomery($x, $n); - case self::BARRETT: - return self::_barrett($x, $n); - case self::POWEROF2: - $lhs = new static(); - $lhs->value = $x; - $rhs = new static(); - $rhs->value = $n; - return $x->_mod2($n); - case self::CLASSIC: - $lhs = new static(); - $lhs->value = $x; - $rhs = new static(); - $rhs->value = $n; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - case self::NONE: - return $x; - default: - // an invalid $mode was provided - } - } - - /** - * Modular reduction preperation - * - * @see self::_slidingWindow() - * @access private - * @param array $x - * @param array $n - * @param int $mode - * @return array - */ - private static function _prepareReduce($x, $n, $mode) - { - if ($mode == self::MONTGOMERY) { - return self::_prepMontgomery($x, $n); - } - return self::_reduce($x, $n, $mode); - } - - /** - * Modular multiply - * - * @see self::_slidingWindow() - * @access private - * @param array $x - * @param array $y - * @param array $n - * @param int $mode - * @return array - */ - private static function _multiplyReduce($x, $y, $n, $mode) - { - if ($mode == self::MONTGOMERY) { - return self::_montgomeryMultiply($x, $y, $n); - } - $temp = self::_multiply($x, false, $y, false); - return self::_reduce($temp[self::VALUE], $n, $mode); - } - - /** - * Modular square - * - * @see self::_slidingWindow() - * @access private - * @param array $x - * @param array $n - * @param int $mode - * @return array - */ - private static function _squareReduce($x, $n, $mode) - { - if ($mode == self::MONTGOMERY) { - return self::_montgomeryMultiply($x, $x, $n); - } - return self::_reduce(self::_square($x), $n, $mode); - } - - /** - * Modulos for Powers of Two - * - * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1), - * we'll just use this function as a wrapper for doing that. - * - * @see self::_slidingWindow() - * @access private - * @param \phpseclib\Math\BigInteger - * @return \phpseclib\Math\BigInteger - */ - private function _mod2($n) - { - $temp = new static(); - $temp->value = array(1); - return $this->bitwise_and($n->subtract($temp)); - } - - /** - * Barrett Modular Reduction - * - * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} / - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly, - * so as not to require negative numbers (initially, this script didn't support negative numbers). - * - * Employs "folding", as described at - * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from - * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x." - * - * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that - * usable on account of (1) its not using reasonable radix points as discussed in - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable - * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that - * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line - * comments for details. - * - * @see self::_slidingWindow() - * @access private - * @param array $n - * @param array $m - * @return array - */ - private static function _barrett($n, $m) - { - static $cache = array( - self::VARIABLE => array(), - self::DATA => array() - ); - - $m_length = count($m); - - // if (self::_compare($n, self::_square($m)) >= 0) { - if (count($n) > 2 * $m_length) { - $lhs = new static(); - $rhs = new static(); - $lhs->value = $n; - $rhs->value = $m; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } - - // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced - if ($m_length < 5) { - return self::_regularBarrett($n, $m); - } - - // n = 2 * m.length - - if (($key = array_search($m, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $m; - - $lhs = new static(); - $lhs_value = &$lhs->value; - $lhs_value = self::_array_repeat(0, $m_length + ($m_length >> 1)); - $lhs_value[] = 1; - $rhs = new static(); - $rhs->value = $m; - - list($u, $m1) = $lhs->divide($rhs); - $u = $u->value; - $m1 = $m1->value; - - $cache[self::DATA][] = array( - 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1) - 'm1'=> $m1 // m.length - ); - } else { - extract($cache[self::DATA][$key]); - } - - $cutoff = $m_length + ($m_length >> 1); - $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1) - $msd = array_slice($n, $cutoff); // m.length >> 1 - $lsd = self::_trim($lsd); - $temp = self::_multiply($msd, false, $m1, false); - $n = self::_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1 - - if ($m_length & 1) { - return self::_regularBarrett($n[self::VALUE], $m); - } - - // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2 - $temp = array_slice($n[self::VALUE], $m_length - 1); - // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2 - // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1 - $temp = self::_multiply($temp, false, $u, false); - // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1 - // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) - $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1); - // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1 - // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1) - $temp = self::_multiply($temp, false, $m, false); - - // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit - // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop - // following this comment would loop a lot (hence our calling _regularBarrett() in that situation). - - $result = self::_subtract($n[self::VALUE], false, $temp[self::VALUE], false); - - while (self::_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) { - $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $m, false); - } - - return $result[self::VALUE]; - } - - /** - * (Regular) Barrett Modular Reduction - * - * For numbers with more than four digits BigInteger::_barrett() is faster. The difference between that and this - * is that this function does not fold the denominator into a smaller form. - * - * @see self::_slidingWindow() - * @access private - * @param array $x - * @param array $n - * @return array - */ - private static function _regularBarrett($x, $n) - { - static $cache = array( - self::VARIABLE => array(), - self::DATA => array() - ); - - $n_length = count($n); - - if (count($x) > 2 * $n_length) { - $lhs = new static(); - $rhs = new static(); - $lhs->value = $x; - $rhs->value = $n; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } - - if (($key = array_search($n, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $n; - $lhs = new static(); - $lhs_value = &$lhs->value; - $lhs_value = self::_array_repeat(0, 2 * $n_length); - $lhs_value[] = 1; - $rhs = new static(); - $rhs->value = $n; - list($temp, ) = $lhs->divide($rhs); // m.length - $cache[self::DATA][] = $temp->value; - } - - // 2 * m.length - (m.length - 1) = m.length + 1 - $temp = array_slice($x, $n_length - 1); - // (m.length + 1) + m.length = 2 * m.length + 1 - $temp = self::_multiply($temp, false, $cache[self::DATA][$key], false); - // (2 * m.length + 1) - (m.length - 1) = m.length + 2 - $temp = array_slice($temp[self::VALUE], $n_length + 1); - - // m.length + 1 - $result = array_slice($x, 0, $n_length + 1); - // m.length + 1 - $temp = self::_multiplyLower($temp, false, $n, false, $n_length + 1); - // $temp == array_slice(self::_multiply($temp, false, $n, false)->value, 0, $n_length + 1) - - if (self::_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) { - $corrector_value = self::_array_repeat(0, $n_length + 1); - $corrector_value[count($corrector_value)] = 1; - $result = self::_add($result, false, $corrector_value, false); - $result = $result[self::VALUE]; - } - - // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits - $result = self::_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]); - while (self::_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) { - $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $n, false); - } - - return $result[self::VALUE]; - } - - /** - * Performs long multiplication up to $stop digits - * - * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved. - * - * @see self::_regularBarrett() - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @param int $stop - * @return array - * @access private - */ - private static function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop) - { - $x_length = count($x_value); - $y_length = count($y_value); - - if (!$x_length || !$y_length) { // a 0 is being multiplied - return array( - self::VALUE => array(), - self::SIGN => false - ); - } - - if ($x_length < $y_length) { - $temp = $x_value; - $x_value = $y_value; - $y_value = $temp; - - $x_length = count($x_value); - $y_length = count($y_value); - } - - $product_value = self::_array_repeat(0, $x_length + $y_length); - - // the following for loop could be removed if the for loop following it - // (the one with nested for loops) initially set $i to 0, but - // doing so would also make the result in one set of unnecessary adds, - // since on the outermost loops first pass, $product->value[$k] is going - // to always be 0 - - $carry = 0; - - for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i - $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 - $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$j] = (int) ($temp - self::$baseFull * $carry); - } - - if ($j < $stop) { - $product_value[$j] = $carry; - } - - // the above for loop is what the previous comment was talking about. the - // following for loop is the "one with nested for loops" - - for ($i = 1; $i < $y_length; ++$i) { - $carry = 0; - - for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) { - $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; - $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$k] = (int) ($temp - self::$baseFull * $carry); - } - - if ($k < $stop) { - $product_value[$k] = $carry; - } - } - - return array( - self::VALUE => self::_trim($product_value), - self::SIGN => $x_negative != $y_negative - ); - } - - /** - * Montgomery Modular Reduction - * - * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n. - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be - * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function - * to work correctly. - * - * @see self::_prepMontgomery() - * @see self::_slidingWindow() - * @access private - * @param array $x - * @param array $n - * @return array - */ - private static function _montgomery($x, $n) - { - static $cache = array( - self::VARIABLE => array(), - self::DATA => array() - ); - - if (($key = array_search($n, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $x; - $cache[self::DATA][] = self::_modInverse67108864($n); - } - - $k = count($n); - - $result = array(self::VALUE => $x); - - for ($i = 0; $i < $k; ++$i) { - $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key]; - $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = self::_regularMultiply(array($temp), $n); - $temp = array_merge($this->_array_repeat(0, $i), $temp); - $result = self::_add($result[self::VALUE], false, $temp, false); - } - - $result[self::VALUE] = array_slice($result[self::VALUE], $k); - - if (self::_compare($result, false, $n, false) >= 0) { - $result = self::_subtract($result[self::VALUE], false, $n, false); - } - - return $result[self::VALUE]; - } - - /** - * Montgomery Multiply - * - * Interleaves the montgomery reduction and long multiplication algorithms together as described in - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36} - * - * @see self::_prepMontgomery() - * @see self::_montgomery() - * @access private - * @param array $x - * @param array $y - * @param array $m - * @return array - */ - private static function _montgomeryMultiply($x, $y, $m) - { - $temp = self::_multiply($x, false, $y, false); - return self::_montgomery($temp[self::VALUE], $m); - - // the following code, although not callable, can be run independently of the above code - // although the above code performed better in my benchmarks the following could might - // perform better under different circumstances. in lieu of deleting it it's just been - // made uncallable - - static $cache = array( - self::VARIABLE => array(), - self::DATA => array() - ); - - if (($key = array_search($m, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $m; - $cache[self::DATA][] = self::_modInverse67108864($m); - } - - $n = max(count($x), count($y), count($m)); - $x = array_pad($x, $n, 0); - $y = array_pad($y, $n, 0); - $m = array_pad($m, $n, 0); - $a = array(self::VALUE => self::_array_repeat(0, $n + 1)); - for ($i = 0; $i < $n; ++$i) { - $temp = $a[self::VALUE][0] + $x[$i] * $y[0]; - $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = $temp * $cache[self::DATA][$key]; - $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = self::_add(self::_regularMultiply(array($x[$i]), $y), false, self::_regularMultiply(array($temp), $m), false); - $a = self::_add($a[self::VALUE], false, $temp[self::VALUE], false); - $a[self::VALUE] = array_slice($a[self::VALUE], 1); - } - if (self::_compare($a[self::VALUE], false, $m, false) >= 0) { - $a = self::_subtract($a[self::VALUE], false, $m, false); - } - return $a[self::VALUE]; - } - - /** - * Prepare a number for use in Montgomery Modular Reductions - * - * @see self::_montgomery() - * @see self::_slidingWindow() - * @access private - * @param array $x - * @param array $n - * @return array - */ - private static function _prepMontgomery($x, $n) - { - $lhs = new static(); - $lhs->value = array_merge(self::_array_repeat(0, count($n)), $x); - $rhs = new static(); - $rhs->value = $n; - - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } - - /** - * Modular Inverse of a number mod 2**26 (eg. 67108864) - * - * Based off of the bnpInvDigit function implemented and justified in the following URL: - * - * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js} - * - * The following URL provides more info: - * - * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85} - * - * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For - * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields - * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't - * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that - * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the - * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to - * 40 bits, which only 64-bit floating points will support. - * - * Thanks to Pedro Gimeno Fortea for input! - * - * @see self::_montgomery() - * @access private - * @param array $x - * @return int - */ - private function _modInverse67108864($x) // 2**26 == 67,108,864 - { - $x = -$x[0]; - $result = $x & 0x3; // x**-1 mod 2**2 - $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4 - $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8 - $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16 - $result = fmod($result * (2 - fmod($x * $result, self::$baseFull)), self::$baseFull); // x**-1 mod 2**26 - return $result & self::$maxDigit; - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * - * Here's an example: - * - * modInverse($b); - * echo $c->toString(); // outputs 4 - * - * echo "\r\n"; - * - * $d = $a->multiply($c); - * list(, $d) = $d->divide($b); - * echo $d; // outputs 1 (as per the definition of modular inverse) - * ?> - * - * - * @param \phpseclib\Math\BigInteger $n - * @return \phpseclib\Math\BigInteger|false - * @access public - * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information. - */ - public function modInverse(BigInteger $n) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = new static(); - $temp->value = gmp_invert($this->value, $n->value); - - return ($temp->value === false) ? false : $this->_normalize($temp); - } - - static $zero, $one; - if (!isset($zero)) { - $zero = new static(); - $one = new static(1); - } - - // $x mod -$n == $x mod $n. - $n = $n->abs(); - - if ($this->compare($zero) < 0) { - $temp = $this->abs(); - $temp = $temp->modInverse($n); - return $this->_normalize($n->subtract($temp)); - } - - extract($this->extendedGCD($n)); - - if (!$gcd->equals($one)) { - return false; - } - - $x = $x->compare($zero) < 0 ? $x->add($n) : $x; - - return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x); - } - - /** - * Calculates the greatest common divisor and Bezout's identity. - * - * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that - * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which - * combination is returned is dependent upon which mode is in use. See - * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information. - * - * Here's an example: - * - * extendedGCD($b)); - * - * echo $gcd->toString() . "\r\n"; // outputs 21 - * echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $n - * @return \phpseclib\Math\BigInteger - * @access public - * @internal Calculates the GCD using the binary xGCD algorithim described in - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes, - * the more traditional algorithim requires "relatively costly multiple-precision divisions". - */ - public function extendedGCD(BigInteger $n) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - extract(gmp_gcdext($this->value, $n->value)); - - return array( - 'gcd' => $this->_normalize(new static($g)), - 'x' => $this->_normalize(new static($s)), - 'y' => $this->_normalize(new static($t)) - ); - case self::MODE_BCMATH: - // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works - // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is, - // the basic extended euclidean algorithim is what we're using. - - $u = $this->value; - $v = $n->value; - - $a = '1'; - $b = '0'; - $c = '0'; - $d = '1'; - - while (bccomp($v, '0', 0) != 0) { - $q = bcdiv($u, $v, 0); - - $temp = $u; - $u = $v; - $v = bcsub($temp, bcmul($v, $q, 0), 0); - - $temp = $a; - $a = $c; - $c = bcsub($temp, bcmul($a, $q, 0), 0); - - $temp = $b; - $b = $d; - $d = bcsub($temp, bcmul($b, $q, 0), 0); - } - - return array( - 'gcd' => $this->_normalize(new static($u)), - 'x' => $this->_normalize(new static($a)), - 'y' => $this->_normalize(new static($b)) - ); - } - - $y = clone $n; - $x = clone $this; - $g = new static(); - $g->value = array(1); - - while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) { - $x->_rshift(1); - $y->_rshift(1); - $g->_lshift(1); - } - - $u = clone $x; - $v = clone $y; - - $a = new static(); - $b = new static(); - $c = new static(); - $d = new static(); - - $a->value = $d->value = $g->value = array(1); - $b->value = $c->value = array(); - - while (!empty($u->value)) { - while (!($u->value[0] & 1)) { - $u->_rshift(1); - if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) { - $a = $a->add($y); - $b = $b->subtract($x); - } - $a->_rshift(1); - $b->_rshift(1); - } - - while (!($v->value[0] & 1)) { - $v->_rshift(1); - if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) { - $c = $c->add($y); - $d = $d->subtract($x); - } - $c->_rshift(1); - $d->_rshift(1); - } - - if ($u->compare($v) >= 0) { - $u = $u->subtract($v); - $a = $a->subtract($c); - $b = $b->subtract($d); - } else { - $v = $v->subtract($u); - $c = $c->subtract($a); - $d = $d->subtract($b); - } - } - - return array( - 'gcd' => $this->_normalize($g->multiply($v)), - 'x' => $this->_normalize($c), - 'y' => $this->_normalize($d) - ); - } - - /** - * Calculates the greatest common divisor - * - * Say you have 693 and 609. The GCD is 21. - * - * Here's an example: - * - * extendedGCD($b); - * - * echo $gcd->toString() . "\r\n"; // outputs 21 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $n - * @return \phpseclib\Math\BigInteger - * @access public - */ - public function gcd(BigInteger $n) - { - extract($this->extendedGCD($n)); - return $gcd; - } - - /** - * Absolute value. - * - * @return \phpseclib\Math\BigInteger - * @access public - */ - public function abs() - { - $temp = new static(); - - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp->value = gmp_abs($this->value); - break; - case self::MODE_BCMATH: - $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value; - break; - default: - $temp->value = $this->value; - } - - return $temp; - } - - /** - * Compares two numbers. - * - * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is - * demonstrated thusly: - * - * $x > $y: $x->compare($y) > 0 - * $x < $y: $x->compare($y) < 0 - * $x == $y: $x->compare($y) == 0 - * - * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). - * - * @param \phpseclib\Math\BigInteger $y - * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. - * @access public - * @see self::equals() - * @internal Could return $this->subtract($x), but that's not as fast as what we do do. - */ - public function compare(BigInteger $y) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - return gmp_cmp($this->value, $y->value); - case self::MODE_BCMATH: - return bccomp($this->value, $y->value, 0); - } - - return self::_compare($this->value, $this->is_negative, $y->value, $y->is_negative); - } - - /** - * Compares two numbers. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return int - * @see self::compare() - * @access private - */ - private static function _compare($x_value, $x_negative, $y_value, $y_negative) - { - if ($x_negative != $y_negative) { - return (!$x_negative && $y_negative) ? 1 : -1; - } - - $result = $x_negative ? -1 : 1; - - if (count($x_value) != count($y_value)) { - return (count($x_value) > count($y_value)) ? $result : -$result; - } - $size = max(count($x_value), count($y_value)); - - $x_value = array_pad($x_value, $size, 0); - $y_value = array_pad($y_value, $size, 0); - - for ($i = count($x_value) - 1; $i >= 0; --$i) { - if ($x_value[$i] != $y_value[$i]) { - return ($x_value[$i] > $y_value[$i]) ? $result : -$result; - } - } - - return 0; - } - - /** - * Tests the equality of two numbers. - * - * If you need to see if one number is greater than or less than another number, use BigInteger::compare() - * - * @param \phpseclib\Math\BigInteger $x - * @return bool - * @access public - * @see self::compare() - */ - public function equals(BigInteger $x) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - return gmp_cmp($this->value, $x->value) == 0; - default: - return $this->value === $x->value && $this->is_negative == $x->is_negative; - } - } - - /** - * Set Precision - * - * Some bitwise operations give different results depending on the precision being used. Examples include left - * shift, not, and rotates. - * - * @param int $bits - * @access public - */ - public function setPrecision($bits) - { - if ($bits < 1) { - $this->precision = -1; - $this->bitmask = false; - - return; - } - $this->precision = $bits; - if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) { - $this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); - } else { - $this->bitmask = new static(bcpow('2', $bits, 0)); - } - - $temp = $this->_normalize($this); - $this->value = $temp->value; - } - - /** - * Get Precision - * - * @return int - * @see self::setPrecision() - * @access public - */ - public function getPrecision() - { - return $this->precision; - } - - /** - * Logical And - * - * @param \phpseclib\Math\BigInteger $x - * @access public - * @internal Implemented per a request by Lluis Pamies i Juarez - * @return \phpseclib\Math\BigInteger - */ - public function bitwise_and(BigInteger $x) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = new static(); - $temp->value = gmp_and($this->value, $x->value); - - return $this->_normalize($temp); - case self::MODE_BCMATH: - $left = $this->toBytes(); - $right = $x->toBytes(); - - $length = max(strlen($left), strlen($right)); - - $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); - $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); - - return $this->_normalize(new static($left & $right, 256)); - } - - $result = clone $this; - - $length = min(count($x->value), count($this->value)); - - $result->value = array_slice($result->value, 0, $length); - - for ($i = 0; $i < $length; ++$i) { - $result->value[$i]&= $x->value[$i]; - } - - return $this->_normalize($result); - } - - /** - * Logical Or - * - * @param \phpseclib\Math\BigInteger $x - * @access public - * @internal Implemented per a request by Lluis Pamies i Juarez - * @return \phpseclib\Math\BigInteger - */ - public function bitwise_or(BigInteger $x) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = new static(); - $temp->value = gmp_or($this->value, $x->value); - - return $this->_normalize($temp); - case self::MODE_BCMATH: - $left = $this->toBytes(); - $right = $x->toBytes(); - - $length = max(strlen($left), strlen($right)); - - $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); - $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); - - return $this->_normalize(new static($left | $right, 256)); - } - - $length = max(count($this->value), count($x->value)); - $result = clone $this; - $result->value = array_pad($result->value, $length, 0); - $x->value = array_pad($x->value, $length, 0); - - for ($i = 0; $i < $length; ++$i) { - $result->value[$i]|= $x->value[$i]; - } - - return $this->_normalize($result); - } - - /** - * Logical Exclusive-Or - * - * @param \phpseclib\Math\BigInteger $x - * @access public - * @internal Implemented per a request by Lluis Pamies i Juarez - * @return \phpseclib\Math\BigInteger - */ - public function bitwise_xor(BigInteger $x) - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $temp = new static(); - $temp->value = gmp_xor($this->value, $x->value); - - return $this->_normalize($temp); - case self::MODE_BCMATH: - $left = $this->toBytes(); - $right = $x->toBytes(); - - $length = max(strlen($left), strlen($right)); - - $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); - $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); - - return $this->_normalize(new static($left ^ $right, 256)); - } - - $length = max(count($this->value), count($x->value)); - $result = clone $this; - $result->value = array_pad($result->value, $length, 0); - $x->value = array_pad($x->value, $length, 0); - - for ($i = 0; $i < $length; ++$i) { - $result->value[$i]^= $x->value[$i]; - } - - return $this->_normalize($result); - } - - /** - * Logical Not - * - * @access public - * @internal Implemented per a request by Lluis Pamies i Juarez - * @return \phpseclib\Math\BigInteger - */ - public function bitwise_not() - { - // calculuate "not" without regard to $this->precision - // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0) - $temp = $this->toBytes(); - if ($temp == '') { - return ''; - } - $pre_msb = decbin(ord($temp[0])); - $temp = ~$temp; - $msb = decbin(ord($temp[0])); - if (strlen($msb) == 8) { - $msb = substr($msb, strpos($msb, '0')); - } - $temp[0] = chr(bindec($msb)); - - // see if we need to add extra leading 1's - $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8; - $new_bits = $this->precision - $current_bits; - if ($new_bits <= 0) { - return $this->_normalize(new static($temp, 256)); - } - - // generate as many leading 1's as we need to. - $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3); - - self::_base256_lshift($leading_ones, $current_bits); - - $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT); - - return $this->_normalize(new static($leading_ones | $temp, 256)); - } - - /** - * Logical Right Shift - * - * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. - * - * @param int $shift - * @return \phpseclib\Math\BigInteger - * @access public - * @internal The only version that yields any speed increases is the internal version. - */ - public function bitwise_rightShift($shift) - { - $temp = new static(); - - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - static $two; - - if (!isset($two)) { - $two = gmp_init('2'); - } - - $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift)); - - break; - case self::MODE_BCMATH: - $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0); - - break; - default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten - // and I don't want to do that... - $temp->value = $this->value; - $temp->_rshift($shift); - } - - return $this->_normalize($temp); - } - - /** - * Logical Left Shift - * - * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. - * - * @param int $shift - * @return \phpseclib\Math\BigInteger - * @access public - * @internal The only version that yields any speed increases is the internal version. - */ - public function bitwise_leftShift($shift) - { - $temp = new static(); - - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - static $two; - - if (!isset($two)) { - $two = gmp_init('2'); - } - - $temp->value = gmp_mul($this->value, gmp_pow($two, $shift)); - - break; - case self::MODE_BCMATH: - $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0); - - break; - default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten - // and I don't want to do that... - $temp->value = $this->value; - $temp->_lshift($shift); - } - - return $this->_normalize($temp); - } - - /** - * Logical Left Rotate - * - * Instead of the top x bits being dropped they're appended to the shifted bit string. - * - * @param int $shift - * @return \phpseclib\Math\BigInteger - * @access public - */ - public function bitwise_leftRotate($shift) - { - $bits = $this->toBytes(); - - if ($this->precision > 0) { - $precision = $this->precision; - if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { - $mask = $this->bitmask->subtract(new static(1)); - $mask = $mask->toBytes(); - } else { - $mask = $this->bitmask->toBytes(); - } - } else { - $temp = ord($bits[0]); - for ($i = 0; $temp >> $i; ++$i) { - } - $precision = 8 * strlen($bits) - 8 + $i; - $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3); - } - - if ($shift < 0) { - $shift+= $precision; - } - $shift%= $precision; - - if (!$shift) { - return clone $this; - } - - $left = $this->bitwise_leftShift($shift); - $left = $left->bitwise_and(new static($mask, 256)); - $right = $this->bitwise_rightShift($precision - $shift); - $result = MATH_BIGINTEGER_MODE != self::MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right); - return $this->_normalize($result); - } - - /** - * Logical Right Rotate - * - * Instead of the bottom x bits being dropped they're prepended to the shifted bit string. - * - * @param int $shift - * @return \phpseclib\Math\BigInteger - * @access public - */ - public function bitwise_rightRotate($shift) - { - return $this->bitwise_leftRotate(-$shift); - } - - /** - * Returns the smallest and largest n-bit number - * - * @param int $bits - * @return \phpseclib\Math\BigInteger - * @access public - */ - public static function minMaxBits($bits) - { - $bytes = $bits >> 3; - $min = str_repeat(chr(0), $bytes); - $max = str_repeat(chr(0xFF), $bytes); - $msb = $bits & 7; - if ($msb) { - $min = chr(1 << ($msb - 1)) . $min; - $max = chr((1 << $msb) - 1) . $max; - } else { - $min[0] = chr(0x80); - } - return array( - 'min' => new static($min, 256), - 'max' => new static($max, 256) - ); - } - - /** - * Generates a random number of a certain size - * - * Bit length is equal to $size. - * - * @param int $size - * @return \phpseclib\Math\BigInteger - * @access public - */ - public static function random($size) - { - extract(self::minMaxBits($size)); - return self::randomRange($min, $max); - } - - /** - * Generate a random number between a range - * - * Returns a random number between $min and $max where $min and $max - * can be defined using one of the two methods: - * - * BigInteger::randomRange($min, $max) - * BigInteger::randomRange($max, $min) - * - * @param \phpseclib\Math\BigInteger $arg1 - * @param \phpseclib\Math\BigInteger $arg2 - * @return \phpseclib\Math\BigInteger - * @access public - */ - public static function randomRange(BigInteger $min, BigInteger $max) - { - $compare = $max->compare($min); - - if (!$compare) { - return $min; - } elseif ($compare < 0) { - // if $min is bigger then $max, swap $min and $max - $temp = $max; - $max = $min; - $min = $temp; - } - - static $one; - if (!isset($one)) { - $one = new static(1); - } - - $max = $max->subtract($min->subtract($one)); - - $size = strlen(ltrim($max->toBytes(), chr(0))); - - /* - doing $random % $max doesn't work because some numbers will be more likely to occur than others. - eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145 - would produce 5 whereas the only value of random that could produce 139 would be 139. ie. - not all numbers would be equally likely. some would be more likely than others. - - creating a whole new random number until you find one that is within the range doesn't work - because, for sufficiently small ranges, the likelihood that you'd get a number within that range - would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability - would be pretty high that $random would be greater than $max. - - phpseclib works around this using the technique described here: - - http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string - */ - $random_max = new static(chr(1) . str_repeat("\0", $size), 256); - $random = new static(Random::string($size), 256); - - list($max_multiple) = $random_max->divide($max); - $max_multiple = $max_multiple->multiply($max); - - while ($random->compare($max_multiple) >= 0) { - $random = $random->subtract($max_multiple); - $random_max = $random_max->subtract($max_multiple); - $random = $random->bitwise_leftShift(8); - $random = $random->add(new static(Random::string(1), 256)); - $random_max = $random_max->bitwise_leftShift(8); - list($max_multiple) = $random_max->divide($max); - $max_multiple = $max_multiple->multiply($max); - } - list(, $random) = $random->divide($max); - - return $random->add($min); - } - - /** - * Generates a random prime number of a certain size - * - * Bit length is equal to $size - * - * @param int $size - * @return \phpseclib\Math\BigInteger - * @access public - */ - public static function randomPrime($size) - { - extract(self::minMaxBits($size)); - return self::randomRangePrime($min, $max); - } - - /** - * Generate a random prime number between a range - * - * If there's not a prime within the given range, false will be returned. - * - * @param \phpseclib\Math\BigInteger $min - * @param \phpseclib\Math\BigInteger $max - * @return Math_BigInteger|false - * @access public - * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}. - */ - public static function randomRangePrime(BigInteger $min, BigInteger $max) - { - $compare = $max->compare($min); - - if (!$compare) { - return $min->isPrime() ? $min : false; - } elseif ($compare < 0) { - // if $min is bigger then $max, swap $min and $max - $temp = $max; - $max = $min; - $min = $temp; - } - - static $one, $two; - if (!isset($one)) { - $one = new static(1); - $two = new static(2); - } - - $x = self::randomRange($min, $max); - - // gmp_nextprime() requires PHP 5 >= 5.2.0 per . - if (MATH_BIGINTEGER_MODE == self::MODE_GMP && extension_loaded('gmp')) { - $p = new static(); - $p->value = gmp_nextprime($x->value); - - if ($p->compare($max) <= 0) { - return $p; - } - - if (!$min->equals($x)) { - $x = $x->subtract($one); - } - - return self::randomRangePrime($min, $x); - } - - if ($x->equals($two)) { - return $x; - } - - $x->_make_odd(); - if ($x->compare($max) > 0) { - // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range - if ($min->equals($max)) { - return false; - } - $x = clone $min; - $x->_make_odd(); - } - - $initial_x = clone $x; - - while (true) { - if ($x->isPrime()) { - return $x; - } - - $x = $x->add($two); - - if ($x->compare($max) > 0) { - $x = clone $min; - if ($x->equals($two)) { - return $x; - } - $x->_make_odd(); - } - - if ($x->equals($initial_x)) { - return false; - } - } - } - - /** - * Make the current number odd - * - * If the current number is odd it'll be unchanged. If it's even, one will be added to it. - * - * @see self::randomPrime() - * @access private - */ - private function _make_odd() - { - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - gmp_setbit($this->value, 0); - break; - case self::MODE_BCMATH: - if ($this->value[strlen($this->value) - 1] % 2 == 0) { - $this->value = bcadd($this->value, '1'); - } - break; - default: - $this->value[0] |= 1; - } - } - - /** - * Checks a numer to see if it's prime - * - * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the - * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads - * on a website instead of just one. - * - * @param \phpseclib\Math\BigInteger $t - * @return bool - * @access public - * @internal Uses the - * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}. - */ - public function isPrime($t = false) - { - $length = strlen($this->toBytes()); - - if (!$t) { - // see HAC 4.49 "Note (controlling the error probability)" - // @codingStandardsIgnoreStart - if ($length >= 163) { $t = 2; } // floor(1300 / 8) - else if ($length >= 106) { $t = 3; } // floor( 850 / 8) - else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8) - else if ($length >= 68 ) { $t = 5; } // floor( 550 / 8) - else if ($length >= 56 ) { $t = 6; } // floor( 450 / 8) - else if ($length >= 50 ) { $t = 7; } // floor( 400 / 8) - else if ($length >= 43 ) { $t = 8; } // floor( 350 / 8) - else if ($length >= 37 ) { $t = 9; } // floor( 300 / 8) - else if ($length >= 31 ) { $t = 12; } // floor( 250 / 8) - else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8) - else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8) - else { $t = 27; } - // @codingStandardsIgnoreEnd - } - - // ie. gmp_testbit($this, 0) - // ie. isEven() or !isOdd() - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - return gmp_prob_prime($this->value, $t) != 0; - case self::MODE_BCMATH: - if ($this->value === '2') { - return true; - } - if ($this->value[strlen($this->value) - 1] % 2 == 0) { - return false; - } - break; - default: - if ($this->value == array(2)) { - return true; - } - if (~$this->value[0] & 1) { - return false; - } - } - - static $primes, $zero, $one, $two; - - if (!isset($primes)) { - $primes = array( - 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997 - ); - - if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { - for ($i = 0; $i < count($primes); ++$i) { - $primes[$i] = new static($primes[$i]); - } - } - - $zero = new static(); - $one = new static(1); - $two = new static(2); - } - - if ($this->equals($one)) { - return false; - } - - // see HAC 4.4.1 "Random search for probable primes" - if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { - foreach ($primes as $prime) { - list(, $r) = $this->divide($prime); - if ($r->equals($zero)) { - return $this->equals($prime); - } - } - } else { - $value = $this->value; - foreach ($primes as $prime) { - list(, $r) = self::_divide_digit($value, $prime); - if (!$r) { - return count($value) == 1 && $value[0] == $prime; - } - } - } - - $n = clone $this; - $n_1 = $n->subtract($one); - $n_2 = $n->subtract($two); - - $r = clone $n_1; - $r_value = $r->value; - // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); - if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { - $s = 0; - // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier - while ($r->value[strlen($r->value) - 1] % 2 == 0) { - $r->value = bcdiv($r->value, '2', 0); - ++$s; - } - } else { - for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) { - $temp = ~$r_value[$i] & 0xFFFFFF; - for ($j = 1; ($temp >> $j) & 1; ++$j) { - } - if ($j != 25) { - break; - } - } - $s = 26 * $i + $j - 1; - $r->_rshift($s); - } - - for ($i = 0; $i < $t; ++$i) { - $a = self::randomRange($two, $n_2); - $y = $a->modPow($r, $n); - - if (!$y->equals($one) && !$y->equals($n_1)) { - for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) { - $y = $y->modPow($two, $n); - if ($y->equals($one)) { - return false; - } - } - - if (!$y->equals($n_1)) { - return false; - } - } - } - return true; - } - - /** - * Logical Left Shift - * - * Shifts BigInteger's by $shift bits. - * - * @param int $shift - * @access private - */ - private function _lshift($shift) - { - if ($shift == 0) { - return; - } - - $num_digits = (int) ($shift / self::$base); - $shift %= self::$base; - $shift = 1 << $shift; - - $carry = 0; - - for ($i = 0; $i < count($this->value); ++$i) { - $temp = $this->value[$i] * $shift + $carry; - $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $this->value[$i] = (int) ($temp - $carry * self::$baseFull); - } - - if ($carry) { - $this->value[count($this->value)] = $carry; - } - - while ($num_digits--) { - array_unshift($this->value, 0); - } - } - - /** - * Logical Right Shift - * - * Shifts BigInteger's by $shift bits. - * - * @param int $shift - * @access private - */ - private function _rshift($shift) - { - if ($shift == 0) { - return; - } - - $num_digits = (int) ($shift / self::$base); - $shift %= self::$base; - $carry_shift = self::$base - $shift; - $carry_mask = (1 << $shift) - 1; - - if ($num_digits) { - $this->value = array_slice($this->value, $num_digits); - } - - $carry = 0; - - for ($i = count($this->value) - 1; $i >= 0; --$i) { - $temp = $this->value[$i] >> $shift | $carry; - $carry = ($this->value[$i] & $carry_mask) << $carry_shift; - $this->value[$i] = $temp; - } - - $this->value = $this->_trim($this->value); - } - - /** - * Normalize - * - * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision - * - * @param \phpseclib\Math\BigInteger - * @return \phpseclib\Math\BigInteger - * @see self::_trim() - * @access private - */ - private function _normalize($result) - { - $result->precision = $this->precision; - $result->bitmask = $this->bitmask; - - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - if ($this->bitmask !== false) { - $result->value = gmp_and($result->value, $result->bitmask->value); - } - - return $result; - case self::MODE_BCMATH: - if (!empty($result->bitmask->value)) { - $result->value = bcmod($result->value, $result->bitmask->value); - } - - return $result; - } - - $value = &$result->value; - - if (!count($value)) { - return $result; - } - - $value = $this->_trim($value); - - if (!empty($result->bitmask->value)) { - $length = min(count($value), count($this->bitmask->value)); - $value = array_slice($value, 0, $length); - - for ($i = 0; $i < $length; ++$i) { - $value[$i] = $value[$i] & $this->bitmask->value[$i]; - } - } - - return $result; - } - - /** - * Trim - * - * Removes leading zeros - * - * @param array $value - * @return \phpseclib\Math\BigInteger - * @access private - */ - private static function _trim($value) - { - for ($i = count($value) - 1; $i >= 0; --$i) { - if ($value[$i]) { - break; - } - unset($value[$i]); - } - - return $value; - } - - /** - * Array Repeat - * - * @param $input Array - * @param $multiplier mixed - * @return array - * @access private - */ - private static function _array_repeat($input, $multiplier) - { - return ($multiplier) ? array_fill(0, $multiplier, $input) : array(); - } - - /** - * Logical Left Shift - * - * Shifts binary strings $shift bits, essentially multiplying by 2**$shift. - * - * @param $x String - * @param $shift Integer - * @return string - * @access private - */ - private static function _base256_lshift(&$x, $shift) - { - if ($shift == 0) { - return; - } - - $num_bytes = $shift >> 3; // eg. floor($shift/8) - $shift &= 7; // eg. $shift % 8 - - $carry = 0; - for ($i = strlen($x) - 1; $i >= 0; --$i) { - $temp = ord($x[$i]) << $shift | $carry; - $x[$i] = chr($temp); - $carry = $temp >> 8; - } - $carry = ($carry != 0) ? chr($carry) : ''; - $x = $carry . $x . str_repeat(chr(0), $num_bytes); - } - - /** - * Logical Right Shift - * - * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder. - * - * @param $x String - * @param $shift Integer - * @return string - * @access private - */ - private static function _base256_rshift(&$x, $shift) - { - if ($shift == 0) { - $x = ltrim($x, chr(0)); - return ''; - } - - $num_bytes = $shift >> 3; // eg. floor($shift/8) - $shift &= 7; // eg. $shift % 8 - - $remainder = ''; - if ($num_bytes) { - $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes; - $remainder = substr($x, $start); - $x = substr($x, 0, -$num_bytes); - } - - $carry = 0; - $carry_shift = 8 - $shift; - for ($i = 0; $i < strlen($x); ++$i) { - $temp = (ord($x[$i]) >> $shift) | $carry; - $carry = (ord($x[$i]) << $carry_shift) & 0xFF; - $x[$i] = chr($temp); - } - $x = ltrim($x, chr(0)); - - $remainder = chr($carry >> $carry_shift) . $remainder; - - return ltrim($remainder, chr(0)); - } - - // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long - // at 32-bits, while java's longs are 64-bits. - - /** - * Converts 32-bit integers to bytes. - * - * @param int $x - * @return string - * @access private - */ - private static function _int2bytes($x) - { - return ltrim(pack('N', $x), chr(0)); - } - - /** - * Converts bytes to 32-bit integers - * - * @param string $x - * @return int - * @access private - */ - private static function _bytes2int($x) - { - $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT)); - return $temp['int']; - } - - /** - * Single digit division - * - * Even if int64 is being used the division operator will return a float64 value - * if the dividend is not evenly divisible by the divisor. Since a float64 doesn't - * have the precision of int64 this is a problem so, when int64 is being used, - * we'll guarantee that the dividend is divisible by first subtracting the remainder. - * - * @access private - * @param int $x - * @param int $y - * @return int - */ - private static function _safe_divide($x, $y) - { - if (self::$base === 26) { - return (int) ($x / $y); - } - - // self::$base === 31 - return ($x - ($x % $y)) / $y; - } - - /** - * Calculates the nth root of a biginteger. - * - * Returns the nth root of a positive biginteger, where n defaults to 2 - * - * Here's an example: - * - * root(); - * - * echo $root->toString(); // outputs 25 - * ?> - * - * - * @param \phpseclib\Math\BigInteger $n - * @access public - * @return \phpseclib\Math\BigInteger - * @internal This function is based off of {@link http://mathforum.org/library/drmath/view/52605.html this page} and {@link http://stackoverflow.com/questions/11242920/calculating-nth-root-with-bcmath-in-php this stackoverflow question}. - */ - public function root($n = null) - { - static $zero, $one, $two; - if (!isset($one)) { - $zero = new static(0); - $one = new static(1); - $two = new static(2); - } - if ($n === null) { - $n = $two; - } - if ($n->compare($one) == -1) { - return $zero; - } // we want positive exponents - if ($this->compare($one) == -1) { - return new static(0); - } // we want positive numbers - if ($this->compare($two) == -1) { - return $one; - } // n-th root of 1 or 2 is 1 - - $root = new static(); - if (MATH_BIGINTEGER_MODE == self::MODE_GMP && function_exists('gmp_root')) { - $root->value = gmp_root($this->value, gmp_intval($n->value)); - return $this->_normalize($root); - } - - // g is our guess number - $g = $two; - // while (g^n < num) g=g*2 - while ($g->pow($n)->compare($this) == -1) { - $g = $g->multiply($two); - } - // if (g^n==num) num is a power of 2, we're lucky, end of job - // == 0 bccomp(bcpow($g,$n), $n->value)==0 - if ($g->pow($n)->equals($this)) { - $root = $g; - return $this->_normalize($root); - } - - // if we're here num wasn't a power of 2 :( - $og = $g; // og means original guess and here is our upper bound - $g = $g->divide($two); // g is set to be our lower bound - $g = $g[0]; // g is set to be our lower bound - $step = $og->subtract($g)->divide($two); // step is the half of upper bound - lower bound - $step = $step[0]; // step is the half of upper bound - lower bound - $g = $g->add($step); // we start at lower bound + step , basically in the middle of our interval - - // while step>1 - - while ($step->compare($one) == 1) { - $guess = $g->pow($n); - $step = $step->divide($two); - $step = $step[0]; - $comp = $guess->compare($this); // compare our guess with real number - switch ($comp) { - case -1: // if guess is lower we add the new step - $g = $g->add($step); - break; - case 1: // if guess is higher we sub the new step - $g = $g->subtract($step); - break; - case 0: // if guess is exactly the num we're done, we return the value - $root = $g; - break 2; - } - } - - if ($comp == 1) { - $g = $g->subtract($step); - } - - // whatever happened, g is the closest guess we can make so return it - $root = $g; - - return $this->_normalize($root); - } - - /** - * Performs exponentiation. - * - * @param \phpseclib\Math\BigInteger $n - * @access public - * @return \phpseclib\Math\BigInteger - */ - public function pow($n) - { - $zero = new static(0); - if ($n->compare($zero) == 0) { - return new static(1); - } // n^0 = 1 - - $res = new static(); - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $res->value = gmp_pow($this->value, gmp_intval($n->value)); - - return $this->_normalize($res); - case self::MODE_BCMATH: - $res->value = bcpow($this->value, $n->value); - - return $this->_normalize($res); - default: - $one = new static(1); - $res = $this; - while (!$n->equals($one)) { - $res = $res->multiply($this); - $n = $n->subtract($one); - } - - return $res; - } - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param \phpseclib\Math\BigInteger ...$param - * @access public - * @return \phpseclib\Math\BigInteger - */ - public static function min() - { - $args = func_get_args(); - if (count($args) == 1) { - return $args[0]; - } - $min = $args[0]; - for ($i = 1; $i < count($args); $i++) { - $min = $min->compare($args[$i]) > 0 ? $args[$i] : $min; - } - return $min; - } - - /** - * Return the maximum BigInteger between an arbitrary number of BigIntegers. - * - * @param \phpseclib\Math\BigInteger ...$param - * @access public - * @return \phpseclib\Math\BigInteger - */ - public static function max() - { - $args = func_get_args(); - if (count($args) == 1) { - return $args[0]; - } - $max = $args[0]; - for ($i = 1; $i < count($args); $i++) { - $max = $max->compare($args[$i]) < 0 ? $args[$i] : $max; - } - return $max; - } - - /** - * Return the size of a BigInteger in bits - * - * @access public - * @return int - */ - public function getLength() - { - return strlen($this->toBits()); - } - - /** - * Return the size of a BigInteger in bytes - * - * @access public - * @return int - */ - public function getLengthInBytes() - { - return strlen($this->toBytes()); - } - - /** - * Tests BigInteger to see if it is between two integers, inclusive - * - * @param \phpseclib\Math\BigInteger $min - * @param \phpseclib\Math\BigInteger $max - * @access public - * @return boolean - */ - function between(BigInteger $min, BigInteger $max) - { - return $this->compare($min) >= 0 && $this->compare($max) <= 0; - } -} diff --git a/lib/phpaes/phpseclib/Net/SCP.php b/lib/phpaes/phpseclib/Net/SCP.php deleted file mode 100644 index 78d46a0fb9..0000000000 --- a/lib/phpaes/phpseclib/Net/SCP.php +++ /dev/null @@ -1,341 +0,0 @@ - - * login('username', 'password')) { - * exit('bad login'); - * } - * $scp = new \phpseclib\Net\SCP($ssh); - * - * $scp->put('abcd', str_repeat('x', 1024*1024)); - * ?> - * - * - * @category Net - * @package SCP - * @author Jim Wigginton - * @copyright 2010 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Net; - -use phpseclib\Exception\FileNotFoundException; -use phpseclib\Common\Functions\Strings; -use phpseclib\Common\Functions\Objects; - -/** - * Pure-PHP implementations of SCP. - * - * @package SCP - * @author Jim Wigginton - * @access public - */ -class SCP -{ - /**#@+ - * @access public - * @see \phpseclib\Net\SCP::put() - */ - /** - * Reads data from a local file. - */ - const SOURCE_LOCAL_FILE = 1; - /** - * Reads data from a string. - */ - const SOURCE_STRING = 2; - /**#@-*/ - - /**#@+ - * @access private - * @see \phpseclib\Net\SCP::_send() - * @see \phpseclib\Net\SCP::_receive() - */ - /** - * SSH1 is being used. - */ - const MODE_SSH1 = 1; - /** - * SSH2 is being used. - */ - const MODE_SSH2 = 2; - /**#@-*/ - - /** - * SSH Object - * - * @var object - * @access private - */ - private $ssh; - - /** - * Packet Size - * - * @var int - * @access private - */ - private $packet_size; - - /** - * Mode - * - * @var int - * @access private - */ - private $mode; - - /** - * Default Constructor. - * - * Connects to an SSH server - * - * @param \phpseclib\Net\SSH1|\phpseclib\Net\SSH2 $ssh - * @return \phpseclib\Net\SCP - * @access public - */ - public function __construct($ssh) - { - if ($ssh instanceof SSH2) { - $this->mode = self::MODE_SSH2; - } elseif ($ssh instanceof SSH1) { - $this->packet_size = 50000; - $this->mode = self::MODE_SSH1; - } else { - return; - } - - $this->ssh = $ssh; - } - - /** - * Uploads a file to the SCP server. - * - * By default, \phpseclib\Net\SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file. - * So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SCP::get(), you will get a file, twelve bytes - * long, containing 'filename.ext' as its contents. - * - * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will - * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how - * large $remote_file will be, as well. - * - * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take - * care of that, yourself. - * - * @param string $remote_file - * @param string $data - * @param int $mode - * @param callable $callback - * @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist - * @return bool - * @access public - */ - public function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null) - { - if (!isset($this->ssh)) { - return false; - } - - if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to - return false; - } - - $temp = $this->receive(); - if ($temp !== chr(0)) { - return false; - } - - if ($this->mode == self::MODE_SSH2) { - $this->packet_size = Objects::getVar($this->ssh, 'packet_size_client_to_server')[SSH2::CHANNEL_EXEC] - 4; - } - - $remote_file = basename($remote_file); - - if ($mode == self::SOURCE_STRING) { - $size = strlen($data); - } else { - if (!is_file($data)) { - throw new FileNotFoundException("$data is not a valid file"); - } - - $fp = @fopen($data, 'rb'); - if (!$fp) { - return false; - } - $size = filesize($data); - } - - $this->send('C0644 ' . $size . ' ' . $remote_file . "\n"); - - $temp = $this->receive(); - if ($temp !== chr(0)) { - return false; - } - - $sent = 0; - while ($sent < $size) { - $temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size); - $this->send($temp); - $sent+= strlen($temp); - - if (is_callable($callback)) { - call_user_func($callback, $sent); - } - } - $this->close(); - - if ($mode != self::SOURCE_STRING) { - fclose($fp); - } - - return true; - } - - /** - * Downloads a file from the SCP server. - * - * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if - * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the - * operation - * - * @param string $remote_file - * @param string $local_file - * @return mixed - * @access public - */ - public function get($remote_file, $local_file = false) - { - if (!isset($this->ssh)) { - return false; - } - - if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from - return false; - } - - $this->send("\0"); - - if (!preg_match('#(?[^ ]+) (?\d+) (?.+)#', rtrim($this->receive()), $info)) { - return false; - } - - $this->send("\0"); - - $size = 0; - - if ($local_file !== false) { - $fp = @fopen($local_file, 'wb'); - if (!$fp) { - return false; - } - } - - $content = ''; - while ($size < $info['size']) { - $data = $this->receive(); - // SCP usually seems to split stuff out into 16k chunks - $size+= strlen($data); - - if ($local_file === false) { - $content.= $data; - } else { - fputs($fp, $data); - } - } - - $this->close(); - - if ($local_file !== false) { - fclose($fp); - return true; - } - - return $content; - } - - /** - * Sends a packet to an SSH server - * - * @param string $data - * @access private - */ - private function send($data) - { - switch ($this->mode) { - case self::MODE_SSH2: - Objects::callFunc($this->ssh, 'send_channel_packet', [SSH2::CHANNEL_EXEC, $data]); - break; - case self::MODE_SSH1: - $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data); - Objects::callFunc($this->ssh, 'send_binary_packet', [$data]); - } - } - - /** - * Receives a packet from an SSH server - * - * @return string - * @throws \UnexpectedValueException on receipt of an unexpected packet - * @access private - */ - private function receive() - { - switch ($this->mode) { - case self::MODE_SSH2: - return Objects::callFunc($this->ssh, 'get_channel_packet', [SSH2::CHANNEL_EXEC, true]); - case self::MODE_SSH1: - if (!Objects::getVar($this->ssh, 'bitmap')) { - return false; - } - while (true) { - $response = Objects::getFunc($this->ssh, 'get_binary_packet'); - switch ($response[SSH1::RESPONSE_TYPE]) { - case NET_SSH1_SMSG_STDOUT_DATA: - if (strlen($response[SSH1::RESPONSE_DATA]) < 4) { - return false; - } - extract(unpack('Nlength', $response[SSH1::RESPONSE_DATA])); - return Strings::shift($response[SSH1::RESPONSE_DATA], $length); - case NET_SSH1_SMSG_STDERR_DATA: - break; - case NET_SSH1_SMSG_EXITSTATUS: - Objects::callFunc($this->ssh, 'send_binary_packet', [chr(NET_SSH1_CMSG_EXIT_CONFIRMATION)]); - fclose(Objects::getVar($this->ssh, 'fsock')); - Objects::setVar($this->ssh, 'bitmap', 0); - return false; - default: - throw new \UnexpectedValueException('Unknown packet received'); - } - } - } - } - - /** - * Closes the connection to an SSH server - * - * @access private - */ - private function close() - { - switch ($this->mode) { - case self::MODE_SSH2: - Objects::callFunc($this->ssh, 'close_channel', [SSH2::CHANNEL_EXEC, true]); - break; - case self::MODE_SSH1: - Objects::callFunc($this->ssh, 'disconnect'); - } - } -} diff --git a/lib/phpaes/phpseclib/Net/SFTP.php b/lib/phpaes/phpseclib/Net/SFTP.php deleted file mode 100644 index ab081a2a9b..0000000000 --- a/lib/phpaes/phpseclib/Net/SFTP.php +++ /dev/null @@ -1,3046 +0,0 @@ - - * login('username', 'password')) { - * exit('Login Failed'); - * } - * - * echo $sftp->pwd() . "\r\n"; - * $sftp->put('filename.ext', 'hello, world!'); - * print_r($sftp->nlist()); - * ?> - * - * - * @category Net - * @package SFTP - * @author Jim Wigginton - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Net; - -use ParagonIE\ConstantTime\Hex; -use phpseclib\Exception\FileNotFoundException; -use phpseclib\Common\Functions\Strings; - -/** - * Pure-PHP implementations of SFTP. - * - * @package SFTP - * @author Jim Wigginton - * @access public - */ -class SFTP extends SSH2 -{ - /** - * SFTP channel constant - * - * \phpseclib\Net\SSH2::exec() uses 0 and \phpseclib\Net\SSH2::read() / \phpseclib\Net\SSH2::write() use 1. - * - * @see \phpseclib\Net\SSH2::_send_channel_packet() - * @see \phpseclib\Net\SSH2::_get_channel_packet() - * @access private - */ - const CHANNEL = 0x100; - - /**#@+ - * @access public - * @see \phpseclib\Net\SFTP::put() - */ - /** - * Reads data from a local file. - */ - const SOURCE_LOCAL_FILE = 1; - /** - * Reads data from a string. - */ - // this value isn't really used anymore but i'm keeping it reserved for historical reasons - const SOURCE_STRING = 2; - /** - * Reads data from callback: - * function callback($length) returns string to proceed, null for EOF - */ - const SOURCE_CALLBACK = 16; - /** - * Resumes an upload - */ - const RESUME = 4; - /** - * Append a local file to an already existing remote file - */ - const RESUME_START = 8; - /**#@-*/ - - /** - * Packet Types - * - * @see self::__construct() - * @var array - * @access private - */ - private $packet_types = []; - - /** - * Status Codes - * - * @see self::__construct() - * @var array - * @access private - */ - private $status_codes = []; - - /** - * The Request ID - * - * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support - * concurrent actions, so it's somewhat academic, here. - * - * @var int - * @see self::_send_sftp_packet() - * @access private - */ - private $request_id = false; - - /** - * The Packet Type - * - * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support - * concurrent actions, so it's somewhat academic, here. - * - * @var int - * @see self::_get_sftp_packet() - * @access private - */ - private $packet_type = -1; - - /** - * Packet Buffer - * - * @var string - * @see self::_get_sftp_packet() - * @access private - */ - private $packet_buffer = ''; - - /** - * Extensions supported by the server - * - * @var array - * @see self::_initChannel() - * @access private - */ - private $extensions = []; - - /** - * Server SFTP version - * - * @var int - * @see self::_initChannel() - * @access private - */ - private $version; - - /** - * Current working directory - * - * @var string - * @see self::_realpath() - * @see self::chdir() - * @access private - */ - private $pwd = false; - - /** - * Packet Type Log - * - * @see self::getLog() - * @var array - * @access private - */ - private $packet_type_log = []; - - /** - * Packet Log - * - * @see self::getLog() - * @var array - * @access private - */ - private $packet_log = []; - - /** - * Error information - * - * @see self::getSFTPErrors() - * @see self::getLastSFTPError() - * @var string - * @access private - */ - private $sftp_errors = []; - - /** - * Stat Cache - * - * Rather than always having to open a directory and close it immediately there after to see if a file is a directory - * we'll cache the results. - * - * @see self::_update_stat_cache() - * @see self::_remove_from_stat_cache() - * @see self::_query_stat_cache() - * @var array - * @access private - */ - private $stat_cache = []; - - /** - * Max SFTP Packet Size - * - * @see self::__construct() - * @see self::get() - * @var array - * @access private - */ - private $max_sftp_packet; - - /** - * Stat Cache Flag - * - * @see self::disableStatCache() - * @see self::enableStatCache() - * @var bool - * @access private - */ - private $use_stat_cache = true; - - /** - * Sort Options - * - * @see self::_comparator() - * @see self::setListOrder() - * @var array - * @access private - */ - private $sortOptions = []; - - /** - * Default Constructor. - * - * Connects to an SFTP server - * - * @param string $host - * @param int $port - * @param int $timeout - * @return \phpseclib\Net\SFTP - * @access public - */ - public function __construct($host, $port = 22, $timeout = 10) - { - parent::__construct($host, $port, $timeout); - - $this->max_sftp_packet = 1 << 15; - - $this->packet_types = [ - 1 => 'NET_SFTP_INIT', - 2 => 'NET_SFTP_VERSION', - /* the format of SSH_FXP_OPEN changed between SFTPv4 and SFTPv5+: - SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.1 - pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 */ - 3 => 'NET_SFTP_OPEN', - 4 => 'NET_SFTP_CLOSE', - 5 => 'NET_SFTP_READ', - 6 => 'NET_SFTP_WRITE', - 7 => 'NET_SFTP_LSTAT', - 9 => 'NET_SFTP_SETSTAT', - 11 => 'NET_SFTP_OPENDIR', - 12 => 'NET_SFTP_READDIR', - 13 => 'NET_SFTP_REMOVE', - 14 => 'NET_SFTP_MKDIR', - 15 => 'NET_SFTP_RMDIR', - 16 => 'NET_SFTP_REALPATH', - 17 => 'NET_SFTP_STAT', - /* the format of SSH_FXP_RENAME changed between SFTPv4 and SFTPv5+: - SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3 - pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */ - 18 => 'NET_SFTP_RENAME', - 19 => 'NET_SFTP_READLINK', - 20 => 'NET_SFTP_SYMLINK', - - 101=> 'NET_SFTP_STATUS', - 102=> 'NET_SFTP_HANDLE', - /* the format of SSH_FXP_NAME changed between SFTPv3 and SFTPv4+: - SFTPv4+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4 - pre-SFTPv4 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7 */ - 103=> 'NET_SFTP_DATA', - 104=> 'NET_SFTP_NAME', - 105=> 'NET_SFTP_ATTRS', - - 200=> 'NET_SFTP_EXTENDED' - ]; - $this->status_codes = [ - 0 => 'NET_SFTP_STATUS_OK', - 1 => 'NET_SFTP_STATUS_EOF', - 2 => 'NET_SFTP_STATUS_NO_SUCH_FILE', - 3 => 'NET_SFTP_STATUS_PERMISSION_DENIED', - 4 => 'NET_SFTP_STATUS_FAILURE', - 5 => 'NET_SFTP_STATUS_BAD_MESSAGE', - 6 => 'NET_SFTP_STATUS_NO_CONNECTION', - 7 => 'NET_SFTP_STATUS_CONNECTION_LOST', - 8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED', - 9 => 'NET_SFTP_STATUS_INVALID_HANDLE', - 10 => 'NET_SFTP_STATUS_NO_SUCH_PATH', - 11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS', - 12 => 'NET_SFTP_STATUS_WRITE_PROTECT', - 13 => 'NET_SFTP_STATUS_NO_MEDIA', - 14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM', - 15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED', - 16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL', - 17 => 'NET_SFTP_STATUS_LOCK_CONFLICT', - 18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY', - 19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY', - 20 => 'NET_SFTP_STATUS_INVALID_FILENAME', - 21 => 'NET_SFTP_STATUS_LINK_LOOP', - 22 => 'NET_SFTP_STATUS_CANNOT_DELETE', - 23 => 'NET_SFTP_STATUS_INVALID_PARAMETER', - 24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY', - 25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT', - 26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED', - 27 => 'NET_SFTP_STATUS_DELETE_PENDING', - 28 => 'NET_SFTP_STATUS_FILE_CORRUPT', - 29 => 'NET_SFTP_STATUS_OWNER_INVALID', - 30 => 'NET_SFTP_STATUS_GROUP_INVALID', - 31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK' - ]; - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1 - // the order, in this case, matters quite a lot - see \phpseclib\Net\SFTP::_parseAttributes() to understand why - $this->attributes = [ - 0x00000001 => 'NET_SFTP_ATTR_SIZE', - 0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+ - 0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS', - 0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME', - // 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers - // yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in - // two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000. - // that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored. - -1 << 31 => 'NET_SFTP_ATTR_EXTENDED' - ]; - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 - // the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name - // the array for that $this->open5_flags and similarly alter the constant names. - $this->open_flags = [ - 0x00000001 => 'NET_SFTP_OPEN_READ', - 0x00000002 => 'NET_SFTP_OPEN_WRITE', - 0x00000004 => 'NET_SFTP_OPEN_APPEND', - 0x00000008 => 'NET_SFTP_OPEN_CREATE', - 0x00000010 => 'NET_SFTP_OPEN_TRUNCATE', - 0x00000020 => 'NET_SFTP_OPEN_EXCL' - ]; - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 - // see \phpseclib\Net\SFTP::_parseLongname() for an explanation - $this->file_types = [ - 1 => 'NET_SFTP_TYPE_REGULAR', - 2 => 'NET_SFTP_TYPE_DIRECTORY', - 3 => 'NET_SFTP_TYPE_SYMLINK', - 4 => 'NET_SFTP_TYPE_SPECIAL', - 5 => 'NET_SFTP_TYPE_UNKNOWN', - // the followin types were first defined for use in SFTPv5+ - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2 - 6 => 'NET_SFTP_TYPE_SOCKET', - 7 => 'NET_SFTP_TYPE_CHAR_DEVICE', - 8 => 'NET_SFTP_TYPE_BLOCK_DEVICE', - 9 => 'NET_SFTP_TYPE_FIFO' - ]; - $this->define_array( - $this->packet_types, - $this->status_codes, - $this->attributes, - $this->open_flags, - $this->file_types - ); - - if (!defined('NET_SFTP_QUEUE_SIZE')) { - define('NET_SFTP_QUEUE_SIZE', 32); - } - } - - /** - * Login - * - * @param string $username - * @param string $password - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - * @access public - */ - public function login($username) - { - $args = func_get_args(); - if (!call_user_func_array([&$this, 'sublogin'], $args)) { - return false; - } - - $this->window_size_server_to_client[self::CHANNEL] = $this->window_size; - - $packet = pack( - 'CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, - strlen('session'), - 'session', - self::CHANNEL, - $this->window_size, - 0x4000 - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN; - - $response = $this->get_channel_packet(self::CHANNEL); - if ($response === false) { - return false; - } - - $packet = pack( - 'CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL], - strlen('subsystem'), - 'subsystem', - 1, - strlen('sftp'), - 'sftp' - ); - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->get_channel_packet(self::CHANNEL); - if ($response === false) { - // from PuTTY's psftp.exe - $command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" . - "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" . - "exec sftp-server"; - // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does - // is redundant - $packet = pack( - 'CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL], - strlen('exec'), - 'exec', - 1, - strlen($command), - $command - ); - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->get_channel_packet(self::CHANNEL); - if ($response === false) { - return false; - } - } - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA; - - if (!$this->send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3")) { - return false; - } - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_VERSION) { - throw new \UnexpectedValueException('Expected SSH_FXP_VERSION'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nversion', Strings::shift($response, 4))); - $this->version = $version; - while (!empty($response)) { - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $key = Strings::shift($response, $length); - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $value = Strings::shift($response, $length); - $this->extensions[$key] = $value; - } - - /* - SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com', - however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's - not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for - one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that - 'newline@vandyke.com' would. - */ - /* - if (isset($this->extensions['newline@vandyke.com'])) { - $this->extensions['newline'] = $this->extensions['newline@vandyke.com']; - unset($this->extensions['newline@vandyke.com']); - } - */ - - $this->request_id = 1; - - /* - A Note on SFTPv4/5/6 support: - states the following: - - "If the client wishes to interoperate with servers that support noncontiguous version - numbers it SHOULD send '3'" - - Given that the server only sends its version number after the client has already done so, the above - seems to be suggesting that v3 should be the default version. This makes sense given that v3 is the - most popular. - - states the following; - - "If the server did not send the "versions" extension, or the version-from-list was not included, the - server MAY send a status response describing the failure, but MUST then close the channel without - processing any further requests." - - So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and - a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements - v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed - in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib\Net\SFTP would do is close the - channel and reopen it with a new and updated SSH_FXP_INIT packet. - */ - switch ($this->version) { - case 2: - case 3: - break; - default: - return false; - } - - $this->pwd = $this->realpath('.'); - - $this->update_stat_cache($this->pwd, []); - - return true; - } - - /** - * Disable the stat cache - * - * @access public - */ - function disableStatCache() - { - $this->use_stat_cache = false; - } - - /** - * Enable the stat cache - * - * @access public - */ - public function enableStatCache() - { - $this->use_stat_cache = true; - } - - /** - * Clear the stat cache - * - * @access public - */ - public function clearStatCache() - { - $this->stat_cache = []; - } - - /** - * Returns the current directory name - * - * @return mixed - * @access public - */ - public function pwd() - { - return $this->pwd; - } - - /** - * Logs errors - * - * @param string $response - * @param int $status - * @access private - */ - private function logError($response, $status = -1) - { - if ($status == -1) { - if (strlen($response) < 4) { - return; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - } - - $error = $this->status_codes[$status]; - - if ($this->version > 2 || strlen($response) < 4) { - extract(unpack('Nlength', Strings::shift($response, 4))); - $this->sftp_errors[] = $error . ': ' . Strings::shift($response, $length); - } else { - $this->sftp_errors[] = $error; - } - } - - /** - * Canonicalize the Server-Side Path Name - * - * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns - * the absolute (canonicalized) path. - * - * @see self::chdir() - * @param string $path - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - * @access public - */ - public function realpath($path) - { - if ($this->pwd === false) { - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9 - if (!$this->send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_NAME: - // although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following - // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks - // at is the first part and that part is defined the same in SFTP versions 3 through 6. - Strings::shift($response, 4); // skip over the count - it should be 1, anyway - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - return Strings::shift($response, $length); - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); - } - } - - if ($path[0] != '/') { - $path = $this->pwd . '/' . $path; - } - - $path = explode('/', $path); - $new = []; - foreach ($path as $dir) { - if (!strlen($dir)) { - continue; - } - switch ($dir) { - case '..': - array_pop($new); - case '.': - break; - default: - $new[] = $dir; - } - } - - return '/' . implode('/', $new); - } - - /** - * Changes the current directory - * - * @param string $dir - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - * @access public - */ - public function chdir($dir) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - // assume current dir if $dir is empty - if ($dir === '') { - $dir = './'; - // suffix a slash if needed - } elseif ($dir[strlen($dir) - 1] != '/') { - $dir.= '/'; - } - - $dir = $this->realpath($dir); - - // confirm that $dir is, in fact, a valid directory - if ($this->use_stat_cache && is_array($this->query_stat_cache($dir))) { - $this->pwd = $dir; - return true; - } - - // we could do a stat on the alleged $dir to see if it's a directory but that doesn't tell us - // the currently logged in user has the appropriate permissions or not. maybe you could see if - // the file's uid / gid match the currently logged in user's uid / gid but how there's no easy - // way to get those with SFTP - - if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) { - return false; - } - - // see \phpseclib\Net\SFTP::nlist() for a more thorough explanation of the following - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); - } - - if (!$this->close_handle($handle)) { - return false; - } - - $this->update_stat_cache($dir, []); - - $this->pwd = $dir; - return true; - } - - /** - * Returns a list of files in the given directory - * - * @param string $dir - * @param bool $recursive - * @return mixed - * @access public - */ - public function nlist($dir = '.', $recursive = false) - { - return $this->nlist_helper($dir, $recursive, ''); - } - - /** - * Helper method for nlist - * - * @param string $dir - * @param bool $recursive - * @param string $relativeDir - * @return mixed - * @access private - */ - private function nlist_helper($dir, $recursive, $relativeDir) - { - $files = $this->readlist($dir, false); - - if (!$recursive || $files === false) { - return $files; - } - - $result = []; - foreach ($files as $value) { - if ($value == '.' || $value == '..') { - if ($relativeDir == '') { - $result[] = $value; - } - continue; - } - if (is_array($this->query_stat_cache($this->realpath($dir . '/' . $value)))) { - $temp = $this->nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/'); - $result = array_merge($result, $temp); - } else { - $result[] = $relativeDir . $value; - } - } - - return $result; - } - - /** - * Returns a detailed list of files in the given directory - * - * @param string $dir - * @param bool $recursive - * @return mixed - * @access public - */ - public function rawlist($dir = '.', $recursive = false) - { - $files = $this->readlist($dir, true); - if (!$recursive || $files === false) { - return $files; - } - - static $depth = 0; - - foreach ($files as $key => $value) { - if ($depth != 0 && $key == '..') { - unset($files[$key]); - continue; - } - if ($key != '.' && $key != '..' && is_array($this->query_stat_cache($this->realpath($dir . '/' . $key)))) { - $depth++; - $files[$key] = $this->rawlist($dir . '/' . $key, true); - $depth--; - } else { - $files[$key] = (object) $value; - } - } - - return $files; - } - - /** - * Reads a list, be it detailed or not, of files in the given directory - * - * @param string $dir - * @param bool $raw - * @return mixed - * @throws \UnexpectedValueException on receipt of unexpected packets - * @access private - */ - private function readlist($dir, $raw = true) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $dir = $this->realpath($dir . '/'); - if ($dir === false) { - return false; - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2 - if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2 - // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that - // represent the length of the string and leave it at that - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: - // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); - } - - $this->update_stat_cache($dir, []); - - $contents = []; - while (true) { - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2 - // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many - // SSH_MSG_CHANNEL_DATA messages is not known to me. - if (!$this->send_sftp_packet(NET_SFTP_READDIR, pack('Na*', strlen($handle), $handle))) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_NAME: - if (strlen($response) < 4) { - return false; - } - extract(unpack('Ncount', Strings::shift($response, 4))); - for ($i = 0; $i < $count; $i++) { - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $shortname = Strings::shift($response, $length); - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $longname = Strings::shift($response, $length); - $attributes = $this->parseAttributes($response); - if (!isset($attributes['type'])) { - $fileType = $this->parseLongname($longname); - if ($fileType) { - $attributes['type'] = $fileType; - } - } - $contents[$shortname] = $attributes + ['filename' => $shortname]; - - if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) { - $this->update_stat_cache($dir . '/' . $shortname, []); - } else { - if ($shortname == '..') { - $temp = $this->realpath($dir . '/..') . '/.'; - } else { - $temp = $dir . '/' . $shortname; - } - $this->update_stat_cache($temp, (object) ['lstat' => $attributes]); - } - // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the - // final SSH_FXP_STATUS packet should tell us that, already. - } - break; - case NET_SFTP_STATUS: - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_EOF) { - $this->logError($response, $status); - return false; - } - break 2; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); - } - } - - if (!$this->close_handle($handle)) { - return false; - } - - if (count($this->sortOptions)) { - uasort($contents, [&$this, 'comparator']); - } - - return $raw ? $contents : array_keys($contents); - } - - /** - * Compares two rawlist entries using parameters set by setListOrder() - * - * Intended for use with uasort() - * - * @param array $a - * @param array $b - * @return int - * @access private - */ - private function comparator($a, $b) - { - switch (true) { - case $a['filename'] === '.' || $b['filename'] === '.': - if ($a['filename'] === $b['filename']) { - return 0; - } - return $a['filename'] === '.' ? -1 : 1; - case $a['filename'] === '..' || $b['filename'] === '..': - if ($a['filename'] === $b['filename']) { - return 0; - } - return $a['filename'] === '..' ? -1 : 1; - case isset($a['type']) && $a['type'] === NET_SFTP_TYPE_DIRECTORY: - if (!isset($b['type'])) { - return 1; - } - if ($b['type'] !== $a['type']) { - return -1; - } - break; - case isset($b['type']) && $b['type'] === NET_SFTP_TYPE_DIRECTORY: - return 1; - } - foreach ($this->sortOptions as $sort => $order) { - if (!isset($a[$sort]) || !isset($b[$sort])) { - if (isset($a[$sort])) { - return -1; - } - if (isset($b[$sort])) { - return 1; - } - return 0; - } - switch ($sort) { - case 'filename': - $result = strcasecmp($a['filename'], $b['filename']); - if ($result) { - return $order === SORT_DESC ? -$result : $result; - } - break; - case 'permissions': - case 'mode': - $a[$sort]&= 07777; - $b[$sort]&= 07777; - default: - if ($a[$sort] === $b[$sort]) { - break; - } - return $order === SORT_ASC ? $a[$sort] - $b[$sort] : $b[$sort] - $a[$sort]; - } - } - } - - /** - * Defines how nlist() and rawlist() will be sorted - if at all. - * - * If sorting is enabled directories and files will be sorted independently with - * directories appearing before files in the resultant array that is returned. - * - * Any parameter returned by stat is a valid sort parameter for this function. - * Filename comparisons are case insensitive. - * - * Examples: - * - * $sftp->setListOrder('filename', SORT_ASC); - * $sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC); - * $sftp->setListOrder(true); - * Separates directories from files but doesn't do any sorting beyond that - * $sftp->setListOrder(); - * Don't do any sort of sorting - * - * @access public - */ - public function setListOrder() - { - $this->sortOptions = []; - $args = func_get_args(); - if (empty($args)) { - return; - } - $len = count($args) & 0x7FFFFFFE; - for ($i = 0; $i < $len; $i+=2) { - $this->sortOptions[$args[$i]] = $args[$i + 1]; - } - if (!count($this->sortOptions)) { - $this->sortOptions = ['bogus' => true]; - } - } - - /** - * Returns the file size, in bytes, or false, on failure - * - * Files larger than 4GB will show up as being exactly 4GB. - * - * @param string $filename - * @return mixed - * @access public - */ - public function size($filename) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $result = $this->stat($filename); - if ($result === false) { - return false; - } - return isset($result['size']) ? $result['size'] : -1; - } - - /** - * Save files / directories to cache - * - * @param string $path - * @param mixed $value - * @access private - */ - private function update_stat_cache($path, $value) - { - if ($this->use_stat_cache === false) { - return; - } - - // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/')) - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - - $temp = &$this->stat_cache; - $max = count($dirs) - 1; - foreach ($dirs as $i => $dir) { - // if $temp is an object that means one of two things. - // 1. a file was deleted and changed to a directory behind phpseclib's back - // 2. it's a symlink. when lstat is done it's unclear what it's a symlink to - if (is_object($temp)) { - $temp = []; - } - if (!isset($temp[$dir])) { - $temp[$dir] = []; - } - if ($i === $max) { - if (is_object($temp[$dir])) { - if (!isset($value->stat) && isset($temp[$dir]->stat)) { - $value->stat = $temp[$dir]->stat; - } - if (!isset($value->lstat) && isset($temp[$dir]->lstat)) { - $value->lstat = $temp[$dir]->lstat; - } - } - $temp[$dir] = $value; - break; - } - $temp = &$temp[$dir]; - } - } - - /** - * Remove files / directories from cache - * - * @param string $path - * @return bool - * @access private - */ - private function remove_from_stat_cache($path) - { - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - - $temp = &$this->stat_cache; - $max = count($dirs) - 1; - foreach ($dirs as $i => $dir) { - if ($i === $max) { - unset($temp[$dir]); - return true; - } - if (!isset($temp[$dir])) { - return false; - } - $temp = &$temp[$dir]; - } - } - - /** - * Checks cache for path - * - * Mainly used by file_exists - * - * @param string $dir - * @return mixed - * @access private - */ - private function query_stat_cache($path) - { - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - - $temp = &$this->stat_cache; - foreach ($dirs as $dir) { - if (!isset($temp[$dir])) { - return null; - } - $temp = &$temp[$dir]; - } - return $temp; - } - - /** - * Returns general information about a file. - * - * Returns an array on success and false otherwise. - * - * @param string $filename - * @return mixed - * @access public - */ - public function stat($filename) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - if ($this->use_stat_cache) { - $result = $this->query_stat_cache($filename); - if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) { - return $result['.']->stat; - } - if (is_object($result) && isset($result->stat)) { - return $result->stat; - } - } - - $stat = $this->stat_helper($filename, NET_SFTP_STAT); - if ($stat === false) { - $this->remove_from_stat_cache($filename); - return false; - } - if (isset($stat['type'])) { - if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename.= '/.'; - } - $this->update_stat_cache($filename, (object) ['stat' => $stat]); - return $stat; - } - - $pwd = $this->pwd; - $stat['type'] = $this->chdir($filename) ? - NET_SFTP_TYPE_DIRECTORY : - NET_SFTP_TYPE_REGULAR; - $this->pwd = $pwd; - - if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename.= '/.'; - } - $this->update_stat_cache($filename, (object) ['stat' => $stat]); - - return $stat; - } - - /** - * Returns general information about a file or symbolic link. - * - * Returns an array on success and false otherwise. - * - * @param string $filename - * @return mixed - * @access public - */ - public function lstat($filename) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - if ($this->use_stat_cache) { - $result = $this->query_stat_cache($filename); - if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) { - return $result['.']->lstat; - } - if (is_object($result) && isset($result->lstat)) { - return $result->lstat; - } - } - - $lstat = $this->stat_helper($filename, NET_SFTP_LSTAT); - if ($lstat === false) { - $this->remove_from_stat_cache($filename); - return false; - } - if (isset($lstat['type'])) { - if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename.= '/.'; - } - $this->update_stat_cache($filename, (object) ['lstat' => $lstat]); - return $lstat; - } - - $stat = $this->stat_helper($filename, NET_SFTP_STAT); - - if ($lstat != $stat) { - $lstat = array_merge($lstat, ['type' => NET_SFTP_TYPE_SYMLINK]); - $this->update_stat_cache($filename, (object) ['lstat' => $lstat]); - return $stat; - } - - $pwd = $this->pwd; - $lstat['type'] = $this->chdir($filename) ? - NET_SFTP_TYPE_DIRECTORY : - NET_SFTP_TYPE_REGULAR; - $this->pwd = $pwd; - - if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename.= '/.'; - } - $this->update_stat_cache($filename, (object) ['lstat' => $lstat]); - - return $lstat; - } - - /** - * Returns general information about a file or symbolic link - * - * Determines information without calling \phpseclib\Net\SFTP::_realpath(). - * The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT. - * - * @param string $filename - * @param int $type - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - * @access private - */ - private function stat_helper($filename, $type) - { - // SFTPv4+ adds an additional 32-bit integer field - flags - to the following: - $packet = pack('Na*', strlen($filename), $filename); - if (!$this->send_sftp_packet($type, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_ATTRS: - return $this->parseAttributes($response); - case NET_SFTP_STATUS: - $this->logError($response); - return false; - } - - throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); - } - - /** - * Truncates a file to a given length - * - * @param string $filename - * @param int $new_size - * @return bool - * @access public - */ - public function truncate($filename, $new_size) - { - $attr = pack('N3', NET_SFTP_ATTR_SIZE, $new_size / 4294967296, $new_size); // 4294967296 == 0x100000000 == 1<<32 - - return $this->setstat($filename, $attr, false); - } - - /** - * Sets access and modification time of file. - * - * If the file does not exist, it will be created. - * - * @param string $filename - * @param int $time - * @param int $atime - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - * @access public - */ - public function touch($filename, $time = null, $atime = null) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - if (!isset($time)) { - $time = time(); - } - if (!isset($atime)) { - $atime = $time; - } - - $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL; - $attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime); - $packet = pack('Na*Na*', strlen($filename), $filename, $flags, $attr); - if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - return $this->close_handle(substr($response, 4)); - case NET_SFTP_STATUS: - $this->logError($response); - break; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); - } - - return $this->setstat($filename, $attr, false); - } - - /** - * Changes file or directory owner - * - * Returns true on success or false on error. - * - * @param string $filename - * @param int $uid - * @param bool $recursive - * @return bool - * @access public - */ - public function chown($filename, $uid, $recursive = false) - { - // quoting from , - // "if the owner or group is specified as -1, then that ID is not changed" - $attr = pack('N3', NET_SFTP_ATTR_UIDGID, $uid, -1); - - return $this->setstat($filename, $attr, $recursive); - } - - /** - * Changes file or directory group - * - * Returns true on success or false on error. - * - * @param string $filename - * @param int $gid - * @param bool $recursive - * @return bool - * @access public - */ - public function chgrp($filename, $gid, $recursive = false) - { - $attr = pack('N3', NET_SFTP_ATTR_UIDGID, -1, $gid); - - return $this->setstat($filename, $attr, $recursive); - } - - /** - * Set permissions on a file. - * - * Returns the new file permissions on success or false on error. - * If $recursive is true than this just returns true or false. - * - * @param int $mode - * @param string $filename - * @param bool $recursive - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - * @access public - */ - public function chmod($mode, $filename, $recursive = false) - { - if (is_string($mode) && is_int($filename)) { - $temp = $mode; - $mode = $filename; - $filename = $temp; - } - - $attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777); - if (!$this->setstat($filename, $attr, $recursive)) { - return false; - } - if ($recursive) { - return true; - } - - $filename = $this->realPath($filename); - // rather than return what the permissions *should* be, we'll return what they actually are. this will also - // tell us if the file actually exists. - // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following: - $packet = pack('Na*', strlen($filename), $filename); - if (!$this->send_sftp_packet(NET_SFTP_STAT, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_ATTRS: - $attrs = $this->parseAttributes($response); - return $attrs['permissions']; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - } - - throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); - } - - /** - * Sets information about a file - * - * @param string $filename - * @param string $attr - * @param bool $recursive - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - * @access private - */ - private function setstat($filename, $attr, $recursive) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - $this->remove_from_stat_cache($filename); - - if ($recursive) { - $i = 0; - $result = $this->setstat_recursive($filename, $attr, $i); - $this->read_put_responses($i); - return $result; - } - - // SFTPv4+ has an additional byte field - type - that would need to be sent, as well. setting it to - // SSH_FILEXFER_TYPE_UNKNOWN might work. if not, we'd have to do an SSH_FXP_STAT before doing an SSH_FXP_SETSTAT. - if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($filename), $filename, $attr))) { - return false; - } - - /* - "Because some systems must use separate system calls to set various attributes, it is possible that a failure - response will be returned, but yet some of the attributes may be have been successfully modified. If possible, - servers SHOULD avoid this situation; however, clients MUST be aware that this is possible." - - -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6 - */ - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - return true; - } - - /** - * Recursively sets information on directories on the SFTP server - * - * Minimizes directory lookups and SSH_FXP_STATUS requests for speed. - * - * @param string $path - * @param string $attr - * @param int $i - * @return bool - * @access private - */ - private function setstat_recursive($path, $attr, &$i) - { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - $entries = $this->readlist($path, true); - - if ($entries === false) { - return $this->setstat($path, $attr, false); - } - - // normally $entries would have at least . and .. but it might not if the directories - // permissions didn't allow reading - if (empty($entries)) { - return false; - } - - unset($entries['.'], $entries['..']); - foreach ($entries as $filename => $props) { - if (!isset($props['type'])) { - return false; - } - - $temp = $path . '/' . $filename; - if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) { - if (!$this->setstat_recursive($temp, $attr, $i)) { - return false; - } - } else { - if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($temp), $temp, $attr))) { - return false; - } - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - } - } - - if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($path), $path, $attr))) { - return false; - } - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - - return true; - } - - /** - * Return the target of a symbolic link - * - * @param string $link - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - * @access public - */ - public function readlink($link) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $link = $this->realpath($link); - - if (!$this->send_sftp_packet(NET_SFTP_READLINK, pack('Na*', strlen($link), $link))) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_NAME: - break; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Ncount', Strings::shift($response, 4))); - // the file isn't a symlink - if (!$count) { - return false; - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - return Strings::shift($response, $length); - } - - /** - * Create a symlink - * - * symlink() creates a symbolic link to the existing target with the specified name link. - * - * @param string $target - * @param string $link - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - * @access public - */ - public function symlink($target, $link) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - //$target = $this->realpath($target); - $link = $this->realpath($link); - - $packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link); - if (!$this->send_sftp_packet(NET_SFTP_SYMLINK, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - return true; - } - - /** - * Creates a directory. - * - * @param string $dir - * @return bool - * @access public - */ - public function mkdir($dir, $mode = -1, $recursive = false) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $dir = $this->realpath($dir); - // by not providing any permissions, hopefully the server will use the logged in users umask - their - // default permissions. - $attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777); - - if ($recursive) { - $dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir)); - if (empty($dirs[0])) { - array_shift($dirs); - $dirs[0] = '/' . $dirs[0]; - } - for ($i = 0; $i < count($dirs); $i++) { - $temp = array_slice($dirs, 0, $i + 1); - $temp = implode('/', $temp); - $result = $this->mkdir_helper($temp, $attr); - } - return $result; - } - - return $this->mkdir_helper($dir, $attr); - } - - /** - * Helper function for directory creation - * - * @param string $dir - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @access private - */ - private function mkdir_helper($dir, $attr) - { - if (!$this->send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, $attr))) { - return false; - } - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - return true; - } - - /** - * Removes a directory. - * - * @param string $dir - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - * @access public - */ - public function rmdir($dir) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $dir = $this->realpath($dir); - if ($dir === false) { - return false; - } - - if (!$this->send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($dir), $dir))) { - return false; - } - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_OK) { - // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED? - $this->logError($response, $status); - return false; - } - - $this->remove_from_stat_cache($dir); - // the following will do a soft delete, which would be useful if you deleted a file - // and then tried to do a stat on the deleted file. the above, in contrast, does - // a hard delete - //$this->update_stat_cache($dir, false); - - return true; - } - - /** - * Uploads a file to the SFTP server. - * - * By default, \phpseclib\Net\SFTP::put() does not read from the local filesystem. $data is dumped directly into $remote_file. - * So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SFTP::get(), you will get a file, twelve bytes - * long, containing 'filename.ext' as its contents. - * - * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will - * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how - * large $remote_file will be, as well. - * - * Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number of bytes to return, and returns a string if there is some data or null if there is no more data - * - * If $data is a resource then it'll be used as a resource instead. - * - * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take - * care of that, yourself. - * - * $mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with - * $mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following: - * - * self::SOURCE_LOCAL_FILE | self::RESUME - * - * If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace - * self::RESUME with self::RESUME_START. - * - * If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed. - * - * $start and $local_start give you more fine grained control over this process and take precident over self::RESUME - * when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle - * of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the - * middle of one. - * - * Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE. - * - * @param string $remote_file - * @param string|resource $data - * @param int $mode - * @param int $start - * @param int $local_start - * @param callable|null $progressCallback - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \BadFunctionCallException if you're uploading via a callback and the callback function is invalid - * @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist - * @return bool - * @access public - * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode(). - */ - public function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $remote_file = $this->realpath($remote_file); - if ($remote_file === false) { - return false; - } - - $this->remove_from_stat_cache($remote_file); - - $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE; - // according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file." - // in practice, it doesn't seem to do that. - //$flags|= ($mode & self::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE; - - if ($start >= 0) { - $offset = $start; - } elseif ($mode & self::RESUME) { - // if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called - $size = $this->size($remote_file); - $offset = $size !== false ? $size : 0; - } else { - $offset = 0; - $flags|= NET_SFTP_OPEN_TRUNCATE; - } - - $packet = pack('Na*N2', strlen($remote_file), $remote_file, $flags, 0); - if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3 - $dataCallback = false; - switch (true) { - case $mode & self::SOURCE_CALLBACK: - if (!is_callable($data)) { - throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag"); - } - $dataCallback = $data; - // do nothing - break; - case is_resource($data): - $mode = $mode & ~self::SOURCE_LOCAL_FILE; - $fp = $data; - break; - case $mode & self::SOURCE_LOCAL_FILE: - if (!is_file($data)) { - throw new FileNotFoundException("$data is not a valid file"); - } - $fp = @fopen($data, 'rb'); - if (!$fp) { - return false; - } - } - - if (isset($fp)) { - $stat = fstat($fp); - $size = $stat['size']; - - if ($local_start >= 0) { - fseek($fp, $local_start); - $size-= $local_start; - } - } elseif ($dataCallback) { - $size = 0; - } else { - $size = strlen($data); - } - - $sent = 0; - $size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size; - - $sftp_packet_size = 4096; // PuTTY uses 4096 - // make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header" - $sftp_packet_size-= strlen($handle) + 25; - $i = 0; - while ($dataCallback || ($size === 0 || $sent < $size)) { - if ($dataCallback) { - $temp = call_user_func($dataCallback, $sftp_packet_size); - if (is_null($temp)) { - break; - } - } else { - $temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size); - if ($temp === false || $temp === '') { - break; - } - } - - $subtemp = $offset + $sent; - $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp); - if (!$this->send_sftp_packet(NET_SFTP_WRITE, $packet)) { - if ($mode & self::SOURCE_LOCAL_FILE) { - fclose($fp); - } - return false; - } - $sent+= strlen($temp); - if (is_callable($progressCallback)) { - call_user_func($progressCallback, $sent); - } - - $i++; - - if ($i == NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - $i = 0; - break; - } - $i = 0; - } - } - - if (!$this->read_put_responses($i)) { - if ($mode & self::SOURCE_LOCAL_FILE) { - fclose($fp); - } - $this->close_handle($handle); - return false; - } - - if ($mode & self::SOURCE_LOCAL_FILE) { - fclose($fp); - } - - return $this->close_handle($handle); - } - - /** - * Reads multiple successive SSH_FXP_WRITE responses - * - * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i - * SSH_FXP_WRITEs, in succession, and then reading $i responses. - * - * @param int $i - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @access private - */ - private function read_put_responses($i) - { - while ($i--) { - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - break; - } - } - - return $i < 0; - } - - /** - * Close handle - * - * @param string $handle - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @access private - */ - private function close_handle($handle) - { - if (!$this->send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle))) { - return false; - } - - // "The client MUST release all resources associated with the handle regardless of the status." - // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3 - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - return true; - } - - /** - * Downloads a file from the SFTP server. - * - * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if - * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the - * operation. - * - * $offset and $length can be used to download files in chunks. - * - * @param string $remote_file - * @param string $local_file - * @param int $offset - * @param int $length - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - * @access public - */ - public function get($remote_file, $local_file = false, $offset = 0, $length = -1) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $remote_file = $this->realpath($remote_file); - if ($remote_file === false) { - return false; - } - - $packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0); - if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); - } - - if (is_resource($local_file)) { - $fp = $local_file; - $stat = fstat($fp); - $res_offset = $stat['size']; - } else { - $res_offset = 0; - if ($local_file !== false) { - $fp = fopen($local_file, 'wb'); - if (!$fp) { - return false; - } - } else { - $content = ''; - } - } - - $fclose_check = $local_file !== false && !is_resource($local_file); - - $start = $offset; - $read = 0; - while (true) { - $i = 0; - - while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) { - $tempoffset = $start + $read; - - $packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet; - - $packet = pack('Na*N3', strlen($handle), $handle, $tempoffset / 4294967296, $tempoffset, $packet_size); - if (!$this->send_sftp_packet(NET_SFTP_READ, $packet)) { - if ($fclose_check) { - fclose($fp); - } - return false; - } - $packet = null; - $read+= $packet_size; - $i++; - } - - if (!$i) { - break; - } - - $clear_responses = false; - while ($i > 0) { - $i--; - - if ($clear_responses) { - $this->get_sftp_packet(); - continue; - } else { - $response = $this->get_sftp_packet(); - } - - switch ($this->packet_type) { - case NET_SFTP_DATA: - $temp = substr($response, 4); - $offset+= strlen($temp); - if ($local_file === false) { - $content.= $temp; - } else { - fputs($fp, $temp); - } - $temp = null; - break; - case NET_SFTP_STATUS: - // could, in theory, return false if !strlen($content) but we'll hold off for the time being - $this->logError($response); - $clear_responses = true; // don't break out of the loop yet, so we can read the remaining responses - break; - default: - if ($fclose_check) { - fclose($fp); - } - throw new \UnexpectedValueException('Expected SSH_FXP_DATA or SSH_FXP_STATUS'); - } - $response = null; - } - - if ($clear_responses) { - break; - } - } - - if ($length > 0 && $length <= $offset - $start) { - if ($local_file === false) { - $content = substr($content, 0, $length); - } else { - ftruncate($fp, $length + $res_offset); - } - } - - if ($fclose_check) { - fclose($fp); - } - - if (!$this->close_handle($handle)) { - return false; - } - - // if $content isn't set that means a file was written to - return isset($content) ? $content : true; - } - - /** - * Deletes a file on the SFTP server. - * - * @param string $path - * @param bool $recursive - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @access public - */ - public function delete($path, $recursive = true) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - if (is_object($path)) { - // It's an object. Cast it as string before we check anything else. - $path = (string) $path; - } - - if (!is_string($path) || $path == '') { - return false; - } - - $path = $this->realpath($path); - if ($path === false) { - return false; - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3 - if (!$this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path))) { - return false; - } - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - if (!$recursive) { - return false; - } - $i = 0; - $result = $this->delete_recursive($path, $i); - $this->read_put_responses($i); - return $result; - } - - $this->remove_from_stat_cache($path); - - return true; - } - - /** - * Recursively deletes directories on the SFTP server - * - * Minimizes directory lookups and SSH_FXP_STATUS requests for speed. - * - * @param string $path - * @param int $i - * @return bool - * @access private - */ - private function delete_recursive($path, &$i) - { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - $entries = $this->readlist($path, true); - - // normally $entries would have at least . and .. but it might not if the directories - // permissions didn't allow reading - if (empty($entries)) { - return false; - } - - unset($entries['.'], $entries['..']); - foreach ($entries as $filename => $props) { - if (!isset($props['type'])) { - return false; - } - - $temp = $path . '/' . $filename; - if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) { - if (!$this->delete_recursive($temp, $i)) { - return false; - } - } else { - if (!$this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) { - return false; - } - $this->remove_from_stat_cache($temp); - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - } - } - - if (!$this->send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) { - return false; - } - $this->remove_from_stat_cache($path); - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - - return true; - } - - /** - * Checks whether a file or directory exists - * - * @param string $path - * @return bool - * @access public - */ - public function file_exists($path) - { - if ($this->use_stat_cache) { - $path = $this->realpath($path); - - $result = $this->query_stat_cache($path); - - if (isset($result)) { - // return true if $result is an array or if it's an stdClass object - return $result !== false; - } - } - - return $this->stat($path) !== false; - } - - /** - * Tells whether the filename is a directory - * - * @param string $path - * @return bool - * @access public - */ - public function is_dir($path) - { - $result = $this->get_stat_cache_prop($path, 'type'); - if ($result === false) { - return false; - } - return $result === NET_SFTP_TYPE_DIRECTORY; - } - - /** - * Tells whether the filename is a regular file - * - * @param string $path - * @return bool - * @access public - */ - public function is_file($path) - { - $result = $this->get_stat_cache_prop($path, 'type'); - if ($result === false) { - return false; - } - return $result === NET_SFTP_TYPE_REGULAR; - } - - /** - * Tells whether the filename is a symbolic link - * - * @param string $path - * @return bool - * @access public - */ - public function is_link($path) - { - $result = $this->get_lstat_cache_prop($path, 'type'); - if ($result === false) { - return false; - } - return $result === NET_SFTP_TYPE_SYMLINK; - } - - /** - * Tells whether a file exists and is readable - * - * @param string $path - * @return bool - * @access public - */ - public function is_readable($path) - { - $path = $this->realpath($path); - - $packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_READ, 0); - if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - return true; - case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - return false; - default: - user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); - return false; - } - } - - /** - * Tells whether the filename is writable - * - * @param string $path - * @return bool - * @access public - */ - public function is_writable($path) - { - $path = $this->realpath($path); - - $packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_WRITE, 0); - if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - return true; - case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - return false; - default: - user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); - return false; - } - } - - /** - * Tells whether the filename is writeable - * - * Alias of is_writable - * - * @param string $path - * @return bool - * @access public - */ - public function is_writeable($path) - { - return $this->is_writable($path); - } - - /** - * Gets last access time of file - * - * @param string $path - * @return mixed - * @access public - */ - public function fileatime($path) - { - return $this->get_stat_cache_prop($path, 'atime'); - } - - /** - * Gets file modification time - * - * @param string $path - * @return mixed - * @access public - */ - public function filemtime($path) - { - return $this->get_stat_cache_prop($path, 'mtime'); - } - - /** - * Gets file permissions - * - * @param string $path - * @return mixed - * @access public - */ - public function fileperms($path) - { - return $this->get_stat_cache_prop($path, 'permissions'); - } - - /** - * Gets file owner - * - * @param string $path - * @return mixed - * @access public - */ - public function fileowner($path) - { - return $this->get_stat_cache_prop($path, 'uid'); - } - - /** - * Gets file group - * - * @param string $path - * @return mixed - * @access public - */ - public function filegroup($path) - { - return $this->get_stat_cache_prop($path, 'gid'); - } - - /** - * Gets file size - * - * @param string $path - * @return mixed - * @access public - */ - public function filesize($path) - { - return $this->get_stat_cache_prop($path, 'size'); - } - - /** - * Gets file type - * - * @param string $path - * @return mixed - * @access public - */ - public function filetype($path) - { - $type = $this->get_stat_cache_prop($path, 'type'); - if ($type === false) { - return false; - } - - switch ($type) { - case NET_SFTP_TYPE_BLOCK_DEVICE: - return 'block'; - case NET_SFTP_TYPE_CHAR_DEVICE: - return 'char'; - case NET_SFTP_TYPE_DIRECTORY: - return 'dir'; - case NET_SFTP_TYPE_FIFO: - return 'fifo'; - case NET_SFTP_TYPE_REGULAR: - return 'file'; - case NET_SFTP_TYPE_SYMLINK: - return 'link'; - default: - return false; - } - } - - /** - * Return a stat properity - * - * Uses cache if appropriate. - * - * @param string $path - * @param string $prop - * @return mixed - * @access private - */ - private function get_stat_cache_prop($path, $prop) - { - return $this->get_xstat_cache_prop($path, $prop, 'stat'); - } - - /** - * Return an lstat properity - * - * Uses cache if appropriate. - * - * @param string $path - * @param string $prop - * @return mixed - * @access private - */ - private function get_lstat_cache_prop($path, $prop) - { - return $this->get_xstat_cache_prop($path, $prop, 'lstat'); - } - - /** - * Return a stat or lstat properity - * - * Uses cache if appropriate. - * - * @param string $path - * @param string $prop - * @return mixed - * @access private - */ - private function get_xstat_cache_prop($path, $prop, $type) - { - if ($this->use_stat_cache) { - $path = $this->realpath($path); - - $result = $this->query_stat_cache($path); - - if (is_object($result) && isset($result->$type)) { - return $result->{$type}[$prop]; - } - } - - $result = $this->$type($path); - - if ($result === false || !isset($result[$prop])) { - return false; - } - - return $result[$prop]; - } - - /** - * Renames a file or a directory on the SFTP server - * - * @param string $oldname - * @param string $newname - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @access public - */ - public function rename($oldname, $newname) - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - $oldname = $this->realpath($oldname); - $newname = $this->realpath($newname); - if ($oldname === false || $newname === false) { - return false; - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3 - $packet = pack('Na*Na*', strlen($oldname), $oldname, strlen($newname), $newname); - if (!$this->send_sftp_packet(NET_SFTP_RENAME, $packet)) { - return false; - } - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); - } - - // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nstatus', Strings::shift($response, 4))); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - // don't move the stat cache entry over since this operation could very well change the - // atime and mtime attributes - //$this->update_stat_cache($newname, $this->query_stat_cache($oldname)); - $this->remove_from_stat_cache($oldname); - $this->remove_from_stat_cache($newname); - - return true; - } - - /** - * Parse Attributes - * - * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info. - * - * @param string $response - * @return array - * @access private - */ - private function parseAttributes(&$response) - { - $attr = []; - if (strlen($response) < 4) { - //user_error('Malformed file attributes'); - return []; - } - extract(unpack('Nflags', Strings::shift($response, 4))); - // SFTPv4+ have a type field (a byte) that follows the above flag field - foreach ($this->attributes as $key => $value) { - switch ($flags & $key) { - case NET_SFTP_ATTR_SIZE: // 0x00000001 - // The size attribute is defined as an unsigned 64-bit integer. - // The following will use floats on 32-bit platforms, if necessary. - // As can be seen in the BigInteger class, floats are generally - // IEEE 754 binary64 "double precision" on such platforms and - // as such can represent integers of at least 2^50 without loss - // of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB. - $attr['size'] = hexdec(Hex::encode(Strings::shift($response, 8))); - break; - case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only) - if (strlen($response) < 8) { - //user_error('Malformed file attributes'); - return $attr; - } - $attr+= unpack('Nuid/Ngid', Strings::shift($response, 8)); - break; - case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004 - if (strlen($response) < 4) { - //user_error('Malformed file attributes'); - return $attr; - } - $attr+= unpack('Npermissions', Strings::shift($response, 4)); - // mode == permissions; permissions was the original array key and is retained for bc purposes. - // mode was added because that's the more industry standard terminology - $attr+= ['mode' => $attr['permissions']]; - $fileType = $this->parseMode($attr['permissions']); - if ($fileType !== false) { - $attr+= ['type' => $fileType]; - } - break; - case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008 - if (strlen($response) < 8) { - //user_error('Malformed file attributes'); - return $attr; - } - $attr+= unpack('Natime/Nmtime', Strings::shift($response, 8)); - break; - case NET_SFTP_ATTR_EXTENDED: // 0x80000000 - if (strlen($response) < 4) { - //user_error('Malformed file attributes'); - return $attr; - } - extract(unpack('Ncount', Strings::shift($response, 4))); - for ($i = 0; $i < $count; $i++) { - if (strlen($response) < 4) { - //user_error('Malformed file attributes'); - return $attr; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $key = Strings::shift($response, $length); - if (strlen($response) < 4) { - //user_error('Malformed file attributes'); - return $attr; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $attr[$key] = Strings::shift($response, $length); - } - } - } - return $attr; - } - - /** - * Attempt to identify the file type - * - * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway - * - * @param int $mode - * @return int - * @access private - */ - private function parseMode($mode) - { - // values come from http://lxr.free-electrons.com/source/include/uapi/linux/stat.h#L12 - // see, also, http://linux.die.net/man/2/stat - switch ($mode & 0170000) {// ie. 1111 0000 0000 0000 - case 0000000: // no file type specified - figure out the file type using alternative means - return false; - case 0040000: - return NET_SFTP_TYPE_DIRECTORY; - case 0100000: - return NET_SFTP_TYPE_REGULAR; - case 0120000: - return NET_SFTP_TYPE_SYMLINK; - // new types introduced in SFTPv5+ - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2 - case 0010000: // named pipe (fifo) - return NET_SFTP_TYPE_FIFO; - case 0020000: // character special - return NET_SFTP_TYPE_CHAR_DEVICE; - case 0060000: // block special - return NET_SFTP_TYPE_BLOCK_DEVICE; - case 0140000: // socket - return NET_SFTP_TYPE_SOCKET; - case 0160000: // whiteout - // "SPECIAL should be used for files that are of - // a known type which cannot be expressed in the protocol" - return NET_SFTP_TYPE_SPECIAL; - default: - return NET_SFTP_TYPE_UNKNOWN; - } - } - - /** - * Parse Longname - * - * SFTPv3 doesn't provide any easy way of identifying a file type. You could try to open - * a file as a directory and see if an error is returned or you could try to parse the - * SFTPv3-specific longname field of the SSH_FXP_NAME packet. That's what this function does. - * The result is returned using the - * {@link http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 SFTPv4 type constants}. - * - * If the longname is in an unrecognized format bool(false) is returned. - * - * @param string $longname - * @return mixed - * @access private - */ - private function parseLongname($longname) - { - // http://en.wikipedia.org/wiki/Unix_file_types - // http://en.wikipedia.org/wiki/Filesystem_permissions#Notation_of_traditional_Unix_permissions - if (preg_match('#^[^/]([r-][w-][xstST-]){3}#', $longname)) { - switch ($longname[0]) { - case '-': - return NET_SFTP_TYPE_REGULAR; - case 'd': - return NET_SFTP_TYPE_DIRECTORY; - case 'l': - return NET_SFTP_TYPE_SYMLINK; - default: - return NET_SFTP_TYPE_SPECIAL; - } - } - - return false; - } - - /** - * Sends SFTP Packets - * - * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info. - * - * @param int $type - * @param string $data - * @see self::_get_sftp_packet() - * @see self::_send_channel_packet() - * @return bool - * @access private - */ - private function send_sftp_packet($type, $data) - { - $packet = $this->request_id !== false ? - pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) : - pack('NCa*', strlen($data) + 1, $type, $data); - - $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 - $result = $this->send_channel_packet(self::CHANNEL, $packet); - $stop = strtok(microtime(), ' ') + strtok(''); - - if (defined('NET_SFTP_LOGGING')) { - $packet_type = '-> ' . $this->packet_types[$type] . - ' (' . round($stop - $start, 4) . 's)'; - if (NET_SFTP_LOGGING == self::LOG_REALTIME) { - echo "
\r\n" . $this->format_log([$data], [$packet_type]) . "\r\n
\r\n"; - flush(); - ob_flush(); - } else { - $this->packet_type_log[] = $packet_type; - if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { - $this->packet_log[] = $data; - } - } - } - - return $result; - } - - /** - * Receives SFTP Packets - * - * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info. - * - * Incidentally, the number of SSH_MSG_CHANNEL_DATA messages has no bearing on the number of SFTP packets present. - * There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA - * messages containing one SFTP packet. - * - * @see self::_send_sftp_packet() - * @return string - * @access private - */ - private function get_sftp_packet() - { - $this->curTimeout = false; - - $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 - - // SFTP packet length - while (strlen($this->packet_buffer) < 4) { - $temp = $this->get_channel_packet(self::CHANNEL); - if (is_bool($temp)) { - $this->packet_type = false; - $this->packet_buffer = ''; - return false; - } - $this->packet_buffer.= $temp; - } - if (strlen($this->packet_buffer) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4))); - $tempLength = $length; - $tempLength-= strlen($this->packet_buffer); - - // SFTP packet type and data payload - while ($tempLength > 0) { - $temp = $this->get_channel_packet(self::CHANNEL); - if (is_bool($temp)) { - $this->packet_type = false; - $this->packet_buffer = ''; - return false; - } - $this->packet_buffer.= $temp; - $tempLength-= strlen($temp); - } - - $stop = strtok(microtime(), ' ') + strtok(''); - - $this->packet_type = ord(Strings::shift($this->packet_buffer)); - - if ($this->request_id !== false) { - Strings::shift($this->packet_buffer, 4); // remove the request id - $length-= 5; // account for the request id and the packet type - } else { - $length-= 1; // account for the packet type - } - - $packet = Strings::shift($this->packet_buffer, $length); - - if (defined('NET_SFTP_LOGGING')) { - $packet_type = '<- ' . $this->packet_types[$this->packet_type] . - ' (' . round($stop - $start, 4) . 's)'; - if (NET_SFTP_LOGGING == self::LOG_REALTIME) { - echo "
\r\n" . $this->format_log([$packet], [$packet_type]) . "\r\n
\r\n"; - flush(); - ob_flush(); - } else { - $this->packet_type_log[] = $packet_type; - if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { - $this->packet_log[] = $packet; - } - } - } - - return $packet; - } - - /** - * Returns a log of the packets that have been sent and received. - * - * Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING') - * - * @access public - * @return string or Array - */ - public function getSFTPLog() - { - if (!defined('NET_SFTP_LOGGING')) { - return false; - } - - switch (NET_SFTP_LOGGING) { - case self::LOG_COMPLEX: - return $this->format_log($this->packet_log, $this->packet_type_log); - break; - //case self::LOG_SIMPLE: - default: - return $this->packet_type_log; - } - } - - /** - * Returns all errors - * - * @return string - * @access public - */ - public function getSFTPErrors() - { - return $this->sftp_errors; - } - - /** - * Returns the last error - * - * @return string - * @access public - */ - public function getLastSFTPError() - { - return count($this->sftp_errors) ? $this->sftp_errors[count($this->sftp_errors) - 1] : ''; - } - - /** - * Get supported SFTP versions - * - * @return array - * @access public - */ - public function getSupportedVersions() - { - $temp = ['version' => $this->version]; - if (isset($this->extensions['versions'])) { - $temp['extensions'] = $this->extensions['versions']; - } - return $temp; - } - - /** - * Disconnect - * - * @param int $reason - * @return bool - * @access private - */ - private function disconnect_helper($reason) - { - $this->pwd = false; - parent::disconnect_helper($reason); - } -} diff --git a/lib/phpaes/phpseclib/Net/SFTP/Stream.php b/lib/phpaes/phpseclib/Net/SFTP/Stream.php deleted file mode 100644 index a0c3bd3a39..0000000000 --- a/lib/phpaes/phpseclib/Net/SFTP/Stream.php +++ /dev/null @@ -1,795 +0,0 @@ - - * @copyright 2013 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Net\SFTP; - -use phpseclib\Crypt\RSA; -use phpseclib\Net\SFTP; -use phpseclib\Net\SSH2; - -/** - * SFTP Stream Wrapper - * - * @package SFTP - * @author Jim Wigginton - * @access public - */ -class Stream -{ - /** - * SFTP instances - * - * Rather than re-create the connection we re-use instances if possible - * - * @var array - */ - static $instances; - - /** - * SFTP instance - * - * @var object - * @access private - */ - private $sftp; - - /** - * Path - * - * @var string - * @access private - */ - private $path; - - /** - * Mode - * - * @var string - * @access private - */ - private $mode; - - /** - * Position - * - * @var int - * @access private - */ - private $pos; - - /** - * Size - * - * @var int - * @access private - */ - private $size; - - /** - * Directory entries - * - * @var array - * @access private - */ - private $entries; - - /** - * EOF flag - * - * @var bool - * @access private - */ - private $eof; - - /** - * Context resource - * - * Technically this needs to be publically accessible so PHP can set it directly - * - * @var resource - * @access public - */ - public $context; - - /** - * Notification callback function - * - * @var callable - * @access public - */ - private $notification; - - /** - * Registers this class as a URL wrapper. - * - * @param string $protocol The wrapper name to be registered. - * @return bool True on success, false otherwise. - * @access public - */ - public static function register($protocol = 'sftp') - { - if (in_array($protocol, stream_get_wrappers(), true)) { - return false; - } - return stream_wrapper_register($protocol, get_called_class()); - } - - /** - * The Constructor - * - * @access public - */ - public function __construct() - { - if (defined('NET_SFTP_STREAM_LOGGING')) { - echo "__construct()\r\n"; - } - } - - /** - * Path Parser - * - * Extract a path from a URI and actually connect to an SSH server if appropriate - * - * If "notification" is set as a context parameter the message code for successful login is - * NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE. - * - * @param string $path - * @return string - * @access private - */ - private function parse_path($path) - { - $orig = $path; - extract(parse_url($path) + ['port' => 22]); - if (isset($query)) { - $path.= '?' . $query; - } elseif (preg_match('/(\?|\?#)$/', $orig)) { - $path.= '?'; - } - if (isset($fragment)) { - $path.= '#' . $fragment; - } elseif ($orig[strlen($orig) - 1] == '#') { - $path.= '#'; - } - - if (!isset($host)) { - return false; - } - - if (isset($this->context)) { - $context = stream_context_get_params($this->context); - if (isset($context['notification'])) { - $this->notification = $context['notification']; - } - } - - if (preg_match('/^{[a-z0-9]+}$/i', $host)) { - $host = SSH2::getConnectionByResourceId($host); - if ($host === false) { - return false; - } - $this->sftp = $host; - } else { - if (isset($this->context)) { - $context = stream_context_get_options($this->context); - } - if (isset($context[$scheme]['session'])) { - $sftp = $context[$scheme]['session']; - } - if (isset($context[$scheme]['sftp'])) { - $sftp = $context[$scheme]['sftp']; - } - if (isset($sftp) && $sftp instanceof SFTP) { - $this->sftp = $sftp; - return $path; - } - if (isset($context[$scheme]['username'])) { - $user = $context[$scheme]['username']; - } - if (isset($context[$scheme]['password'])) { - $pass = $context[$scheme]['password']; - } - if (isset($context[$scheme]['privkey']) && $context[$scheme]['privkey'] instanceof RSA) { - $pass = $context[$scheme]['privkey']; - } - - if (!isset($user) || !isset($pass)) { - return false; - } - - // casting $pass to a string is necessary in the event that it's a \phpseclib\Crypt\RSA object - if (isset(self::$instances[$host][$port][$user][(string) $pass])) { - $this->sftp = self::$instances[$host][$port][$user][(string) $pass]; - } else { - $this->sftp = new SFTP($host, $port); - $this->sftp->disableStatCache(); - if (isset($this->notification) && is_callable($this->notification)) { - /* if !is_callable($this->notification) we could do this: - - user_error('fopen(): failed to call user notifier', E_USER_WARNING); - - the ftp wrapper gives errors like that when the notifier isn't callable. - i've opted not to do that, however, since the ftp wrapper gives the line - on which the fopen occurred as the line number - not the line that the - user_error is on. - */ - call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0); - call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0); - if (!$this->sftp->login($user, $pass)) { - call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0); - return false; - } - call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0); - } else { - if (!$this->sftp->login($user, $pass)) { - return false; - } - } - self::$instances[$host][$port][$user][(string) $pass] = $this->sftp; - } - } - - return $path; - } - - /** - * Opens file or URL - * - * @param string $path - * @param string $mode - * @param int $options - * @param string $opened_path - * @return bool - * @access public - */ - private function _stream_open($path, $mode, $options, &$opened_path) - { - $path = $this->parse_path($path); - - if ($path === false) { - return false; - } - $this->path = $path; - - $this->size = $this->sftp->size($path); - $this->mode = preg_replace('#[bt]$#', '', $mode); - $this->eof = false; - - if ($this->size === false) { - if ($this->mode[0] == 'r') { - return false; - } else { - $this->sftp->touch($path); - $this->size = 0; - } - } else { - switch ($this->mode[0]) { - case 'x': - return false; - case 'w': - $this->sftp->truncate($path, 0); - $this->size = 0; - } - } - - $this->pos = $this->mode[0] != 'a' ? 0 : $this->size; - - return true; - } - - /** - * Read from stream - * - * @param int $count - * @return mixed - * @access public - */ - private function _stream_read($count) - { - switch ($this->mode) { - case 'w': - case 'a': - case 'x': - case 'c': - return false; - } - - // commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite - //if ($this->pos >= $this->size) { - // $this->eof = true; - // return false; - //} - - $result = $this->sftp->get($this->path, false, $this->pos, $count); - if (isset($this->notification) && is_callable($this->notification)) { - if ($result === false) { - call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0); - return 0; - } - // seems that PHP calls stream_read in 8k chunks - call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size); - } - - if (empty($result)) { // ie. false or empty string - $this->eof = true; - return false; - } - $this->pos+= strlen($result); - - return $result; - } - - /** - * Write to stream - * - * @param string $data - * @return mixed - * @access public - */ - private function _stream_write($data) - { - switch ($this->mode) { - case 'r': - return false; - } - - $result = $this->sftp->put($this->path, $data, SFTP::SOURCE_STRING, $this->pos); - if (isset($this->notification) && is_callable($this->notification)) { - if (!$result) { - call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0); - return 0; - } - // seems that PHP splits up strings into 8k blocks before calling stream_write - call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data)); - } - - if ($result === false) { - return false; - } - $this->pos+= strlen($data); - if ($this->pos > $this->size) { - $this->size = $this->pos; - } - $this->eof = false; - return strlen($data); - } - - /** - * Retrieve the current position of a stream - * - * @return int - * @access public - */ - private function _stream_tell() - { - return $this->pos; - } - - /** - * Tests for end-of-file on a file pointer - * - * In my testing there are four classes functions that normally effect the pointer: - * fseek, fputs / fwrite, fgets / fread and ftruncate. - * - * Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof() - * will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof() - * will return false. do fread($fp, 1) and feof() will then return true. - * - * @return bool - * @access public - */ - private function _stream_eof() - { - return $this->eof; - } - - /** - * Seeks to specific location in a stream - * - * @param int $offset - * @param int $whence - * @return bool - * @access public - */ - private function _stream_seek($offset, $whence) - { - switch ($whence) { - case SEEK_SET: - if ($offset >= $this->size || $offset < 0) { - return false; - } - break; - case SEEK_CUR: - $offset+= $this->pos; - break; - case SEEK_END: - $offset+= $this->size; - } - - $this->pos = $offset; - $this->eof = false; - return true; - } - - /** - * Change stream options - * - * @param string $path - * @param int $option - * @param mixed $var - * @return bool - * @access public - */ - private function _stream_metadata($path, $option, $var) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - // stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined - // see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246 - // and https://github.com/php/php-src/blob/master/main/php_streams.h#L592 - switch ($option) { - case 1: // PHP_STREAM_META_TOUCH - return $this->sftp->touch($path, $var[0], $var[1]); - case 2: // PHP_STREAM_OWNER_NAME - case 3: // PHP_STREAM_GROUP_NAME - return false; - case 4: // PHP_STREAM_META_OWNER - return $this->sftp->chown($path, $var); - case 5: // PHP_STREAM_META_GROUP - return $this->sftp->chgrp($path, $var); - case 6: // PHP_STREAM_META_ACCESS - return $this->sftp->chmod($path, $var) !== false; - } - } - - /** - * Retrieve the underlaying resource - * - * @param int $cast_as - * @return resource - * @access public - */ - private function _stream_cast($cast_as) - { - return $this->sftp->fsock; - } - - /** - * Advisory file locking - * - * @param int $operation - * @return bool - * @access public - */ - private function _stream_lock($operation) - { - return false; - } - - /** - * Renames a file or directory - * - * Attempts to rename oldname to newname, moving it between directories if necessary. - * If newname exists, it will be overwritten. This is a departure from what \phpseclib\Net\SFTP - * does. - * - * @param string $path_from - * @param string $path_to - * @return bool - * @access public - */ - private function _rename($path_from, $path_to) - { - $path1 = parse_url($path_from); - $path2 = parse_url($path_to); - unset($path1['path'], $path2['path']); - if ($path1 != $path2) { - return false; - } - - $path_from = $this->parse_path($path_from); - $path_to = parse_url($path_to); - if ($path_from === false) { - return false; - } - - $path_to = $path_to['path']; // the $component part of parse_url() was added in PHP 5.1.2 - // "It is an error if there already exists a file with the name specified by newpath." - // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5 - if (!$this->sftp->rename($path_from, $path_to)) { - if ($this->sftp->stat($path_to)) { - return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to); - } - return false; - } - - return true; - } - - /** - * Open directory handle - * - * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and - * removed in 5.4 I'm just going to ignore it. - * - * Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client - * sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting - * the SFTP specs: - * - * The SSH_FXP_NAME response has the following format: - * - * uint32 id - * uint32 count - * repeats count times: - * string filename - * string longname - * ATTRS attrs - * - * @param string $path - * @param int $options - * @return bool - * @access public - */ - private function _dir_opendir($path, $options) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - $this->pos = 0; - $this->entries = $this->sftp->nlist($path); - return $this->entries !== false; - } - - /** - * Read entry from directory handle - * - * @return mixed - * @access public - */ - private function _dir_readdir() - { - if (isset($this->entries[$this->pos])) { - return $this->entries[$this->pos++]; - } - return false; - } - - /** - * Rewind directory handle - * - * @return bool - * @access public - */ - private function _dir_rewinddir() - { - $this->pos = 0; - return true; - } - - /** - * Close directory handle - * - * @return bool - * @access public - */ - private function _dir_closedir() - { - return true; - } - - /** - * Create a directory - * - * Only valid $options is STREAM_MKDIR_RECURSIVE - * - * @param string $path - * @param int $mode - * @param int $options - * @return bool - * @access public - */ - private function _mkdir($path, $mode, $options) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE); - } - - /** - * Removes a directory - * - * Only valid $options is STREAM_MKDIR_RECURSIVE per , however, - * does not have a $recursive parameter as mkdir() does so I don't know how - * STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as - * $options. What does 8 correspond to? - * - * @param string $path - * @param int $mode - * @param int $options - * @return bool - * @access public - */ - private function _rmdir($path, $options) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - return $this->sftp->rmdir($path); - } - - /** - * Flushes the output - * - * See . Always returns true because \phpseclib\Net\SFTP doesn't cache stuff before writing - * - * @return bool - * @access public - */ - private function _stream_flush() - { - return true; - } - - /** - * Retrieve information about a file resource - * - * @return mixed - * @access public - */ - private function _stream_stat() - { - $results = $this->sftp->stat($this->path); - if ($results === false) { - return false; - } - return $results; - } - - /** - * Delete a file - * - * @param string $path - * @return bool - * @access public - */ - private function _unlink($path) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - return $this->sftp->delete($path, false); - } - - /** - * Retrieve information about a file - * - * Ignores the STREAM_URL_STAT_QUIET flag because the entirety of \phpseclib\Net\SFTP\Stream is quiet by default - * might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll - * cross that bridge when and if it's reached - * - * @param string $path - * @param int $flags - * @return mixed - * @access public - */ - private function _url_stat($path, $flags) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - $results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path); - if ($results === false) { - return false; - } - - return $results; - } - - /** - * Truncate stream - * - * @param int $new_size - * @return bool - * @access public - */ - private function _stream_truncate($new_size) - { - if (!$this->sftp->truncate($this->path, $new_size)) { - return false; - } - - $this->eof = false; - $this->size = $new_size; - - return true; - } - - /** - * Change stream options - * - * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't. - * The other two aren't supported because of limitations in \phpseclib\Net\SFTP. - * - * @param int $option - * @param int $arg1 - * @param int $arg2 - * @return bool - * @access public - */ - private function _stream_set_option($option, $arg1, $arg2) - { - return false; - } - - /** - * Close an resource - * - * @access public - */ - private function _stream_close() - { - } - - /** - * __call Magic Method - * - * When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you. - * Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function - * lets you figure that out. - * - * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not - * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method. - * - * @param string - * @param array - * @return mixed - * @access public - */ - public function __call($name, $arguments) - { - if (defined('NET_SFTP_STREAM_LOGGING')) { - echo $name . '('; - $last = count($arguments) - 1; - foreach ($arguments as $i => $argument) { - var_export($argument); - if ($i != $last) { - echo ','; - } - } - echo ")\r\n"; - } - $name = '_' . $name; - if (!method_exists($this, $name)) { - return false; - } - return call_user_func_array([$this, $name], $arguments); - } -} diff --git a/lib/phpaes/phpseclib/Net/SSH1.php b/lib/phpaes/phpseclib/Net/SSH1.php deleted file mode 100644 index edb4b5f341..0000000000 --- a/lib/phpaes/phpseclib/Net/SSH1.php +++ /dev/null @@ -1,1619 +0,0 @@ - - * login('username', 'password')) { - * exit('Login Failed'); - * } - * - * echo $ssh->exec('ls -la'); - * ?> - * - * - * Here's another short example: - * - * login('username', 'password')) { - * exit('Login Failed'); - * } - * - * echo $ssh->read('username@username:~$'); - * $ssh->write("ls -la\n"); - * echo $ssh->read('username@username:~$'); - * ?> - * - * - * More information on the SSHv1 specification can be found by reading - * {@link http://www.snailbook.com/docs/protocol-1.5.txt protocol-1.5.txt}. - * - * @category Net - * @package SSH1 - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Net; - -use ParagonIE\ConstantTime\Hex; -use phpseclib\Crypt\DES; -use phpseclib\Crypt\Random; -use phpseclib\Crypt\TripleDES; -use phpseclib\Math\BigInteger; -use phpseclib\Common\Functions\Strings; - -/** - * Pure-PHP implementation of SSHv1. - * - * @package SSH1 - * @author Jim Wigginton - * @access public - */ -class SSH1 -{ - /**#@+ - * Encryption Methods - * - * @see \phpseclib\Net\SSH1::getSupportedCiphers() - * @access public - */ - /** - * No encryption - * - * Not supported. - */ - const CIPHER_NONE = 0; - /** - * IDEA in CFB mode - * - * Not supported. - */ - const CIPHER_IDEA = 1; - /** - * DES in CBC mode - */ - const CIPHER_DES = 2; - /** - * Triple-DES in CBC mode - * - * All implementations are required to support this - */ - const CIPHER_3DES = 3; - /** - * TRI's Simple Stream encryption CBC - * - * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h), - * although it doesn't use it (see cipher.c) - */ - const CIPHER_BROKEN_TSS = 4; - /** - * RC4 - * - * Not supported. - * - * @internal According to the SSH1 specs: - * - * "The first 16 bytes of the session key are used as the key for - * the server to client direction. The remaining 16 bytes are used - * as the key for the client to server direction. This gives - * independent 128-bit keys for each direction." - * - * This library currently only supports encryption when the same key is being used for both directions. This is - * because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps). - */ - const CIPHER_RC4 = 5; - /** - * Blowfish - * - * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and - * uses it (see cipher.c) - */ - const CIPHER_BLOWFISH = 6; - /**#@-*/ - - /**#@+ - * Authentication Methods - * - * @see \phpseclib\Net\SSH1::getSupportedAuthentications() - * @access public - */ - /** - * .rhosts or /etc/hosts.equiv - */ - const AUTH_RHOSTS = 1; - /** - * pure RSA authentication - */ - const AUTH_RSA = 2; - /** - * password authentication - * - * This is the only method that is supported by this library. - */ - const AUTH_PASSWORD = 3; - /** - * .rhosts with RSA host authentication - */ - const AUTH_RHOSTS_RSA = 4; - /**#@-*/ - - /**#@+ - * Terminal Modes - * - * @link http://3sp.com/content/developer/maverick-net/docs/Maverick.SSH.PseudoTerminalModesMembers.html - * @access private - */ - const TTY_OP_END = 0; - /**#@-*/ - - /** - * The Response Type - * - * @see \phpseclib\Net\SSH1::_get_binary_packet() - * @access private - */ - const RESPONSE_TYPE = 1; - - /** - * The Response Data - * - * @see \phpseclib\Net\SSH1::_get_binary_packet() - * @access private - */ - const RESPONSE_DATA = 2; - - /**#@+ - * Execution Bitmap Masks - * - * @see \phpseclib\Net\SSH1::bitmap - * @access private - */ - const MASK_CONSTRUCTOR = 0x00000001; - const MASK_CONNECTED = 0x00000002; - const MASK_LOGIN = 0x00000004; - const MASK_SHELL = 0x00000008; - /**#@-*/ - - /**#@+ - * @access public - * @see \phpseclib\Net\SSH1::getLog() - */ - /** - * Returns the message numbers - */ - const LOG_SIMPLE = 1; - /** - * Returns the message content - */ - const LOG_COMPLEX = 2; - /** - * Outputs the content real-time - */ - const LOG_REALTIME = 3; - /** - * Dumps the content real-time to a file - */ - const LOG_REALTIME_FILE = 4; - /**#@-*/ - - /**#@+ - * @access public - * @see \phpseclib\Net\SSH1::read() - */ - /** - * Returns when a string matching $expect exactly is found - */ - const READ_SIMPLE = 1; - /** - * Returns when a string matching the regular expression $expect is found - */ - const READ_REGEX = 2; - /**#@-*/ - - /** - * The SSH identifier - * - * @var string - * @access private - */ - private $identifier = 'SSH-1.5-phpseclib'; - - /** - * The Socket Object - * - * @var object - * @access private - */ - private $fsock; - - /** - * The cryptography object - * - * @var object - * @access private - */ - private $crypto = false; - - /** - * Execution Bitmap - * - * The bits that are set represent functions that have been called already. This is used to determine - * if a requisite function has been successfully executed. If not, an error should be thrown. - * - * @var int - * @access private - */ - private $bitmap = 0; - - /** - * The Server Key Public Exponent - * - * Logged for debug purposes - * - * @see self::getServerKeyPublicExponent() - * @var string - * @access private - */ - private $server_key_public_exponent; - - /** - * The Server Key Public Modulus - * - * Logged for debug purposes - * - * @see self::getServerKeyPublicModulus() - * @var string - * @access private - */ - private $server_key_public_modulus; - - /** - * The Host Key Public Exponent - * - * Logged for debug purposes - * - * @see self::getHostKeyPublicExponent() - * @var string - * @access private - */ - private $host_key_public_exponent; - - /** - * The Host Key Public Modulus - * - * Logged for debug purposes - * - * @see self::getHostKeyPublicModulus() - * @var string - * @access private - */ - private $host_key_public_modulus; - - /** - * Supported Ciphers - * - * Logged for debug purposes - * - * @see self::getSupportedCiphers() - * @var array - * @access private - */ - private $supported_ciphers = [ - self::CIPHER_NONE => 'No encryption', - self::CIPHER_IDEA => 'IDEA in CFB mode', - self::CIPHER_DES => 'DES in CBC mode', - self::CIPHER_3DES => 'Triple-DES in CBC mode', - self::CIPHER_BROKEN_TSS => 'TRI\'s Simple Stream encryption CBC', - self::CIPHER_RC4 => 'RC4', - self::CIPHER_BLOWFISH => 'Blowfish' - ]; - - /** - * Supported Authentications - * - * Logged for debug purposes - * - * @see self::getSupportedAuthentications() - * @var array - * @access private - */ - private $supported_authentications = [ - self::AUTH_RHOSTS => '.rhosts or /etc/hosts.equiv', - self::AUTH_RSA => 'pure RSA authentication', - self::AUTH_PASSWORD => 'password authentication', - self::AUTH_RHOSTS_RSA => '.rhosts with RSA host authentication' - ]; - - /** - * Server Identification - * - * @see self::getServerIdentification() - * @var string - * @access private - */ - private $server_identification = ''; - - /** - * Protocol Flags - * - * @see self::__construct() - * @var array - * @access private - */ - private $protocol_flags = []; - - /** - * Protocol Flag Log - * - * @see self::getLog() - * @var array - * @access private - */ - private $protocol_flag_log = []; - - /** - * Message Log - * - * @see self::getLog() - * @var array - * @access private - */ - private $message_log = []; - - /** - * Real-time log file pointer - * - * @see self::_append_log() - * @var resource - * @access private - */ - private $realtime_log_file; - - /** - * Real-time log file size - * - * @see self::_append_log() - * @var int - * @access private - */ - private $realtime_log_size; - - /** - * Real-time log file wrap boolean - * - * @see self::_append_log() - * @var bool - * @access private - */ - private $realtime_log_wrap; - - /** - * Interactive Buffer - * - * @see self::read() - * @var array - * @access private - */ - private $interactiveBuffer = ''; - - /** - * Timeout - * - * @see self::setTimeout() - * @access private - */ - private $timeout; - - /** - * Current Timeout - * - * @see self::_get_channel_packet() - * @access private - */ - private $curTimeout; - - /** - * Log Boundary - * - * @see self::_format_log() - * @access private - */ - private $log_boundary = ':'; - - /** - * Log Long Width - * - * @see self::_format_log() - * @access private - */ - private $log_long_width = 65; - - /** - * Log Short Width - * - * @see self::_format_log() - * @access private - */ - private $log_short_width = 16; - - /** - * Hostname - * - * @see self::__construct() - * @see self::_connect() - * @var string - * @access private - */ - private $host; - - /** - * Port Number - * - * @see self::__construct() - * @see self::_connect() - * @var int - * @access private - */ - private $port; - - /** - * Timeout for initial connection - * - * Set by the constructor call. Calling setTimeout() is optional. If it's not called functions like - * exec() won't timeout unless some PHP setting forces it too. The timeout specified in the constructor, - * however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be - * 10 seconds. It is used by fsockopen() in that function. - * - * @see self::__construct() - * @see self::_connect() - * @var int - * @access private - */ - private $connectionTimeout; - - /** - * Default cipher - * - * @see self::__construct() - * @see self::_connect() - * @var int - * @access private - */ - private $cipher; - - /** - * Default Constructor. - * - * Connects to an SSHv1 server - * - * @param string $host - * @param int $port - * @param int $timeout - * @param int $cipher - * @return \phpseclib\Net\SSH1 - * @access public - */ - public function __construct($host, $port = 22, $timeout = 10, $cipher = self::CIPHER_3DES) - { - $this->protocol_flags = [ - 1 => 'NET_SSH1_MSG_DISCONNECT', - 2 => 'NET_SSH1_SMSG_PUBLIC_KEY', - 3 => 'NET_SSH1_CMSG_SESSION_KEY', - 4 => 'NET_SSH1_CMSG_USER', - 9 => 'NET_SSH1_CMSG_AUTH_PASSWORD', - 10 => 'NET_SSH1_CMSG_REQUEST_PTY', - 12 => 'NET_SSH1_CMSG_EXEC_SHELL', - 13 => 'NET_SSH1_CMSG_EXEC_CMD', - 14 => 'NET_SSH1_SMSG_SUCCESS', - 15 => 'NET_SSH1_SMSG_FAILURE', - 16 => 'NET_SSH1_CMSG_STDIN_DATA', - 17 => 'NET_SSH1_SMSG_STDOUT_DATA', - 18 => 'NET_SSH1_SMSG_STDERR_DATA', - 19 => 'NET_SSH1_CMSG_EOF', - 20 => 'NET_SSH1_SMSG_EXITSTATUS', - 33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION' - ]; - - $this->define_array($this->protocol_flags); - - $this->host = $host; - $this->port = $port; - $this->connectionTimeout = $timeout; - $this->cipher = $cipher; - } - - /** - * Connect to an SSHv1 server - * - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @access private - */ - private function connect() - { - $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout); - if (!$this->fsock) { - throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr")); - } - - $this->server_identification = $init_line = fgets($this->fsock, 255); - - if (defined('NET_SSH1_LOGGING')) { - $this->append_log('<-', $this->server_identification); - $this->append_log('->', $this->identifier . "\r\n"); - } - - if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) { - throw new \RuntimeException('Can only connect to SSH servers'); - } - if ($parts[1][0] != 1) { - throw new \RuntimeException("Cannot connect to $parts[1] servers"); - } - - fputs($this->fsock, $this->identifier."\r\n"); - - $response = $this->get_binary_packet(); - if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) { - throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY'); - } - - $anti_spoofing_cookie = Strings::shift($response[self::RESPONSE_DATA], 8); - - Strings::shift($response[self::RESPONSE_DATA], 4); - - if (strlen($response[self::RESPONSE_DATA]) < 2) { - return false; - } - $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2)); - $server_key_public_exponent = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256); - $this->server_key_public_exponent = $server_key_public_exponent; - - if (strlen($response[self::RESPONSE_DATA]) < 2) { - return false; - } - $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2)); - $server_key_public_modulus = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256); - - $this->server_key_public_modulus = $server_key_public_modulus; - - Strings::shift($response[self::RESPONSE_DATA], 4); - - if (strlen($response[self::RESPONSE_DATA]) < 2) { - return false; - } - $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2)); - $host_key_public_exponent = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256); - $this->host_key_public_exponent = $host_key_public_exponent; - - if (strlen($response[self::RESPONSE_DATA]) < 2) { - return false; - } - $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2)); - $host_key_public_modulus = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256); - - $this->host_key_public_modulus = $host_key_public_modulus; - - Strings::shift($response[self::RESPONSE_DATA], 4); - - // get a list of the supported ciphers - if (strlen($response[self::RESPONSE_DATA]) < 4) { - return false; - } - extract(unpack('Nsupported_ciphers_mask', Strings::shift($response[self::RESPONSE_DATA], 4))); - - foreach ($this->supported_ciphers as $mask => $name) { - if (($supported_ciphers_mask & (1 << $mask)) == 0) { - unset($this->supported_ciphers[$mask]); - } - } - - // get a list of the supported authentications - if (strlen($response[self::RESPONSE_DATA]) < 4) { - return false; - } - extract(unpack('Nsupported_authentications_mask', Strings::shift($response[self::RESPONSE_DATA], 4))); - foreach ($this->supported_authentications as $mask => $name) { - if (($supported_authentications_mask & (1 << $mask)) == 0) { - unset($this->supported_authentications[$mask]); - } - } - - $session_id = md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie, true); - - $session_key = Random::string(32); - $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0)); - - if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) { - $double_encrypted_session_key = $this->rsa_crypt( - $double_encrypted_session_key, - [ - $server_key_public_exponent, - $server_key_public_modulus - ] - ); - $double_encrypted_session_key = $this->rsa_crypt( - $double_encrypted_session_key, - [ - $host_key_public_exponent, - $host_key_public_modulus - ] - ); - } else { - $double_encrypted_session_key = $this->rsa_crypt( - $double_encrypted_session_key, - [ - $host_key_public_exponent, - $host_key_public_modulus - ] - ); - $double_encrypted_session_key = $this->rsa_crypt( - $double_encrypted_session_key, - [ - $server_key_public_exponent, - $server_key_public_modulus - ] - ); - } - - $cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : self::CIPHER_3DES; - $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY'); - } - - switch ($cipher) { - //case self::CIPHER_NONE: - // $this->crypto = new \phpseclib\Crypt\Null(); - // break; - case self::CIPHER_DES: - $this->crypto = new DES(DES::MODE_CBC); - $this->crypto->disablePadding(); - $this->crypto->enableContinuousBuffer(); - $this->crypto->setKey(substr($session_key, 0, 8)); - // "The iv (initialization vector) is initialized to all zeroes." - $this->crypto->setIV(str_repeat("\0", 8)); - break; - case self::CIPHER_3DES: - $this->crypto = new TripleDES(TripleDES::MODE_3CBC); - $this->crypto->disablePadding(); - $this->crypto->enableContinuousBuffer(); - $this->crypto->setKey(substr($session_key, 0, 24)); - // "All three initialization vectors are initialized to zero." - $this->crypto->setIV(str_repeat("\0", 8)); - break; - //case self::CIPHER_RC4: - // $this->crypto = new RC4(); - // $this->crypto->enableContinuousBuffer(); - // $this->crypto->setKey(substr($session_key, 0, 16)); - // break; - } - - $response = $this->get_binary_packet(); - - if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS'); - } - - $this->bitmap = self::MASK_CONNECTED; - - return true; - } - - /** - * Login - * - * @param string $username - * @param string $password - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @access public - */ - public function login($username, $password = '') - { - if (!($this->bitmap & self::MASK_CONSTRUCTOR)) { - $this->bitmap |= self::MASK_CONSTRUCTOR; - if (!$this->connect()) { - return false; - } - } - - if (!($this->bitmap & self::MASK_CONNECTED)) { - return false; - } - - $data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_USER'); - } - - $response = $this->get_binary_packet(); - - if ($response === true) { - return false; - } - if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { - $this->bitmap |= self::MASK_LOGIN; - return true; - } elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); - } - - $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_AUTH_PASSWORD'); - } - - // remove the username and password from the last logged packet - if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == self::LOG_COMPLEX) { - $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen('password'), 'password'); - $this->message_log[count($this->message_log) - 1] = $data; - } - - $response = $this->get_binary_packet(); - - if ($response === true) { - return false; - } - if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { - $this->bitmap |= self::MASK_LOGIN; - return true; - } elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) { - return false; - } else { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); - } - } - - /** - * Set Timeout - * - * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout. - * Setting $timeout to false or 0 will mean there is no timeout. - * - * @param mixed $timeout - */ - public function setTimeout($timeout) - { - $this->timeout = $this->curTimeout = $timeout; - } - - /** - * Executes a command on a non-interactive shell, returns the output, and quits. - * - * An SSH1 server will close the connection after a command has been executed on a non-interactive shell. SSH2 - * servers don't, however, this isn't an SSH2 client. The way this works, on the server, is by initiating a - * shell with the -s option, as discussed in the following links: - * - * {@link http://www.faqs.org/docs/bashman/bashref_65.html http://www.faqs.org/docs/bashman/bashref_65.html} - * {@link http://www.faqs.org/docs/bashman/bashref_62.html http://www.faqs.org/docs/bashman/bashref_62.html} - * - * To execute further commands, a new \phpseclib\Net\SSH1 object will need to be created. - * - * Returns false on failure and the output, otherwise. - * - * @see self::interactiveRead() - * @see self::interactiveWrite() - * @param string $cmd - * @return mixed - * @throws \RuntimeException on error sending command - * @access public - */ - public function exec($cmd, $block = true) - { - if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); - } - - $data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_EXEC_CMD'); - } - - if (!$block) { - return true; - } - - $output = ''; - $response = $this->get_binary_packet(); - - if ($response !== false) { - do { - $output.= substr($response[self::RESPONSE_DATA], 4); - $response = $this->get_binary_packet(); - } while (is_array($response) && $response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS); - } - - $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION); - - // i don't think it's really all that important if this packet gets sent or not. - $this->send_binary_packet($data); - - fclose($this->fsock); - - // reset the execution bitmap - a new \phpseclib\Net\SSH1 object needs to be created. - $this->bitmap = 0; - - return $output; - } - - /** - * Creates an interactive shell - * - * @see self::interactiveRead() - * @see self::interactiveWrite() - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @access private - */ - private function initShell() - { - // connect using the sample parameters in protocol-1.5.txt. - // according to wikipedia.org's entry on text terminals, "the fundamental type of application running on a text - // terminal is a command line interpreter or shell". thus, opening a terminal session to run the shell. - $data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_REQUEST_PTY'); - } - - $response = $this->get_binary_packet(); - - if ($response === true) { - return false; - } - if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS'); - } - - $data = pack('C', NET_SSH1_CMSG_EXEC_SHELL); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_EXEC_SHELL'); - } - - $this->bitmap |= self::MASK_SHELL; - - //stream_set_blocking($this->fsock, 0); - - return true; - } - - /** - * Inputs a command into an interactive shell. - * - * @see self::interactiveWrite() - * @param string $cmd - * @return bool - * @access public - */ - public function write($cmd) - { - return $this->interactiveWrite($cmd); - } - - /** - * Returns the output of an interactive shell when there's a match for $expect - * - * $expect can take the form of a string literal or, if $mode == self::READ__REGEX, - * a regular expression. - * - * @see self::write() - * @param string $expect - * @param int $mode - * @return bool - * @throws \RuntimeException on connection error - * @access public - */ - public function read($expect, $mode = self::READ__SIMPLE) - { - if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); - } - - if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); - } - - $match = $expect; - while (true) { - if ($mode == self::READ__REGEX) { - preg_match($expect, $this->interactiveBuffer, $matches); - $match = isset($matches[0]) ? $matches[0] : ''; - } - $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false; - if ($pos !== false) { - return Strings::shift($this->interactiveBuffer, $pos + strlen($match)); - } - $response = $this->get_binary_packet(); - - if ($response === true) { - return Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer)); - } - $this->interactiveBuffer.= substr($response[self::RESPONSE_DATA], 4); - } - } - - /** - * Inputs a command into an interactive shell. - * - * @see self::interactiveRead() - * @param string $cmd - * @return bool - * @throws \RuntimeException on connection error - * @access public - */ - public function interactiveWrite($cmd) - { - if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); - } - - if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); - } - - $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_STDIN'); - } - - return true; - } - - /** - * Returns the output of an interactive shell when no more output is available. - * - * Requires PHP 4.3.0 or later due to the use of the stream_select() function. If you see stuff like - * "^[[00m", you're seeing ANSI escape codes. According to - * {@link http://support.microsoft.com/kb/101875 How to Enable ANSI.SYS in a Command Window}, "Windows NT - * does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user, - * there's not going to be much recourse. - * - * @see self::interactiveRead() - * @return string - * @throws \RuntimeException on connection error - * @access public - */ - public function interactiveRead() - { - if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); - } - - if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); - } - - $read = [$this->fsock]; - $write = $except = null; - if (stream_select($read, $write, $except, 0)) { - $response = $this->get_binary_packet(); - return substr($response[self::RESPONSE_DATA], 4); - } else { - return ''; - } - } - - /** - * Disconnect - * - * @access public - */ - public function disconnect() - { - $this->disconnect_helper(); - } - - /** - * Destructor. - * - * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call - * disconnect(). - * - * @access public - */ - public function __destruct() - { - $this->disconnect_helper(); - } - - /** - * Disconnect - * - * @param string $msg - * @access private - */ - private function disconnect_helper($msg = 'Client Quit') - { - if ($this->bitmap) { - $data = pack('C', NET_SSH1_CMSG_EOF); - $this->send_binary_packet($data); - /* - $response = $this->get_binary_packet(); - if ($response === true) { - $response = [self::RESPONSE_TYPE => -1]; - } - switch ($response[self::RESPONSE_TYPE]) { - case NET_SSH1_SMSG_EXITSTATUS: - $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION); - break; - default: - $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg); - } - */ - $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg); - - $this->send_binary_packet($data); - fclose($this->fsock); - $this->bitmap = 0; - } - } - - /** - * Gets Binary Packets - * - * See 'The Binary Packet Protocol' of protocol-1.5.txt for more info. - * - * Also, this function could be improved upon by adding detection for the following exploit: - * http://www.securiteam.com/securitynews/5LP042K3FY.html - * - * @see self::_send_binary_packet() - * @return array - * @access private - */ - private function get_binary_packet() - { - if (feof($this->fsock)) { - //user_error('connection closed prematurely'); - return false; - } - - if ($this->curTimeout) { - $read = [$this->fsock]; - $write = $except = null; - - $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 - $sec = floor($this->curTimeout); - $usec = 1000000 * ($this->curTimeout - $sec); - // on windows this returns a "Warning: Invalid CRT parameters detected" error - if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { - //$this->disconnect_helper('Timeout'); - return true; - } - $elapsed = strtok(microtime(), ' ') + strtok('') - $start; - $this->curTimeout-= $elapsed; - } - - $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 - $data = fread($this->fsock, 4); - if (strlen($data) < 4) { - return false; - } - $temp = unpack('Nlength', $data); - - $padding_length = 8 - ($temp['length'] & 7); - $length = $temp['length'] + $padding_length; - $raw = ''; - - while ($length > 0) { - $temp = fread($this->fsock, $length); - $raw.= $temp; - $length-= strlen($temp); - } - $stop = strtok(microtime(), ' ') + strtok(''); - - if (strlen($raw) && $this->crypto !== false) { - $raw = $this->crypto->decrypt($raw); - } - - $padding = substr($raw, 0, $padding_length); - $type = $raw[$padding_length]; - $data = substr($raw, $padding_length + 1, -4); - - if (strlen($raw) < 4) { - return false; - } - $temp = unpack('Ncrc', substr($raw, -4)); - - //if ( $temp['crc'] != $this->crc($padding . $type . $data) ) { - // user_error('Bad CRC in packet from server'); - // return false; - //} - - $type = ord($type); - - if (defined('NET_SSH1_LOGGING')) { - $temp = isset($this->protocol_flags[$type]) ? $this->protocol_flags[$type] : 'UNKNOWN'; - $temp = '<- ' . $temp . - ' (' . round($stop - $start, 4) . 's)'; - $this->append_log($temp, $data); - } - - return [ - self::RESPONSE_TYPE => $type, - self::RESPONSE_DATA => $data - ]; - } - - /** - * Sends Binary Packets - * - * Returns true on success, false on failure. - * - * @see self::_get_binary_packet() - * @param string $data - * @return bool - * @access private - */ - private function send_binary_packet($data) - { - if (feof($this->fsock)) { - //user_error('connection closed prematurely'); - return false; - } - - $length = strlen($data) + 4; - - $padding = Random::string(8 - ($length & 7)); - - $orig = $data; - $data = $padding . $data; - $data.= pack('N', $this->crc($data)); - - if ($this->crypto !== false) { - $data = $this->crypto->encrypt($data); - } - - $packet = pack('Na*', $length, $data); - - $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 - $result = strlen($packet) == fputs($this->fsock, $packet); - $stop = strtok(microtime(), ' ') + strtok(''); - - if (defined('NET_SSH1_LOGGING')) { - $temp = isset($this->protocol_flags[ord($orig[0])]) ? $this->protocol_flags[ord($orig[0])] : 'UNKNOWN'; - $temp = '-> ' . $temp . - ' (' . round($stop - $start, 4) . 's)'; - $this->append_log($temp, $orig); - } - - return $result; - } - - /** - * Cyclic Redundancy Check (CRC) - * - * PHP's crc32 function is implemented slightly differently than the one that SSH v1 uses, so - * we've reimplemented it. A more detailed discussion of the differences can be found after - * $crc_lookup_table's initialization. - * - * @see self::_get_binary_packet() - * @see self::_send_binary_packet() - * @param string $data - * @return int - * @access private - */ - private function crc($data) - { - static $crc_lookup_table = [ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D - ]; - - // For this function to yield the same output as PHP's crc32 function, $crc would have to be - // set to 0xFFFFFFFF, initially - not 0x00000000 as it currently is. - $crc = 0x00000000; - $length = strlen($data); - - for ($i=0; $i<$length; $i++) { - // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all - // be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example, - // yields 0xFF800000 - not 0x00800000. The following link elaborates: - // http://www.php.net/manual/en/language.operators.bitwise.php#57281 - $crc = (($crc >> 8) & 0x00FFFFFF) ^ $crc_lookup_table[($crc & 0xFF) ^ ord($data[$i])]; - } - - // In addition to having to set $crc to 0xFFFFFFFF, initially, the return value must be XOR'd with - // 0xFFFFFFFF for this function to return the same thing that PHP's crc32 function would. - return $crc; - } - - /** - * RSA Encrypt - * - * Returns mod(pow($m, $e), $n), where $n should be the product of two (large) primes $p and $q and where $e - * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that - * calls this call modexp, instead, but I think this makes things clearer, maybe... - * - * @see self::__construct() - * @param BigInteger $m - * @param array $key - * @return BigInteger - * @access private - */ - private function rsa_crypt($m, $key) - { - /* - $rsa = new RSA(); - $rsa->load($key, 'raw'); - $rsa->setHash('sha1'); - return $rsa->encrypt($m, RSA::PADDING_PKCS1); - */ - - // To quote from protocol-1.5.txt: - // The most significant byte (which is only partial as the value must be - // less than the public modulus, which is never a power of two) is zero. - // - // The next byte contains the value 2 (which stands for public-key - // encrypted data in the PKCS standard [PKCS#1]). Then, there are non- - // zero random bytes to fill any unused space, a zero byte, and the data - // to be encrypted in the least significant bytes, the last byte of the - // data in the least significant byte. - - // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation", - // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL: - // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf - $modulus = $key[1]->toBytes(); - $length = strlen($modulus) - strlen($m) - 3; - $random = ''; - while (strlen($random) != $length) { - $block = Random::string($length - strlen($random)); - $block = str_replace("\x00", '', $block); - $random.= $block; - } - $temp = chr(0) . chr(2) . $random . chr(0) . $m; - - $m = new BigInteger($temp, 256); - $m = $m->modPow($key[0], $key[1]); - - return $m->toBytes(); - } - - /** - * Define Array - * - * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of - * named constants from it, using the value as the name of the constant and the index as the value of the constant. - * If any of the constants that would be defined already exists, none of the constants will be defined. - * - * @param array $array - * @access private - */ - private function define_array() - { - $args = func_get_args(); - foreach ($args as $arg) { - foreach ($arg as $key => $value) { - if (!defined($value)) { - define($value, $key); - } else { - break 2; - } - } - } - } - - /** - * Returns a log of the packets that have been sent and received. - * - * Returns a string if NET_SSH1_LOGGING == self::LOG_COMPLEX, an array if NET_SSH1_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING') - * - * @access public - * @return array|false|string - */ - public function getLog() - { - if (!defined('NET_SSH1_LOGGING')) { - return false; - } - - switch (NET_SSH1_LOGGING) { - case self::LOG_SIMPLE: - return $this->message_number_log; - break; - case self::LOG_COMPLEX: - return $this->format_log($this->message_log, $this->protocol_flags_log); - break; - default: - return false; - } - } - - /** - * Formats a log for printing - * - * @param array $message_log - * @param array $message_number_log - * @access private - * @return string - */ - private function format_log($message_log, $message_number_log) - { - $output = ''; - for ($i = 0; $i < count($message_log); $i++) { - $output.= $message_number_log[$i] . "\r\n"; - $current_log = $message_log[$i]; - $j = 0; - do { - if (strlen($current_log)) { - $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 '; - } - $fragment = Strings::shift($current_log, $this->log_short_width); - $hex = substr(preg_replace_callback('#.#s', [$this, 'format_log_helper'], $fragment), strlen($this->log_boundary)); - // replace non ASCII printable characters with dots - // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters - // also replace < with a . since < messes up the output on web browsers - $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); - $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n"; - $j++; - } while (strlen($current_log)); - $output.= "\r\n"; - } - - return $output; - } - - /** - * Helper function for _format_log - * - * For use with preg_replace_callback() - * - * @param array $matches - * @access private - * @return string - */ - private function format_log_helper($matches) - { - return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT); - } - - /** - * Return the server key public exponent - * - * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, - * the raw bytes. This behavior is similar to PHP's md5() function. - * - * @param bool $raw_output - * @return string - * @access public - */ - public function getServerKeyPublicExponent($raw_output = false) - { - return $raw_output ? $this->server_key_public_exponent->toBytes() : $this->server_key_public_exponent->toString(); - } - - /** - * Return the server key public modulus - * - * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, - * the raw bytes. This behavior is similar to PHP's md5() function. - * - * @param bool $raw_output - * @return string - * @access public - */ - public function getServerKeyPublicModulus($raw_output = false) - { - return $raw_output ? $this->server_key_public_modulus->toBytes() : $this->server_key_public_modulus->toString(); - } - - /** - * Return the host key public exponent - * - * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, - * the raw bytes. This behavior is similar to PHP's md5() function. - * - * @param bool $raw_output - * @return string - * @access public - */ - public function getHostKeyPublicExponent($raw_output = false) - { - return $raw_output ? $this->host_key_public_exponent->toBytes() : $this->host_key_public_exponent->toString(); - } - - /** - * Return the host key public modulus - * - * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, - * the raw bytes. This behavior is similar to PHP's md5() function. - * - * @param bool $raw_output - * @return string - * @access public - */ - public function getHostKeyPublicModulus($raw_output = false) - { - return $raw_output ? $this->host_key_public_modulus->toBytes() : $this->host_key_public_modulus->toString(); - } - - /** - * Return a list of ciphers supported by SSH1 server. - * - * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output - * is set to true, returns, instead, an array of constants. ie. instead of ['Triple-DES in CBC mode'], you'll - * get [self::CIPHER_3DES]. - * - * @param bool $raw_output - * @return array - * @access public - */ - public function getSupportedCiphers($raw_output = false) - { - return $raw_output ? array_keys($this->supported_ciphers) : array_values($this->supported_ciphers); - } - - /** - * Return a list of authentications supported by SSH1 server. - * - * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output - * is set to true, returns, instead, an array of constants. ie. instead of ['password authentication'], you'll - * get [self::AUTH_PASSWORD]. - * - * @param bool $raw_output - * @return array - * @access public - */ - public function getSupportedAuthentications($raw_output = false) - { - return $raw_output ? array_keys($this->supported_authentications) : array_values($this->supported_authentications); - } - - /** - * Return the server identification. - * - * @return string - * @access public - */ - public function getServerIdentification() - { - return rtrim($this->server_identification); - } - - /** - * Logs data packets - * - * Makes sure that only the last 1MB worth of packets will be logged - * - * @param string $data - * @access private - */ - private function append_log($protocol_flags, $message) - { - switch (NET_SSH1_LOGGING) { - // useful for benchmarks - case self::LOG_SIMPLE: - $this->protocol_flags_log[] = $protocol_flags; - break; - // the most useful log for SSH1 - case self::LOG_COMPLEX: - $this->protocol_flags_log[] = $protocol_flags; - Strings::shift($message); - $this->log_size+= strlen($message); - $this->message_log[] = $message; - while ($this->log_size > self::LOG_MAX_SIZE) { - $this->log_size-= strlen(array_shift($this->message_log)); - array_shift($this->protocol_flags_log); - } - break; - // dump the output out realtime; packets may be interspersed with non packets, - // passwords won't be filtered out and select other packets may not be correctly - // identified - case self::LOG_REALTIME: - echo "
\r\n" . $this->format_log([$message], [$protocol_flags]) . "\r\n
\r\n"; - @flush(); - @ob_flush(); - break; - // basically the same thing as self::LOG_REALTIME with the caveat that self::LOG_REALTIME_FILE - // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE. - // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily - // at the beginning of the file - case self::LOG_REALTIME_FILE: - if (!isset($this->realtime_log_file)) { - // PHP doesn't seem to like using constants in fopen() - $filename = self::LOG_REALTIME_FILE; - $fp = fopen($filename, 'w'); - $this->realtime_log_file = $fp; - } - if (!is_resource($this->realtime_log_file)) { - break; - } - $entry = $this->format_log([$message], [$protocol_flags]); - if ($this->realtime_log_wrap) { - $temp = "<<< START >>>\r\n"; - $entry.= $temp; - fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); - } - $this->realtime_log_size+= strlen($entry); - if ($this->realtime_log_size > self::LOG_MAX_SIZE) { - fseek($this->realtime_log_file, 0); - $this->realtime_log_size = strlen($entry); - $this->realtime_log_wrap = true; - } - fputs($this->realtime_log_file, $entry); - } - } -} diff --git a/lib/phpaes/phpseclib/Net/SSH2.php b/lib/phpaes/phpseclib/Net/SSH2.php deleted file mode 100644 index f733ee782d..0000000000 --- a/lib/phpaes/phpseclib/Net/SSH2.php +++ /dev/null @@ -1,4441 +0,0 @@ - - * login('username', 'password')) { - * exit('Login Failed'); - * } - * - * echo $ssh->exec('pwd'); - * echo $ssh->exec('ls -la'); - * ?> - * - * - * - * setPassword('whatever'); - * $key->load(file_get_contents('privatekey')); - * - * $ssh = new \phpseclib\Net\SSH2('www.domain.tld'); - * if (!$ssh->login('username', $key)) { - * exit('Login Failed'); - * } - * - * echo $ssh->read('username@username:~$'); - * $ssh->write("ls -la\n"); - * echo $ssh->read('username@username:~$'); - * ?> - * - * - * @category Net - * @package SSH2 - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Net; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Crypt\Common\BlockCipher; -use phpseclib\Crypt\Blowfish; -use phpseclib\Crypt\Hash; -use phpseclib\Crypt\Random; -use phpseclib\Crypt\RC4; -use phpseclib\Crypt\Rijndael; -use phpseclib\Crypt\RSA; -use phpseclib\Crypt\TripleDES; -use phpseclib\Crypt\Twofish; -use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification. -use phpseclib\System\SSH\Agent; -use phpseclib\Exception\NoSupportedAlgorithmsException; -use phpseclib\Common\Functions\Strings; -use phpseclib\Common\Functions\Objects; - -/** - * Pure-PHP implementation of SSHv2. - * - * @package SSH2 - * @author Jim Wigginton - * @access public - */ -class SSH2 -{ - /**#@+ - * Execution Bitmap Masks - * - * @see \phpseclib\Net\SSH2::bitmap - * @access private - */ - const MASK_CONSTRUCTOR = 0x00000001; - const MASK_CONNECTED = 0x00000002; - const MASK_LOGIN_REQ = 0x00000004; - const MASK_LOGIN = 0x00000008; - const MASK_SHELL = 0x00000010; - const MASK_WINDOW_ADJUST = 0x00000020; - /**#@-*/ - - /**#@+ - * Channel constants - * - * RFC4254 refers not to client and server channels but rather to sender and recipient channels. we don't refer - * to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with - * a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a - * recepient channel. at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel - * would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snipet: - * The 'recipient channel' is the channel number given in the original - * open request, and 'sender channel' is the channel number allocated by - * the other side. - * - * @see \phpseclib\Net\SSH2::_send_channel_packet() - * @see \phpseclib\Net\SSH2::_get_channel_packet() - * @access private - */ - const CHANNEL_EXEC = 0; // PuTTy uses 0x100 - const CHANNEL_SHELL = 1; - const CHANNEL_SUBSYSTEM = 2; - const CHANNEL_AGENT_FORWARD = 3; - /**#@-*/ - - /**#@+ - * @access public - * @see \phpseclib\Net\SSH2::getLog() - */ - /** - * Returns the message numbers - */ - const LOG_SIMPLE = 1; - /** - * Returns the message content - */ - const LOG_COMPLEX = 2; - /** - * Outputs the content real-time - */ - const LOG_REALTIME = 3; - /** - * Dumps the content real-time to a file - */ - const LOG_REALTIME_FILE = 4; - /**#@-*/ - - /**#@+ - * @access public - * @see \phpseclib\Net\SSH2::read() - */ - /** - * Returns when a string matching $expect exactly is found - */ - const READ_SIMPLE = 1; - /** - * Returns when a string matching the regular expression $expect is found - */ - const READ_REGEX = 2; - /** - * Make sure that the log never gets larger than this - */ - const LOG_MAX_SIZE = 1048576; // 1024 * 1024 - /**#@-*/ - - /** - * The SSH identifier - * - * @var string - * @access private - */ - private $identifier; - - /** - * The Socket Object - * - * @var object - * @access private - */ - private $fsock; - - /** - * Execution Bitmap - * - * The bits that are set represent functions that have been called already. This is used to determine - * if a requisite function has been successfully executed. If not, an error should be thrown. - * - * @var int - * @access private - */ - protected $bitmap = 0; - - /** - * Error information - * - * @see self::getErrors() - * @see self::getLastError() - * @var array - * @access private - */ - private $errors = []; - - /** - * Server Identifier - * - * @see self::getServerIdentification() - * @var array|false - * @access private - */ - private $server_identifier = false; - - /** - * Key Exchange Algorithms - * - * @see self::getKexAlgorithims() - * @var array|false - * @access private - */ - private $kex_algorithms = false; - - /** - * Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods - * - * @see self::_key_exchange() - * @var int - * @access private - */ - private $kex_dh_group_size_min = 1536; - - /** - * Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods - * - * @see self::_key_exchange() - * @var int - * @access private - */ - private $kex_dh_group_size_preferred = 2048; - - /** - * Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods - * - * @see self::_key_exchange() - * @var int - * @access private - */ - private $kex_dh_group_size_max = 4096; - - /** - * Server Host Key Algorithms - * - * @see self::getServerHostKeyAlgorithms() - * @var array|false - * @access private - */ - private $server_host_key_algorithms = false; - - /** - * Encryption Algorithms: Client to Server - * - * @see self::getEncryptionAlgorithmsClient2Server() - * @var array|false - * @access private - */ - private $encryption_algorithms_client_to_server = false; - - /** - * Encryption Algorithms: Server to Client - * - * @see self::getEncryptionAlgorithmsServer2Client() - * @var array|false - * @access private - */ - private $encryption_algorithms_server_to_client = false; - - /** - * MAC Algorithms: Client to Server - * - * @see self::getMACAlgorithmsClient2Server() - * @var array|false - * @access private - */ - private $mac_algorithms_client_to_server = false; - - /** - * MAC Algorithms: Server to Client - * - * @see self::getMACAlgorithmsServer2Client() - * @var array|false - * @access private - */ - private $mac_algorithms_server_to_client = false; - - /** - * Compression Algorithms: Client to Server - * - * @see self::getCompressionAlgorithmsClient2Server() - * @var array|false - * @access private - */ - private $compression_algorithms_client_to_server = false; - - /** - * Compression Algorithms: Server to Client - * - * @see self::getCompressionAlgorithmsServer2Client() - * @var array|false - * @access private - */ - private $compression_algorithms_server_to_client = false; - - /** - * Languages: Server to Client - * - * @see self::getLanguagesServer2Client() - * @var array|false - * @access private - */ - private $languages_server_to_client = false; - - /** - * Languages: Client to Server - * - * @see self::getLanguagesClient2Server() - * @var array|false - * @access private - */ - private $languages_client_to_server = false; - - /** - * Block Size for Server to Client Encryption - * - * "Note that the length of the concatenation of 'packet_length', - * 'padding_length', 'payload', and 'random padding' MUST be a multiple - * of the cipher block size or 8, whichever is larger. This constraint - * MUST be enforced, even when using stream ciphers." - * - * -- http://tools.ietf.org/html/rfc4253#section-6 - * - * @see self::__construct() - * @see self::_send_binary_packet() - * @var int - * @access private - */ - private $encrypt_block_size = 8; - - /** - * Block Size for Client to Server Encryption - * - * @see self::__construct() - * @see self::_get_binary_packet() - * @var int - * @access private - */ - private $decrypt_block_size = 8; - - /** - * Server to Client Encryption Object - * - * @see self::_get_binary_packet() - * @var object - * @access private - */ - private $decrypt = false; - - /** - * Client to Server Encryption Object - * - * @see self::_send_binary_packet() - * @var object - * @access private - */ - private $encrypt = false; - - /** - * Client to Server HMAC Object - * - * @see self::_send_binary_packet() - * @var object - * @access private - */ - private $hmac_create = false; - - /** - * Server to Client HMAC Object - * - * @see self::_get_binary_packet() - * @var object - * @access private - */ - private $hmac_check = false; - - /** - * Size of server to client HMAC - * - * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read. - * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is - * append it. - * - * @see self::_get_binary_packet() - * @var int - * @access private - */ - private $hmac_size = false; - - /** - * Server Public Host Key - * - * @see self::getServerPublicHostKey() - * @var string - * @access private - */ - private $server_public_host_key; - - /** - * Session identifier - * - * "The exchange hash H from the first key exchange is additionally - * used as the session identifier, which is a unique identifier for - * this connection." - * - * -- http://tools.ietf.org/html/rfc4253#section-7.2 - * - * @see self::_key_exchange() - * @var string - * @access private - */ - private $session_id = false; - - /** - * Exchange hash - * - * The current exchange hash - * - * @see self::_key_exchange() - * @var string - * @access private - */ - private $exchange_hash = false; - - /** - * Message Numbers - * - * @see self::__construct() - * @var array - * @access private - */ - private $message_numbers = []; - - /** - * Disconnection Message 'reason codes' defined in RFC4253 - * - * @see self::__construct() - * @var array - * @access private - */ - private $disconnect_reasons = []; - - /** - * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254 - * - * @see self::__construct() - * @var array - * @access private - */ - private $channel_open_failure_reasons = []; - - /** - * Terminal Modes - * - * @link http://tools.ietf.org/html/rfc4254#section-8 - * @see self::__construct() - * @var array - * @access private - */ - private $terminal_modes = []; - - /** - * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes - * - * @link http://tools.ietf.org/html/rfc4254#section-5.2 - * @see self::__construct() - * @var array - * @access private - */ - private $channel_extended_data_type_codes = []; - - /** - * Send Sequence Number - * - * See 'Section 6.4. Data Integrity' of rfc4253 for more info. - * - * @see self::_send_binary_packet() - * @var int - * @access private - */ - private $send_seq_no = 0; - - /** - * Get Sequence Number - * - * See 'Section 6.4. Data Integrity' of rfc4253 for more info. - * - * @see self::_get_binary_packet() - * @var int - * @access private - */ - private $get_seq_no = 0; - - /** - * Server Channels - * - * Maps client channels to server channels - * - * @see self::_get_channel_packet() - * @see self::exec() - * @var array - * @access private - */ - protected $server_channels = []; - - /** - * Channel Buffers - * - * If a client requests a packet from one channel but receives two packets from another those packets should - * be placed in a buffer - * - * @see self::_get_channel_packet() - * @see self::exec() - * @var array - * @access private - */ - private $channel_buffers = []; - - /** - * Channel Status - * - * Contains the type of the last sent message - * - * @see self::_get_channel_packet() - * @var array - * @access private - */ - protected $channel_status = []; - - /** - * Packet Size - * - * Maximum packet size indexed by channel - * - * @see self::_send_channel_packet() - * @var array - * @access private - */ - private $packet_size_client_to_server = []; - - /** - * Message Number Log - * - * @see self::getLog() - * @var array - * @access private - */ - private $message_number_log = []; - - /** - * Message Log - * - * @see self::getLog() - * @var array - * @access private - */ - private $message_log = []; - - /** - * The Window Size - * - * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB) - * - * @var int - * @see self::_send_channel_packet() - * @see self::exec() - * @access private - */ - protected $window_size = 0x7FFFFFFF; - - /** - * Window size, server to client - * - * Window size indexed by channel - * - * @see self::_send_channel_packet() - * @var array - * @access private - */ - protected $window_size_server_to_client = []; - - /** - * Window size, client to server - * - * Window size indexed by channel - * - * @see self::_get_channel_packet() - * @var array - * @access private - */ - private $window_size_client_to_server = []; - - /** - * Server signature - * - * Verified against $this->session_id - * - * @see self::getServerPublicHostKey() - * @var string - * @access private - */ - private $signature = ''; - - /** - * Server signature format - * - * ssh-rsa or ssh-dss. - * - * @see self::getServerPublicHostKey() - * @var string - * @access private - */ - private $signature_format = ''; - - /** - * Interactive Buffer - * - * @see self::read() - * @var array - * @access private - */ - private $interactiveBuffer = ''; - - /** - * Current log size - * - * Should never exceed self::LOG_MAX_SIZE - * - * @see self::_send_binary_packet() - * @see self::_get_binary_packet() - * @var int - * @access private - */ - private $log_size; - - /** - * Timeout - * - * @see self::setTimeout() - * @access private - */ - private $timeout; - - /** - * Current Timeout - * - * @see self::_get_channel_packet() - * @access private - */ - private $curTimeout; - - /** - * Real-time log file pointer - * - * @see self::_append_log() - * @var resource - * @access private - */ - private $realtime_log_file; - - /** - * Real-time log file size - * - * @see self::_append_log() - * @var int - * @access private - */ - private $realtime_log_size; - - /** - * Has the signature been validated? - * - * @see self::getServerPublicHostKey() - * @var bool - * @access private - */ - private $signature_validated = false; - - /** - * Real-time log file wrap boolean - * - * @see self::_append_log() - * @access private - */ - private $realtime_log_wrap; - - /** - * Flag to suppress stderr from output - * - * @see self::enableQuietMode() - * @access private - */ - private $quiet_mode = false; - - /** - * Time of first network activity - * - * @var int - * @access private - */ - private $last_packet; - - /** - * Exit status returned from ssh if any - * - * @var int - * @access private - */ - private $exit_status; - - /** - * Flag to request a PTY when using exec() - * - * @var bool - * @see self::enablePTY() - * @access private - */ - private $request_pty = false; - - /** - * Flag set while exec() is running when using enablePTY() - * - * @var bool - * @access private - */ - private $in_request_pty_exec = false; - - /** - * Flag set after startSubsystem() is called - * - * @var bool - * @access private - */ - private $in_subsystem; - - /** - * Contents of stdError - * - * @var string - * @access private - */ - private $stdErrorLog; - - /** - * The Last Interactive Response - * - * @see self::_keyboard_interactive_process() - * @var string - * @access private - */ - private $last_interactive_response = ''; - - /** - * Keyboard Interactive Request / Responses - * - * @see self::_keyboard_interactive_process() - * @var array - * @access private - */ - private $keyboard_requests_responses = []; - - /** - * Banner Message - * - * Quoting from the RFC, "in some jurisdictions, sending a warning message before - * authentication may be relevant for getting legal protection." - * - * @see self::_filter() - * @see self::getBannerMessage() - * @var string - * @access private - */ - private $banner_message = ''; - - /** - * Did read() timeout or return normally? - * - * @see self::isTimeout() - * @var bool - * @access private - */ - private $is_timeout = false; - - /** - * Log Boundary - * - * @see self::_format_log() - * @var string - * @access private - */ - private $log_boundary = ':'; - - /** - * Log Long Width - * - * @see self::_format_log() - * @var int - * @access private - */ - private $log_long_width = 65; - - /** - * Log Short Width - * - * @see self::_format_log() - * @var int - * @access private - */ - private $log_short_width = 16; - - /** - * Hostname - * - * @see self::__construct() - * @see self::_connect() - * @var string - * @access private - */ - private $host; - - /** - * Port Number - * - * @see self::__construct() - * @see self::_connect() - * @var int - * @access private - */ - private $port; - - /** - * Number of columns for terminal window size - * - * @see self::getWindowColumns() - * @see self::setWindowColumns() - * @see self::setWindowSize() - * @var int - * @access private - */ - private $windowColumns = 80; - - /** - * Number of columns for terminal window size - * - * @see self::getWindowRows() - * @see self::setWindowRows() - * @see self::setWindowSize() - * @var int - * @access private - */ - private $windowRows = 24; - - /** - * Crypto Engine - * - * @see self::setCryptoEngine() - * @see self::_key_exchange() - * @var int - * @access private - */ - private $crypto_engine = false; - - /** - * A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario - * - * @var System_SSH_Agent - * @access private - */ - private $agent; - - /** - * Connection storage to replicates ssh2 extension functionality: - * {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples} - * - * @var SSH2[] - */ - private static $connections; - - /** - * Default Constructor. - * - * $host can either be a string, representing the host, or a stream resource. - * - * @param mixed $host - * @param int $port - * @param int $timeout - * @see self::login() - * @return \phpseclib\Net\SSH2 - * @access public - */ - public function __construct($host, $port = 22, $timeout = 10) - { - $this->message_numbers = [ - 1 => 'NET_SSH2_MSG_DISCONNECT', - 2 => 'NET_SSH2_MSG_IGNORE', - 3 => 'NET_SSH2_MSG_UNIMPLEMENTED', - 4 => 'NET_SSH2_MSG_DEBUG', - 5 => 'NET_SSH2_MSG_SERVICE_REQUEST', - 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT', - 20 => 'NET_SSH2_MSG_KEXINIT', - 21 => 'NET_SSH2_MSG_NEWKEYS', - 30 => 'NET_SSH2_MSG_KEXDH_INIT', - 31 => 'NET_SSH2_MSG_KEXDH_REPLY', - 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST', - 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE', - 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS', - 53 => 'NET_SSH2_MSG_USERAUTH_BANNER', - - 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST', - 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS', - 82 => 'NET_SSH2_MSG_REQUEST_FAILURE', - 90 => 'NET_SSH2_MSG_CHANNEL_OPEN', - 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION', - 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE', - 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST', - 94 => 'NET_SSH2_MSG_CHANNEL_DATA', - 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA', - 96 => 'NET_SSH2_MSG_CHANNEL_EOF', - 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE', - 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST', - 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS', - 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE' - ]; - $this->disconnect_reasons = [ - 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT', - 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR', - 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED', - 4 => 'NET_SSH2_DISCONNECT_RESERVED', - 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR', - 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR', - 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE', - 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED', - 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE', - 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST', - 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION', - 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS', - 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER', - 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE', - 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME' - ]; - $this->channel_open_failure_reasons = [ - 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED' - ]; - $this->terminal_modes = [ - 0 => 'NET_SSH2_TTY_OP_END' - ]; - $this->channel_extended_data_type_codes = [ - 1 => 'NET_SSH2_EXTENDED_DATA_STDERR' - ]; - - $this->define_array( - $this->message_numbers, - $this->disconnect_reasons, - $this->channel_open_failure_reasons, - $this->terminal_modes, - $this->channel_extended_data_type_codes, - [60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'], - [60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'], - [60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', - 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'], - // RFC 4419 - diffie-hellman-group-exchange-sha{1,256} - [30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD', - 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP', - 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT', - 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY', - 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'], - // RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org) - [30 => 'NET_SSH2_MSG_KEX_ECDH_INIT', - 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY'] - ); - - self::$connections[$this->getResourceId()] = $this; - - if (is_resource($host)) { - $this->fsock = $host; - return; - } - - if (is_string($host)) { - $this->host = $host; - $this->port = $port; - $this->timeout = $timeout; - } - } - - /** - * Set Crypto Engine Mode - * - * Possible $engine values: - * CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT - * - * @param int $engine - * @access private - */ - public function setCryptoEngine($engine) - { - $this->crypto_engine = $engine; - } - - /** - * Connect to an SSHv2 server - * - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @access private - */ - private function connect() - { - if ($this->bitmap & self::MASK_CONSTRUCTOR) { - return false; - } - - $this->bitmap |= self::MASK_CONSTRUCTOR; - - $this->curTimeout = $this->timeout; - - $this->last_packet = microtime(true); - - if (!is_resource($this->fsock)) { - $start = microtime(true); - // with stream_select a timeout of 0 means that no timeout takes place; - // with fsockopen a timeout of 0 means that you instantly timeout - // to resolve this incompatibility a timeout of 100,000 will be used for fsockopen if timeout is 0 - $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout); - if (!$this->fsock) { - $host = $this->host . ':' . $this->port; - throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr")); - } - $elapsed = microtime(true) - $start; - - $this->curTimeout-= $elapsed; - - if ($this->curTimeout <= 0) { - $this->is_timeout = true; - return false; - } - } - - $this->identifier = $this->generate_identifier(); - - fputs($this->fsock, $this->identifier . "\r\n"); - - /* According to the SSH2 specs, - - "The server MAY send other lines of data before sending the version - string. Each line SHOULD be terminated by a Carriage Return and Line - Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded - in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients - MUST be able to process such lines." */ - $data = ''; - while (!feof($this->fsock) && !preg_match('#(.*)^(SSH-(\d\.\d+).*)#ms', $data, $matches)) { - $line = ''; - while (true) { - if ($this->curTimeout) { - if ($this->curTimeout < 0) { - $this->is_timeout = true; - return false; - } - $read = [$this->fsock]; - $write = $except = null; - $start = microtime(true); - $sec = floor($this->curTimeout); - $usec = 1000000 * ($this->curTimeout - $sec); - // on windows this returns a "Warning: Invalid CRT parameters detected" error - // the !count() is done as a workaround for - if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { - $this->is_timeout = true; - return false; - } - $elapsed = microtime(true) - $start; - $this->curTimeout-= $elapsed; - } - - $temp = stream_get_line($this->fsock, 255, "\n"); - if (strlen($temp) == 255) { - continue; - } - - $line.= "$temp\n"; - - // quoting RFC4253, "Implementers who wish to maintain - // compatibility with older, undocumented versions of this protocol may - // want to process the identification string without expecting the - // presence of the carriage return character for reasons described in - // Section 5 of this document." - - //if (substr($line, -2) == "\r\n") { - // break; - //} - - break; - } - - $data.= $line; - } - - if (feof($this->fsock)) { - throw new \RuntimeException('Connection closed by server'); - } - - $extra = $matches[1]; - - if (defined('NET_SSH2_LOGGING')) { - $this->append_log('<-', $matches[0]); - $this->append_log('->', $this->identifier . "\r\n"); - } - - $this->server_identifier = trim($temp, "\r\n"); - if (strlen($extra)) { - $this->errors[] = utf8_decode($data); - } - - if ($matches[3] != '1.99' && $matches[3] != '2.0') { - throw new \RuntimeException("Cannot connect to SSH $matches[1] servers"); - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) { - throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT'); - } - - if (!$this->key_exchange($response)) { - return false; - } - - $this->bitmap|= self::MASK_CONNECTED; - - return true; - } - - /** - * Generates the SSH identifier - * - * You should overwrite this method in your own class if you want to use another identifier - * - * @access protected - * @return string - */ - private function generate_identifier() - { - $identifier = 'SSH-2.0-phpseclib_2.0'; - - $ext = []; - if (extension_loaded('libsodium')) { - $ext[] = 'libsodium'; - } - - if (extension_loaded('openssl')) { - $ext[] = 'openssl'; - } elseif (extension_loaded('mcrypt')) { - $ext[] = 'mcrypt'; - } - - if (extension_loaded('gmp')) { - $ext[] = 'gmp'; - } elseif (extension_loaded('bcmath')) { - $ext[] = 'bcmath'; - } - - if (!empty($ext)) { - $identifier .= ' (' . implode(', ', $ext) . ')'; - } - - return $identifier; - } - - /** - * Key Exchange - * - * @param string $kexinit_payload_server - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @throws \phpseclib\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible - * @access private - */ - private function key_exchange($kexinit_payload_server) - { - $kex_algorithms = [ - // Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using - // Curve25519. See doc/curve25519-sha256@libssh.org.txt in the - // libssh repository for more information. - 'curve25519-sha256@libssh.org', - - // Diffie-Hellman Key Agreement (DH) using integer modulo prime - // groups. - 'diffie-hellman-group1-sha1', // REQUIRED - 'diffie-hellman-group14-sha1', // REQUIRED - 'diffie-hellman-group-exchange-sha1', // RFC 4419 - 'diffie-hellman-group-exchange-sha256', // RFC 4419 - ]; - if (!function_exists('\\Sodium\\library_version_major')) { - $kex_algorithms = array_diff( - $kex_algorithms, - ['curve25519-sha256@libssh.org'] - ); - } - - $server_host_key_algorithms = [ - 'ssh-rsa', // RECOMMENDED sign Raw RSA Key - 'ssh-dss' // REQUIRED sign Raw DSS Key - ]; - - $encryption_algorithms = [ - // from : - 'arcfour256', - 'arcfour128', - - //'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key - - // CTR modes from : - 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key - 'aes192-ctr', // RECOMMENDED AES with 192-bit key - 'aes256-ctr', // RECOMMENDED AES with 256-bit key - - 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key - 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key - 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key - - 'aes128-cbc', // RECOMMENDED AES with a 128-bit key - 'aes192-cbc', // OPTIONAL AES with a 192-bit key - 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key - - 'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key - 'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key - 'twofish256-cbc', - 'twofish-cbc', // OPTIONAL alias for "twofish256-cbc" - // (this is being retained for historical reasons) - - 'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode - - 'blowfish-cbc', // OPTIONAL Blowfish in CBC mode - - '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode - - '3des-cbc', // REQUIRED three-key 3DES in CBC mode - //'none' // OPTIONAL no encryption; NOT RECOMMENDED - ]; - - if (extension_loaded('openssl') && !extension_loaded('mcrypt')) { - // OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to - // instances that do not use continuous buffers - $encryption_algorithms = array_diff( - $encryption_algorithms, - ['arcfour256', 'arcfour128', 'arcfour'] - ); - } - - if (class_exists('\phpseclib\Crypt\RC4') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - ['arcfour256', 'arcfour128', 'arcfour'] - ); - } - if (class_exists('\phpseclib\Crypt\Rijndael') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - ['aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc'] - ); - } - if (class_exists('\phpseclib\Crypt\Twofish') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - ['twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc'] - ); - } - if (class_exists('\phpseclib\Crypt\Blowfish') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - ['blowfish-ctr', 'blowfish-cbc'] - ); - } - if (class_exists('\phpseclib\Crypt\TripleDES') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - ['3des-ctr', '3des-cbc'] - ); - } - $encryption_algorithms = array_values($encryption_algorithms); - - $mac_algorithms = [ - // from : - 'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32) - - 'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20) - 'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20) - 'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16) - 'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16) - //'none' // OPTIONAL no MAC; NOT RECOMMENDED - ]; - - $compression_algorithms = [ - 'none' // REQUIRED no compression - //'zlib' // OPTIONAL ZLIB (LZ77) compression - ]; - - // some SSH servers have buggy implementations of some of the above algorithms - switch ($this->server_identifier) { - case 'SSH-2.0-SSHD': - $mac_algorithms = array_values(array_diff( - $mac_algorithms, - ['hmac-sha1-96', 'hmac-md5-96'] - )); - } - - $str_kex_algorithms = implode(',', $kex_algorithms); - $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms); - $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms); - $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms); - $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms); - - $client_cookie = Random::string(16); - - $response = $kexinit_payload_server; - Strings::shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT) - $server_cookie = Strings::shift($response, 16); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->kex_algorithms = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->server_host_key_algorithms = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->encryption_algorithms_client_to_server = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->encryption_algorithms_server_to_client = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->mac_algorithms_client_to_server = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->mac_algorithms_server_to_client = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->compression_algorithms_client_to_server = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->compression_algorithms_server_to_client = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->languages_client_to_server = explode(',', Strings::shift($response, $temp['length'])); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->languages_server_to_client = explode(',', Strings::shift($response, $temp['length'])); - - if (!strlen($response)) { - return false; - } - extract(unpack('Cfirst_kex_packet_follows', Strings::shift($response, 1))); - - $first_kex_packet_follows = $first_kex_packet_follows != 0; - - // the sending of SSH2_MSG_KEXINIT could go in one of two places. this is the second place. - $kexinit_payload_client = pack( - 'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN', - NET_SSH2_MSG_KEXINIT, - $client_cookie, - strlen($str_kex_algorithms), - $str_kex_algorithms, - strlen($str_server_host_key_algorithms), - $str_server_host_key_algorithms, - strlen($encryption_algorithms_client_to_server), - $encryption_algorithms_client_to_server, - strlen($encryption_algorithms_server_to_client), - $encryption_algorithms_server_to_client, - strlen($mac_algorithms_client_to_server), - $mac_algorithms_client_to_server, - strlen($mac_algorithms_server_to_client), - $mac_algorithms_server_to_client, - strlen($compression_algorithms_client_to_server), - $compression_algorithms_client_to_server, - strlen($compression_algorithms_server_to_client), - $compression_algorithms_server_to_client, - 0, - '', - 0, - '', - 0, - 0 - ); - - if (!$this->send_binary_packet($kexinit_payload_client)) { - return false; - } - // here ends the second place. - - // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange - - // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the - // diffie-hellman key exchange as fast as possible - $decrypt = $this->array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client); - $decryptKeyLength = $this->encryption_algorithm_to_key_size($decrypt); - if ($decryptKeyLength === null) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found'); - } - - $encrypt = $this->array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server); - $encryptKeyLength = $this->encryption_algorithm_to_key_size($encrypt); - if ($encryptKeyLength === null) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found'); - } - - // through diffie-hellman key exchange a symmetric key is obtained - $kex_algorithm = $this->array_intersect_first($kex_algorithms, $this->kex_algorithms); - if ($kex_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found'); - } - - // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty. - $exchange_hash_rfc4419 = ''; - - if ($kex_algorithm === 'curve25519-sha256@libssh.org') { - $x = Random::string(32); - $eBytes = \Sodium\crypto_box_publickey_from_secretkey($x); - $clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT; - $serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY; - $kexHash = new Hash('sha256'); - } else { - if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) { - $dh_group_sizes_packed = pack( - 'NNN', - $this->kex_dh_group_size_min, - $this->kex_dh_group_size_preferred, - $this->kex_dh_group_size_max - ); - $packet = pack( - 'Ca*', - NET_SSH2_MSG_KEXDH_GEX_REQUEST, - $dh_group_sizes_packed - ); - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - user_error('Connection closed by server'); - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) { - user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP'); - return false; - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('NprimeLength', Strings::shift($response, 4))); - $primeBytes = Strings::shift($response, $primeLength); - $prime = new BigInteger($primeBytes, -256); - - if (strlen($response) < 4) { - return false; - } - extract(unpack('NgLength', Strings::shift($response, 4))); - $gBytes = Strings::shift($response, $gLength); - $g = new BigInteger($gBytes, -256); - - $exchange_hash_rfc4419 = pack( - 'a*Na*Na*', - $dh_group_sizes_packed, - $primeLength, - $primeBytes, - $gLength, - $gBytes - ); - - $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT; - $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY; - } else { - switch ($kex_algorithm) { - // see http://tools.ietf.org/html/rfc2409#section-6.2 and - // http://tools.ietf.org/html/rfc2412, appendex E - case 'diffie-hellman-group1-sha1': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'; - break; - // see http://tools.ietf.org/html/rfc3526#section-3 - case 'diffie-hellman-group14-sha1': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'; - break; - } - // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1 - // the generator field element is 2 (decimal) and the hash function is sha1. - $g = new BigInteger(2); - $prime = new BigInteger($prime, 16); - $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT; - $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY; - } - - switch ($kex_algorithm) { - case 'diffie-hellman-group-exchange-sha256': - $kexHash = new Hash('sha256'); - break; - default: - $kexHash = new Hash('sha1'); - } - - /* To increase the speed of the key exchange, both client and server may - reduce the size of their private exponents. It should be at least - twice as long as the key material that is generated from the shared - secret. For more details, see the paper by van Oorschot and Wiener - [VAN-OORSCHOT]. - - -- http://tools.ietf.org/html/rfc4419#section-6.2 */ - $one = new BigInteger(1); - $keyLength = min($kexHash->getLengthInBytes(), max($encryptKeyLength, $decryptKeyLength)); - $max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength - $max = $max->subtract($one); - - $x = BigInteger::randomRange($one, $max); - $e = $g->modPow($x, $prime); - - $eBytes = $e->toBytes(true); - } - $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes); - - if (!$this->send_binary_packet($data)) { - throw new \RuntimeException('Connection closed by server'); - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - if ($type != $serverKexReplyMessage) { - throw new \UnexpectedValueException('Expected SSH_MSG_KEXDH_REPLY'); - } - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->server_public_host_key = $server_public_host_key = Strings::shift($response, $temp['length']); - - if (strlen($server_public_host_key) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($server_public_host_key, 4)); - $public_key_format = Strings::shift($server_public_host_key, $temp['length']); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $fBytes = Strings::shift($response, $temp['length']); - - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($response, 4)); - $this->signature = Strings::shift($response, $temp['length']); - - if (strlen($this->signature) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($this->signature, 4)); - $this->signature_format = Strings::shift($this->signature, $temp['length']); - - if ($kex_algorithm === 'curve25519-sha256@libssh.org') { - if (strlen($fBytes) !== 32) { - user_error('Received curve25519 public key of invalid length.'); - return false; - } - $key = new BigInteger(\Sodium\crypto_scalarmult($x, $fBytes), 256); - \Sodium\memzero($x); - } else { - $f = new BigInteger($fBytes, -256); - $key = $f->modPow($x, $prime); - } - $keyBytes = $key->toBytes(true); - - $this->exchange_hash = pack( - 'Na*Na*Na*Na*Na*a*Na*Na*Na*', - strlen($this->identifier), - $this->identifier, - strlen($this->server_identifier), - $this->server_identifier, - strlen($kexinit_payload_client), - $kexinit_payload_client, - strlen($kexinit_payload_server), - $kexinit_payload_server, - strlen($this->server_public_host_key), - $this->server_public_host_key, - $exchange_hash_rfc4419, - strlen($eBytes), - $eBytes, - strlen($fBytes), - $fBytes, - strlen($keyBytes), - $keyBytes - ); - - $this->exchange_hash = $kexHash->hash($this->exchange_hash); - - if ($this->session_id === false) { - $this->session_id = $this->exchange_hash; - } - - $server_host_key_algorithm = $this->array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms); - if ($server_host_key_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found'); - } - - if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Server Host Key Algorithm Mismatch'); - } - - $packet = pack( - 'C', - NET_SSH2_MSG_NEWKEYS - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - if ($type != NET_SSH2_MSG_NEWKEYS) { - throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS'); - } - - $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); - - $this->encrypt = $this->encryption_algorithm_to_crypt_instance($encrypt); - if ($this->encrypt) { - if ($this->crypto_engine) { - $this->encrypt->setEngine($this->crypto_engine); - } - if ($this->encrypt->getBlockLengthInBytes()) { - $this->encrypt_block_size = $this->encrypt->getBlockLengthInBytes(); - } - $this->encrypt->enableContinuousBuffer(); - $this->encrypt->disablePadding(); - - if ($this->encrypt->usesIV()) { - $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id); - while ($this->encrypt_block_size > strlen($iv)) { - $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); - } - $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size)); - } - - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id); - while ($encryptKeyLength > strlen($key)) { - $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - $this->encrypt->setKey(substr($key, 0, $encryptKeyLength)); - } - - $this->decrypt = $this->encryption_algorithm_to_crypt_instance($decrypt); - if ($this->decrypt) { - if ($this->crypto_engine) { - $this->decrypt->setEngine($this->crypto_engine); - } - if ($this->decrypt->getBlockLengthInBytes()) { - $this->decrypt_block_size = $this->decrypt->getBlockLengthInBytes(); - } - $this->decrypt->enableContinuousBuffer(); - $this->decrypt->disablePadding(); - - if ($this->decrypt->usesIV()) { - $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id); - while ($this->decrypt_block_size > strlen($iv)) { - $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); - } - $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size)); - } - - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id); - while ($decryptKeyLength > strlen($key)) { - $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - $this->decrypt->setKey(substr($key, 0, $decryptKeyLength)); - } - - /* The "arcfour128" algorithm is the RC4 cipher, as described in - [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream - generated by the cipher MUST be discarded, and the first byte of the - first encrypted packet MUST be encrypted using the 1537th byte of - keystream. - - -- http://tools.ietf.org/html/rfc4345#section-4 */ - if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') { - $this->encrypt->encrypt(str_repeat("\0", 1536)); - } - if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') { - $this->decrypt->decrypt(str_repeat("\0", 1536)); - } - - $mac_algorithm = $this->array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server); - if ($mac_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found'); - } - - $createKeyLength = 0; // ie. $mac_algorithm == 'none' - switch ($mac_algorithm) { - case 'hmac-sha2-256': - $this->hmac_create = new Hash('sha256'); - $createKeyLength = 32; - break; - case 'hmac-sha1': - $this->hmac_create = new Hash('sha1'); - $createKeyLength = 20; - break; - case 'hmac-sha1-96': - $this->hmac_create = new Hash('sha1-96'); - $createKeyLength = 20; - break; - case 'hmac-md5': - $this->hmac_create = new Hash('md5'); - $createKeyLength = 16; - break; - case 'hmac-md5-96': - $this->hmac_create = new Hash('md5-96'); - $createKeyLength = 16; - } - - $mac_algorithm = $this->array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client); - if ($mac_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found'); - } - - $checkKeyLength = 0; - $this->hmac_size = 0; - switch ($mac_algorithm) { - case 'hmac-sha2-256': - $this->hmac_check = new Hash('sha256'); - $checkKeyLength = 32; - $this->hmac_size = 32; - break; - case 'hmac-sha1': - $this->hmac_check = new Hash('sha1'); - $checkKeyLength = 20; - $this->hmac_size = 20; - break; - case 'hmac-sha1-96': - $this->hmac_check = new Hash('sha1-96'); - $checkKeyLength = 20; - $this->hmac_size = 12; - break; - case 'hmac-md5': - $this->hmac_check = new Hash('md5'); - $checkKeyLength = 16; - $this->hmac_size = 16; - break; - case 'hmac-md5-96': - $this->hmac_check = new Hash('md5-96'); - $checkKeyLength = 16; - $this->hmac_size = 12; - } - - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id); - while ($createKeyLength > strlen($key)) { - $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - $this->hmac_create->setKey(substr($key, 0, $createKeyLength)); - - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id); - while ($checkKeyLength > strlen($key)) { - $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - $this->hmac_check->setKey(substr($key, 0, $checkKeyLength)); - - $compression_algorithm = $this->array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client); - if ($compression_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found'); - } - $this->decompress = $compression_algorithm == 'zlib'; - - $compression_algorithm = $this->array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server); - if ($compression_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found'); - } - $this->compress = $compression_algorithm == 'zlib'; - - return true; - } - - /** - * Maps an encryption algorithm name to the number of key bytes. - * - * @param string $algorithm Name of the encryption algorithm - * @return int|null Number of bytes as an integer or null for unknown - * @access private - */ - private function encryption_algorithm_to_key_size($algorithm) - { - switch ($algorithm) { - case 'none': - return 0; - case 'aes128-cbc': - case 'aes128-ctr': - case 'arcfour': - case 'arcfour128': - case 'blowfish-cbc': - case 'blowfish-ctr': - case 'twofish128-cbc': - case 'twofish128-ctr': - return 16; - case '3des-cbc': - case '3des-ctr': - case 'aes192-cbc': - case 'aes192-ctr': - case 'twofish192-cbc': - case 'twofish192-ctr': - return 24; - case 'aes256-cbc': - case 'aes256-ctr': - case 'arcfour256': - case 'twofish-cbc': - case 'twofish256-cbc': - case 'twofish256-ctr': - return 32; - } - return null; - } - - /** - * Maps an encryption algorithm name to an instance of a subclass of - * \phpseclib\Crypt\Base. - * - * @param string $algorithm Name of the encryption algorithm - * @return mixed Instance of \phpseclib\Crypt\Base or null for unknown - * @access private - */ - private function encryption_algorithm_to_crypt_instance($algorithm) - { - switch ($algorithm) { - case '3des-cbc': - return new TripleDES(BlockCipher::MODE_CBC); - case '3des-ctr': - return new TripleDES(BlockCipher::MODE_CTR); - case 'aes256-cbc': - case 'aes192-cbc': - case 'aes128-cbc': - return new Rijndael(BlockCipher::MODE_CBC); - case 'aes256-ctr': - case 'aes192-ctr': - case 'aes128-ctr': - return new Rijndael(BlockCipher::MODE_CTR); - case 'blowfish-cbc': - return new Blowfish(BlockCipher::MODE_CBC); - case 'blowfish-ctr': - return new Blowfish(BlockCipher::MODE_CTR); - case 'twofish128-cbc': - case 'twofish192-cbc': - case 'twofish256-cbc': - case 'twofish-cbc': - return new Twofish(BlockCipher::MODE_CBC); - case 'twofish128-ctr': - case 'twofish192-ctr': - case 'twofish256-ctr': - return new Twofish(BlockCipher::MODE_CTR); - case 'arcfour': - case 'arcfour128': - case 'arcfour256': - return new RC4(); - } - return null; - } - - /** - * Login - * - * The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array - * - * @param string $username - * @param mixed $password - * @param mixed $... - * @return bool - * @see self::_login() - * @access public - */ - public function login($username) - { - $args = func_get_args(); - return call_user_func_array([&$this, 'sublogin'], $args); - } - - /** - * Login Helper - * - * @param string $username - * @param mixed $password - * @param mixed $... - * @return bool - * @see self::_login_helper() - * @access private - */ - protected function sublogin($username) - { - if (!($this->bitmap & self::MASK_CONSTRUCTOR)) { - if (!$this->connect()) { - return false; - } - } - - $args = array_slice(func_get_args(), 1); - if (empty($args)) { - return $this->login_helper($username); - } - - foreach ($args as $arg) { - if ($this->login_helper($username, $arg)) { - return true; - } - } - return false; - } - - /** - * Login Helper - * - * @param string $username - * @param string $password - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @access private - * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} - * by sending dummy SSH_MSG_IGNORE messages. - */ - private function login_helper($username, $password = null) - { - if (!($this->bitmap & self::MASK_CONNECTED)) { - return false; - } - - if (!($this->bitmap & self::MASK_LOGIN_REQ)) { - $packet = pack( - 'CNa*', - NET_SSH2_MSG_SERVICE_REQUEST, - strlen('ssh-userauth'), - 'ssh-userauth' - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) { - throw new \UnexpectedValueException('Expected SSH_MSG_SERVICE_ACCEPT'); - } - $this->bitmap |= self::MASK_LOGIN_REQ; - } - - if (strlen($this->last_interactive_response)) { - return !is_string($password) && !is_array($password) ? false : $this->keyboard_interactive_process($password); - } - - if ($password instanceof RSA) { - return $this->privatekey_login($username, $password); - } elseif ($password instanceof Agent) { - return $this->ssh_agent_login($username, $password); - } - - if (is_array($password)) { - if ($this->keyboard_interactive_login($username, $password)) { - $this->bitmap |= self::MASK_LOGIN; - return true; - } - return false; - } - - if (!isset($password)) { - $packet = pack( - 'CNa*Na*Na*', - NET_SSH2_MSG_USERAUTH_REQUEST, - strlen($username), - $username, - strlen('ssh-connection'), - 'ssh-connection', - strlen('none'), - 'none' - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - switch ($type) { - case NET_SSH2_MSG_USERAUTH_SUCCESS: - $this->bitmap |= self::MASK_LOGIN; - return true; - //case NET_SSH2_MSG_USERAUTH_FAILURE: - default: - return false; - } - } - - $packet = pack( - 'CNa*Na*Na*CNa*', - NET_SSH2_MSG_USERAUTH_REQUEST, - strlen($username), - $username, - strlen('ssh-connection'), - 'ssh-connection', - strlen('password'), - 'password', - 0, - strlen($password), - $password - ); - - // remove the username and password from the logged packet - if (!defined('NET_SSH2_LOGGING')) { - $logged = null; - } else { - $logged = pack( - 'CNa*Na*Na*CNa*', - NET_SSH2_MSG_USERAUTH_REQUEST, - strlen('username'), - 'username', - strlen('ssh-connection'), - 'ssh-connection', - strlen('password'), - 'password', - 0, - strlen('password'), - 'password' - ); - } - - if (!$this->send_binary_packet($packet, $logged)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - switch ($type) { - case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // in theory, the password can be changed - if (defined('NET_SSH2_LOGGING')) { - $this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'; - } - - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . utf8_decode(Strings::shift($response, $length)); - - return $this->disconnect_helper(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); - case NET_SSH2_MSG_USERAUTH_FAILURE: - // can we use keyboard-interactive authentication? if not then either the login is bad or the server employees - // multi-factor authentication - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $auth_methods = explode(',', Strings::shift($response, $length)); - if (!strlen($response)) { - return false; - } - extract(unpack('Cpartial_success', Strings::shift($response, 1))); - $partial_success = $partial_success != 0; - - if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) { - if ($this->keyboard_interactive_login($username, $password)) { - $this->bitmap |= self::MASK_LOGIN; - return true; - } - return false; - } - return false; - case NET_SSH2_MSG_USERAUTH_SUCCESS: - $this->bitmap |= self::MASK_LOGIN; - return true; - } - - return false; - } - - /** - * Login via keyboard-interactive authentication - * - * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator. - * - * @param string $username - * @param string $password - * @return bool - * @access private - */ - private function keyboard_interactive_login($username, $password) - { - $packet = pack( - 'CNa*Na*Na*Na*Na*', - NET_SSH2_MSG_USERAUTH_REQUEST, - strlen($username), - $username, - strlen('ssh-connection'), - 'ssh-connection', - strlen('keyboard-interactive'), - 'keyboard-interactive', - 0, - '', - 0, - '' - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - return $this->keyboard_interactive_process($password); - } - - /** - * Handle the keyboard-interactive requests / responses. - * - * @param string $responses... - * @return bool - * @throws \RuntimeException on connection error - * @access private - */ - private function keyboard_interactive_process() - { - $responses = func_get_args(); - - if (strlen($this->last_interactive_response)) { - $response = $this->last_interactive_response; - } else { - $orig = $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - } - - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - switch ($type) { - case NET_SSH2_MSG_USERAUTH_INFO_REQUEST: - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - Strings::shift($response, $length); // name; may be empty - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - Strings::shift($response, $length); // instruction; may be empty - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - Strings::shift($response, $length); // language tag; may be empty - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nnum_prompts', Strings::shift($response, 4))); - - for ($i = 0; $i < count($responses); $i++) { - if (is_array($responses[$i])) { - foreach ($responses[$i] as $key => $value) { - $this->keyboard_requests_responses[$key] = $value; - } - unset($responses[$i]); - } - } - $responses = array_values($responses); - - if (isset($this->keyboard_requests_responses)) { - for ($i = 0; $i < $num_prompts; $i++) { - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - // prompt - ie. "Password: "; must not be empty - $prompt = Strings::shift($response, $length); - //$echo = Strings::shift($response) != chr(0); - foreach ($this->keyboard_requests_responses as $key => $value) { - if (substr($prompt, 0, strlen($key)) == $key) { - $responses[] = $value; - break; - } - } - } - } - - // see http://tools.ietf.org/html/rfc4256#section-3.2 - if (strlen($this->last_interactive_response)) { - $this->last_interactive_response = ''; - } elseif (defined('NET_SSH2_LOGGING')) { - $this->message_number_log[count($this->message_number_log) - 1] = str_replace( - 'UNKNOWN', - 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', - $this->message_number_log[count($this->message_number_log) - 1] - ); - } - - if (!count($responses) && $num_prompts) { - $this->last_interactive_response = $orig; - return false; - } - - /* - After obtaining the requested information from the user, the client - MUST respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message. - */ - // see http://tools.ietf.org/html/rfc4256#section-3.4 - $packet = $logged = pack('CN', NET_SSH2_MSG_USERAUTH_INFO_RESPONSE, count($responses)); - for ($i = 0; $i < count($responses); $i++) { - $packet.= pack('Na*', strlen($responses[$i]), $responses[$i]); - $logged.= pack('Na*', strlen('dummy-answer'), 'dummy-answer'); - } - - if (!$this->send_binary_packet($packet, $logged)) { - return false; - } - - if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) { - $this->message_number_log[count($this->message_number_log) - 1] = str_replace( - 'UNKNOWN', - 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE', - $this->message_number_log[count($this->message_number_log) - 1] - ); - } - - /* - After receiving the response, the server MUST send either an - SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another - SSH_MSG_USERAUTH_INFO_REQUEST message. - */ - // maybe phpseclib should force close the connection after x request / responses? unless something like that is done - // there could be an infinite loop of request / responses. - return $this->keyboard_interactive_process(); - case NET_SSH2_MSG_USERAUTH_SUCCESS: - return true; - case NET_SSH2_MSG_USERAUTH_FAILURE: - return false; - } - - return false; - } - - /** - * Login with an ssh-agent provided key - * - * @param string $username - * @param \phpseclib\System\SSH\Agent $agent - * @return bool - * @access private - */ - private function ssh_agent_login($username, $agent) - { - $this->agent = $agent; - $keys = $agent->requestIdentities(); - foreach ($keys as $key) { - if ($this->privatekey_login($username, $key)) { - return true; - } - } - - return false; - } - - /** - * Login with an RSA private key - * - * @param string $username - * @param \phpseclib\Crypt\RSA $password - * @return bool - * @throws \RuntimeException on connection error - * @access private - * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} - * by sending dummy SSH_MSG_IGNORE messages. - */ - private function privatekey_login($username, $privatekey) - { - // see http://tools.ietf.org/html/rfc4253#page-15 - $publickey = $privatekey->getPublicKey('Raw'); - if ($publickey === false) { - return false; - } - - $publickey = [ - 'e' => $publickey['e']->toBytes(true), - 'n' => $publickey['n']->toBytes(true) - ]; - $publickey = pack( - 'Na*Na*Na*', - strlen('ssh-rsa'), - 'ssh-rsa', - strlen($publickey['e']), - $publickey['e'], - strlen($publickey['n']), - $publickey['n'] - ); - - $part1 = pack( - 'CNa*Na*Na*', - NET_SSH2_MSG_USERAUTH_REQUEST, - strlen($username), - $username, - strlen('ssh-connection'), - 'ssh-connection', - strlen('publickey'), - 'publickey' - ); - $part2 = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey), $publickey); - - $packet = $part1 . chr(0) . $part2; - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - switch ($type) { - case NET_SSH2_MSG_USERAUTH_FAILURE: - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . Strings::shift($response, $length); - - return false; - case NET_SSH2_MSG_USERAUTH_PK_OK: - // we'll just take it on faith that the public key blob and the public key algorithm name are as - // they should be - if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) { - $this->message_number_log[count($this->message_number_log) - 1] = str_replace( - 'UNKNOWN', - 'NET_SSH2_MSG_USERAUTH_PK_OK', - $this->message_number_log[count($this->message_number_log) - 1] - ); - } - } - - $packet = $part1 . chr(1) . $part2; - $privatekey->setHash('sha1'); - $signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet), RSA::PADDING_PKCS1); - $signature = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($signature), $signature); - $packet.= pack('Na*', strlen($signature), $signature); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - switch ($type) { - case NET_SSH2_MSG_USERAUTH_FAILURE: - // either the login is bad or the server employs multi-factor authentication - return false; - case NET_SSH2_MSG_USERAUTH_SUCCESS: - $this->bitmap |= self::MASK_LOGIN; - return true; - } - - return false; - } - - /** - * Set Timeout - * - * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout. - * Setting $timeout to false or 0 will mean there is no timeout. - * - * @param mixed $timeout - * @access public - */ - public function setTimeout($timeout) - { - $this->timeout = $this->curTimeout = $timeout; - } - - /** - * Get the output from stdError - * - * @access public - */ - public function getStdError() - { - return $this->stdErrorLog; - } - - /** - * Execute Command - * - * If $callback is set to false then \phpseclib\Net\SSH2::_get_channel_packet(self::CHANNEL_EXEC) will need to be called manually. - * In all likelihood, this is not a feature you want to be taking advantage of. - * - * @param string $command - * @param Callback $callback - * @return string - * @throws \RuntimeException on connection error - * @access public - */ - public function exec($command, $callback = null) - { - $this->curTimeout = $this->timeout; - $this->is_timeout = false; - $this->stdErrorLog = ''; - - if (!$this->isAuthenticated()) { - return false; - } - - if ($this->in_request_pty_exec) { - user_error('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.'); - return false; - } - - // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to - // be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but, - // honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway. - // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info - $this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size; - // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy - // uses 0x4000, that's what will be used here, as well. - $packet_size = 0x4000; - - $packet = pack( - 'CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, - strlen('session'), - 'session', - self::CHANNEL_EXEC, - $this->window_size_server_to_client[self::CHANNEL_EXEC], - $packet_size - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN; - - $response = $this->get_channel_packet(self::CHANNEL_EXEC); - if ($response === false) { - return false; - } - - if ($this->request_pty === true) { - $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); - $packet = pack( - 'CNNa*CNa*N5a*', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_EXEC], - strlen('pty-req'), - 'pty-req', - 1, - strlen('vt100'), - 'vt100', - $this->windowColumns, - $this->windowRows, - 0, - 0, - strlen($terminal_modes), - $terminal_modes - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response)) { - return false; - } - list(, $type) = unpack('C', Strings::shift($response, 1)); - - switch ($type) { - case NET_SSH2_MSG_CHANNEL_SUCCESS: - break; - case NET_SSH2_MSG_CHANNEL_FAILURE: - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to request pseudo-terminal'); - } - $this->in_request_pty_exec = true; - } - - // sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things - // down. the one place where it might be desirable is if you're doing something like \phpseclib\Net\SSH2::exec('ping localhost &'). - // with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then - // then immediately terminate. without such a request exec() will loop indefinitely. the ping process won't end but - // neither will your script. - - // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by - // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the - // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates. - $packet = pack( - 'CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_EXEC], - strlen('exec'), - 'exec', - 1, - strlen($command), - $command - ); - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->get_channel_packet(self::CHANNEL_EXEC); - if ($response === false) { - return false; - } - - $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA; - - if ($callback === false || $this->in_request_pty_exec) { - return true; - } - - $output = ''; - while (true) { - $temp = $this->get_channel_packet(self::CHANNEL_EXEC); - switch (true) { - case $temp === true: - return is_callable($callback) ? true : $output; - case $temp === false: - return false; - default: - if (is_callable($callback)) { - if (call_user_func($callback, $temp) === true) { - $this->close_channel(self::CHANNEL_EXEC); - return true; - } - } else { - $output.= $temp; - } - } - } - } - - /** - * Creates an interactive shell - * - * @see self::read() - * @see self::write() - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @access private - */ - private function initShell() - { - if ($this->in_request_pty_exec === true) { - return true; - } - - $this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size; - $packet_size = 0x4000; - - $packet = pack( - 'CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, - strlen('session'), - 'session', - self::CHANNEL_SHELL, - $this->window_size_server_to_client[self::CHANNEL_SHELL], - $packet_size - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN; - - $response = $this->get_channel_packet(self::CHANNEL_SHELL); - if ($response === false) { - return false; - } - - $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); - $packet = pack( - 'CNNa*CNa*N5a*', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_SHELL], - strlen('pty-req'), - 'pty-req', - 1, - strlen('vt100'), - 'vt100', - $this->windowColumns, - $this->windowRows, - 0, - 0, - strlen($terminal_modes), - $terminal_modes - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - - if (!strlen($response)) { - return false; - } - list(, $type) = unpack('C', Strings::shift($response, 1)); - - switch ($type) { - case NET_SSH2_MSG_CHANNEL_SUCCESS: - // if a pty can't be opened maybe commands can still be executed - case NET_SSH2_MSG_CHANNEL_FAILURE: - break; - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \UnexpectedValueException('Unable to request pseudo-terminal'); - } - - $packet = pack( - 'CNNa*C', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_SHELL], - strlen('shell'), - 'shell', - 1 - ); - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->get_channel_packet(self::CHANNEL_SHELL); - if ($response === false) { - return false; - } - - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA; - - $this->bitmap |= self::MASK_SHELL; - - return true; - } - - /** - * Return the channel to be used with read() / write() - * - * @see self::read() - * @see self::write() - * @return int - * @access public - */ - private function get_interactive_channel() - { - switch (true) { - case $this->in_subsystem: - return self::CHANNEL_SUBSYSTEM; - case $this->in_request_pty_exec: - return self::CHANNEL_EXEC; - default: - return self::CHANNEL_SHELL; - } - } - - /** - * Return an available open channel - * - * @return int - * @access public - */ - private function get_open_channel() - { - $channel = self::CHANNEL_EXEC; - do { - if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) { - return $channel; - } - } while ($channel++ < self::CHANNEL_SUBSYSTEM); - - return false; - } - - /** - * Returns the output of an interactive shell - * - * Returns when there's a match for $expect, which can take the form of a string literal or, - * if $mode == self::READ_REGEX, a regular expression. - * - * @see self::write() - * @param string $expect - * @param int $mode - * @return string - * @throws \RuntimeException on connection error - * @access public - */ - public function read($expect = '', $mode = self::READ_SIMPLE) - { - $this->curTimeout = $this->timeout; - $this->is_timeout = false; - - if (!$this->isAuthenticated()) { - throw new \RuntimeException('Operation disallowed prior to login()'); - } - - if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); - } - - $channel = $this->get_interactive_channel(); - - $match = $expect; - while (true) { - if ($mode == self::READ_REGEX) { - preg_match($expect, substr($this->interactiveBuffer, -1024), $matches); - $match = isset($matches[0]) ? $matches[0] : ''; - } - $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false; - if ($pos !== false) { - return Strings::shift($this->interactiveBuffer, $pos + strlen($match)); - } - $response = $this->get_channel_packet($channel); - if (is_bool($response)) { - $this->in_request_pty_exec = false; - return $response ? Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer)) : false; - } - - $this->interactiveBuffer.= $response; - } - } - - /** - * Inputs a command into an interactive shell. - * - * @see self::read() - * @param string $cmd - * @return bool - * @throws \RuntimeException on connection error - * @access public - */ - public function write($cmd) - { - if (!$this->isAuthenticated()) { - throw new \RuntimeException('Operation disallowed prior to login()'); - } - - if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); - } - - return $this->send_channel_packet($this->get_interactive_channel(), $cmd); - } - - /** - * Start a subsystem. - * - * Right now only one subsystem at a time is supported. To support multiple subsystem's stopSubsystem() could accept - * a string that contained the name of the subsystem, but at that point, only one subsystem of each type could be opened. - * To support multiple subsystem's of the same name maybe it'd be best if startSubsystem() generated a new channel id and - * returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented - * if there's sufficient demand for such a feature. - * - * @see self::stopSubsystem() - * @param string $subsystem - * @return bool - * @access public - */ - public function startSubsystem($subsystem) - { - $this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size; - - $packet = pack( - 'CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, - strlen('session'), - 'session', - self::CHANNEL_SUBSYSTEM, - $this->window_size, - 0x4000 - ); - - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN; - - $response = $this->get_channel_packet(self::CHANNEL_SUBSYSTEM); - if ($response === false) { - return false; - } - - $packet = pack( - 'CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_SUBSYSTEM], - strlen('subsystem'), - 'subsystem', - 1, - strlen($subsystem), - $subsystem - ); - if (!$this->send_binary_packet($packet)) { - return false; - } - - $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->get_channel_packet(self::CHANNEL_SUBSYSTEM); - - if ($response === false) { - return false; - } - - $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA; - - $this->bitmap |= self::MASK_SHELL; - $this->in_subsystem = true; - - return true; - } - - /** - * Stops a subsystem. - * - * @see self::startSubsystem() - * @return bool - * @access public - */ - public function stopSubsystem() - { - $this->in_subsystem = false; - $this->close_channel(self::CHANNEL_SUBSYSTEM); - return true; - } - - /** - * Closes a channel - * - * If read() timed out you might want to just close the channel and have it auto-restart on the next read() call - * - * @access public - */ - public function reset() - { - $this->close_channel($this->get_interactive_channel()); - } - - /** - * Is timeout? - * - * Did exec() or read() return because they timed out or because they encountered the end? - * - * @access public - */ - public function isTimeout() - { - return $this->is_timeout; - } - - /** - * Disconnect - * - * @access public - */ - public function disconnect() - { - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) { - fclose($this->realtime_log_file); - } - unset(self::$connections[$this->getResourceId()]); - } - - /** - * Destructor. - * - * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call - * disconnect(). - * - * @access public - */ - public function __destruct() - { - $this->disconnect(); - } - - /** - * Is the connection still active? - * - * @return bool - * @access public - */ - public function isConnected() - { - return (bool) ($this->bitmap & self::MASK_CONNECTED); - } - - /** - * Have you successfully been logged in? - * - * @return bool - * @access public - */ - public function isAuthenticated() - { - return (bool) ($this->bitmap & self::MASK_LOGIN); - } - - /** - * Gets Binary Packets - * - * See '6. Binary Packet Protocol' of rfc4253 for more info. - * - * @see self::_send_binary_packet() - * @return string - * @throws \RuntimeException on connection errors - * @access private - */ - private function get_binary_packet() - { - if (!is_resource($this->fsock) || feof($this->fsock)) { - $this->bitmap = 0; - throw new \RuntimeException('Connection closed prematurely'); - } - - $start = microtime(true); - $raw = stream_get_contents($this->fsock, $this->decrypt_block_size); - - if (!strlen($raw)) { - return ''; - } - - if ($this->decrypt !== false) { - $raw = $this->decrypt->decrypt($raw); - } - - if (strlen($raw) < 5) { - return false; - } - extract(unpack('Npacket_length/Cpadding_length', Strings::shift($raw, 5))); - - $remaining_length = $packet_length + 4 - $this->decrypt_block_size; - - // quoting , - // "implementations SHOULD check that the packet length is reasonable" - // PuTTY uses 0x9000 as the actual max packet size and so to shall we - if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) { - throw new \RuntimeException('Invalid size'); - } - - $buffer = ''; - while ($remaining_length > 0) { - $temp = stream_get_contents($this->fsock, $remaining_length); - if ($temp === false || feof($this->fsock)) { - $this->bitmap = 0; - throw new \RuntimeException('Error reading from socket'); - } - $buffer.= $temp; - $remaining_length-= strlen($temp); - } - $stop = microtime(true); - if (strlen($buffer)) { - $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer; - } - - $payload = Strings::shift($raw, $packet_length - $padding_length - 1); - $padding = Strings::shift($raw, $padding_length); // should leave $raw empty - - if ($this->hmac_check !== false) { - $hmac = stream_get_contents($this->fsock, $this->hmac_size); - if ($hmac === false || strlen($hmac) != $this->hmac_size) { - $this->bitmap = 0; - throw new \RuntimeException('Error reading socket'); - } elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) { - throw new \RuntimeException('Invalid HMAC'); - } - } - - //if ($this->decompress) { - // $payload = gzinflate(substr($payload, 2)); - //} - - $this->get_seq_no++; - - if (defined('NET_SSH2_LOGGING')) { - $current = microtime(true); - $message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')'; - $message_number = '<- ' . $message_number . - ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; - $this->append_log($message_number, $payload); - $this->last_packet = $current; - } - - return $this->filter($payload); - } - - /** - * Filter Binary Packets - * - * Because some binary packets need to be ignored... - * - * @see self::_get_binary_packet() - * @return string - * @access private - */ - private function filter($payload) - { - switch (ord($payload[0])) { - case NET_SSH2_MSG_DISCONNECT: - Strings::shift($payload, 1); - if (strlen($payload) < 8) { - return false; - } - extract(unpack('Nreason_code/Nlength', Strings::shift($payload, 8))); - $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode(Strings::shift($payload, $length)); - $this->bitmap = 0; - return false; - case NET_SSH2_MSG_IGNORE: - $payload = $this->get_binary_packet(); - break; - case NET_SSH2_MSG_DEBUG: - Strings::shift($payload, 2); - if (strlen($payload) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($payload, 4))); - $this->errors[] = 'SSH_MSG_DEBUG: ' . utf8_decode(Strings::shift($payload, $length)); - $payload = $this->get_binary_packet(); - break; - case NET_SSH2_MSG_UNIMPLEMENTED: - return false; - case NET_SSH2_MSG_KEXINIT: - if ($this->session_id !== false) { - if (!$this->key_exchange($payload)) { - $this->bitmap = 0; - return false; - } - $payload = $this->get_binary_packet(); - } - } - - // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in - if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) { - Strings::shift($payload, 1); - if (strlen($payload) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($payload, 4))); - $this->banner_message = utf8_decode(Strings::shift($payload, $length)); - $payload = $this->get_binary_packet(); - } - - // only called when we've already logged in - if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) { - switch (ord($payload[0])) { - case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4 - if (strlen($payload) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($payload, 4))); - $this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . Strings::shift($payload, $length); - - if (!$this->send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) { - return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - } - - $payload = $this->get_binary_packet(); - break; - case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1 - Strings::shift($payload, 1); - if (strlen($payload) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($payload, 4))); - $data = Strings::shift($payload, $length); - if (strlen($payload) < 4) { - return false; - } - extract(unpack('Nserver_channel', Strings::shift($payload, 4))); - switch ($data) { - case 'auth-agent': - case 'auth-agent@openssh.com': - if (isset($this->agent)) { - $new_channel = self::CHANNEL_AGENT_FORWARD; - - if (strlen($payload) < 8) { - return false; - } - extract(unpack('Nremote_window_size', Strings::shift($payload, 4))); - extract(unpack('Nremote_maximum_packet_size', Strings::shift($payload, 4))); - - $this->packet_size_client_to_server[$new_channel] = $remote_window_size; - $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size; - $this->window_size_client_to_server[$new_channel] = $this->window_size; - - $packet_size = 0x4000; - - $packet = pack( - 'CN4', - NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, - $server_channel, - $new_channel, - $packet_size, - $packet_size - ); - - $this->server_channels[$new_channel] = $server_channel; - $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION; - if (!$this->send_binary_packet($packet)) { - return false; - } - } - break; - default: - $packet = pack( - 'CN3a*Na*', - NET_SSH2_MSG_REQUEST_FAILURE, - $server_channel, - NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, - 0, - '', - 0, - '' - ); - - if (!$this->send_binary_packet($packet)) { - return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - } - } - $payload = $this->get_binary_packet(); - break; - case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST: - Strings::shift($payload, 1); - if (strlen($payload) < 8) { - return false; - } - extract(unpack('Nchannel', Strings::shift($payload, 4))); - extract(unpack('Nwindow_size', Strings::shift($payload, 4))); - - $this->window_size_client_to_server[$channel]+= $window_size; - - $payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? true : $this->get_binary_packet(); - } - } - - return $payload; - } - - /** - * Enable Quiet Mode - * - * Suppress stderr from output - * - * @access public - */ - public function enableQuietMode() - { - $this->quiet_mode = true; - } - - /** - * Disable Quiet Mode - * - * Show stderr in output - * - * @access public - */ - public function disableQuietMode() - { - $this->quiet_mode = false; - } - - /** - * Returns whether Quiet Mode is enabled or not - * - * @see self::enableQuietMode() - * @see self::disableQuietMode() - * @access public - * @return bool - */ - public function isQuietModeEnabled() - { - return $this->quiet_mode; - } - - /** - * Enable request-pty when using exec() - * - * @access public - */ - public function enablePTY() - { - $this->request_pty = true; - } - - /** - * Disable request-pty when using exec() - * - * @access public - */ - public function disablePTY() - { - if ($this->in_request_pty_exec) { - $this->_close_channel(self::CHANNEL_EXEC); - $this->in_request_pty_exec = false; - } - $this->request_pty = false; - } - - /** - * Returns whether request-pty is enabled or not - * - * @see self::enablePTY() - * @see self::disablePTY() - * @access public - * @return bool - */ - public function isPTYEnabled() - { - return $this->request_pty; - } - - /** - * Gets channel data - * - * Returns the data as a string if it's available and false if not. - * - * @param $client_channel - * @return mixed - * @throws \RuntimeException on connection error - * @access private - */ - protected function get_channel_packet($client_channel, $skip_extended = false) - { - if (!empty($this->channel_buffers[$client_channel])) { - return array_shift($this->channel_buffers[$client_channel]); - } - - while (true) { - if ($this->curTimeout) { - if ($this->curTimeout < 0) { - $this->is_timeout = true; - return true; - } - - $read = [$this->fsock]; - $write = $except = null; - - $start = microtime(true); - $sec = floor($this->curTimeout); - $usec = 1000000 * ($this->curTimeout - $sec); - // on windows this returns a "Warning: Invalid CRT parameters detected" error - if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { - $this->is_timeout = true; - return true; - } - $elapsed = microtime(true) - $start; - $this->curTimeout-= $elapsed; - } - - $response = $this->get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - if ($client_channel == -1 && $response === true) { - return true; - } - if (!strlen($response)) { - return ''; - } - - if (!strlen($response)) { - return false; - } - extract(unpack('Ctype', Strings::shift($response, 1))); - - if (strlen($response) < 4) { - return false; - } - if ($type == NET_SSH2_MSG_CHANNEL_OPEN) { - extract(unpack('Nlength', Strings::shift($response, 4))); - } else { - extract(unpack('Nchannel', Strings::shift($response, 4))); - } - - // will not be setup yet on incoming channel open request - if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) { - $this->window_size_server_to_client[$channel]-= strlen($response); - - // resize the window, if appropriate - if ($this->window_size_server_to_client[$channel] < 0) { - $packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size); - if (!$this->send_binary_packet($packet)) { - return false; - } - $this->window_size_server_to_client[$channel]+= $this->window_size; - } - - switch ($this->channel_status[$channel]) { - case NET_SSH2_MSG_CHANNEL_OPEN: - switch ($type) { - case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nserver_channel', Strings::shift($response, 4))); - $this->server_channels[$channel] = $server_channel; - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nwindow_size', Strings::shift($response, 4))); - - if ($window_size < 0) { - $window_size&= 0x7FFFFFFF; - $window_size+= 0x80000000; - } - $this->window_size_client_to_server[$channel] = $window_size; - if (strlen($response) < 4) { - return false; - } - $temp = unpack('Npacket_size_client_to_server', Strings::shift($response, 4)); - - $this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server']; - $result = $client_channel == $channel ? true : $this->get_channel_packet($client_channel, $skip_extended); - $this->on_channel_open(); - return $result; - //case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE: - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to open channel'); - } - break; - case NET_SSH2_MSG_CHANNEL_REQUEST: - switch ($type) { - case NET_SSH2_MSG_CHANNEL_SUCCESS: - return true; - case NET_SSH2_MSG_CHANNEL_FAILURE: - return false; - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to fulfill channel request'); - } - case NET_SSH2_MSG_CHANNEL_CLOSE: - return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->get_channel_packet($client_channel, $skip_extended); - } - } - - // ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA - - switch ($type) { - case NET_SSH2_MSG_CHANNEL_DATA: - /* - if ($channel == self::CHANNEL_EXEC) { - // SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server - // this actually seems to make things twice as fast. more to the point, the message right after - // SSH_MSG_CHANNEL_DATA (usually SSH_MSG_IGNORE) won't block for as long as it would have otherwise. - // in OpenSSH it slows things down but only by a couple thousandths of a second. - $this->send_channel_packet($channel, chr(0)); - } - */ - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $data = Strings::shift($response, $length); - - if ($channel == self::CHANNEL_AGENT_FORWARD) { - $agent_response = Objects::callFunc($this->agent, 'forward_data', [$data]); - if (!is_bool($agent_response)) { - $this->send_channel_packet($channel, $agent_response); - } - break; - } - - if ($client_channel == $channel) { - return $data; - } - if (!isset($this->channel_buffers[$channel])) { - $this->channel_buffers[$channel] = []; - } - $this->channel_buffers[$channel][] = $data; - break; - case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA: - /* - if ($client_channel == self::CHANNEL_EXEC) { - $this->send_channel_packet($client_channel, chr(0)); - } - */ - // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR - if (strlen($response) < 8) { - return false; - } - extract(unpack('Ndata_type_code/Nlength', Strings::shift($response, 8))); - $data = Strings::shift($response, $length); - - $this->stdErrorLog.= $data; - if ($skip_extended || $this->quiet_mode) { - break; - } - if ($client_channel == $channel) { - return $data; - } - if (!isset($this->channel_buffers[$channel])) { - $this->channel_buffers[$channel] = []; - } - $this->channel_buffers[$channel][] = $data; - break; - case NET_SSH2_MSG_CHANNEL_REQUEST: - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $value = Strings::shift($response, $length); - switch ($value) { - case 'exit-signal': - Strings::shift($response, 1); - if (strlen($response) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($response, 4))); - $this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . Strings::shift($response, $length); - if (strlen($response) < 4) { - return false; - } - Strings::shift($response, 1); - extract(unpack('Nlength', Strings::shift($response, 4))); - if ($length) { - $this->errors[count($this->errors)].= "\r\n" . Strings::shift($response, $length); - } - - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); - - $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF; - - break; - case 'exit-status': - if (strlen($response) < 5) { - return false; - } - extract(unpack('Cfalse/Nexit_status', Strings::shift($response, 5))); - - $this->exit_status = $exit_status; - - // "The client MAY ignore these messages." - // -- http://tools.ietf.org/html/rfc4254#section-6.10 - - break; - default: - // "Some systems may not implement signals, in which case they SHOULD ignore this message." - // -- http://tools.ietf.org/html/rfc4254#section-6.9 - break; - } - break; - case NET_SSH2_MSG_CHANNEL_CLOSE: - $this->curTimeout = 0; - - if ($this->bitmap & self::MASK_SHELL) { - $this->bitmap&= ~self::MASK_SHELL; - } - if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); - } - - $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE; - if ($client_channel == $channel) { - return true; - } - case NET_SSH2_MSG_CHANNEL_EOF: - break; - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Error reading channel data'); - } - } - } - - /** - * Sends Binary Packets - * - * See '6. Binary Packet Protocol' of rfc4253 for more info. - * - * @param string $data - * @param string $logged - * @see self::_get_binary_packet() - * @return bool - * @access private - */ - protected function send_binary_packet($data, $logged = null) - { - if (!is_resource($this->fsock) || feof($this->fsock)) { - $this->bitmap = 0; - throw new \RuntimeException('Connection closed prematurely'); - } - - //if ($this->compress) { - // // the -4 removes the checksum: - // // http://php.net/function.gzcompress#57710 - // $data = substr(gzcompress($data), 0, -4); - //} - - // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9 - $packet_length = strlen($data) + 9; - // round up to the nearest $this->encrypt_block_size - $packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size; - // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length - $padding_length = $packet_length - strlen($data) - 5; - $padding = Random::string($padding_length); - - // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself - $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding); - - $hmac = $this->hmac_create !== false ? $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)) : ''; - $this->send_seq_no++; - - if ($this->encrypt !== false) { - $packet = $this->encrypt->encrypt($packet); - } - - $packet.= $hmac; - - $start = microtime(true); - $result = strlen($packet) == fputs($this->fsock, $packet); - $stop = microtime(true); - - if (defined('NET_SSH2_LOGGING')) { - $current = microtime(true); - $message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')'; - $message_number = '-> ' . $message_number . - ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; - $this->append_log($message_number, isset($logged) ? $logged : $data); - $this->last_packet = $current; - } - - return $result; - } - - /** - * Logs data packets - * - * Makes sure that only the last 1MB worth of packets will be logged - * - * @param string $data - * @access private - */ - private function append_log($message_number, $message) - { - // remove the byte identifying the message type from all but the first two messages (ie. the identification strings) - if (strlen($message_number) > 2) { - Strings::shift($message); - } - - switch (NET_SSH2_LOGGING) { - // useful for benchmarks - case self::LOG_SIMPLE: - $this->message_number_log[] = $message_number; - break; - // the most useful log for SSH2 - case self::LOG_COMPLEX: - $this->message_number_log[] = $message_number; - $this->log_size+= strlen($message); - $this->message_log[] = $message; - while ($this->log_size > self::LOG_MAX_SIZE) { - $this->log_size-= strlen(array_shift($this->message_log)); - array_shift($this->message_number_log); - } - break; - // dump the output out realtime; packets may be interspersed with non packets, - // passwords won't be filtered out and select other packets may not be correctly - // identified - case self::LOG_REALTIME: - switch (PHP_SAPI) { - case 'cli': - $start = $stop = "\r\n"; - break; - default: - $start = '
';
-                        $stop = '
'; - } - echo $start . $this->format_log([$message], [$message_number]) . $stop; - @flush(); - @ob_flush(); - break; - // basically the same thing as self::LOG_REALTIME with the caveat that NET_SFTP_LOG_REALTIME_FILENAME - // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE. - // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily - // at the beginning of the file - case self::LOG_REALTIME_FILE: - if (!isset($this->realtime_log_file)) { - // PHP doesn't seem to like using constants in fopen() - $filename = NET_SSH2_LOG_REALTIME_FILENAME; - $fp = fopen($filename, 'w'); - $this->realtime_log_file = $fp; - } - if (!is_resource($this->realtime_log_file)) { - break; - } - $entry = $this->format_log([$message], [$message_number]); - if ($this->realtime_log_wrap) { - $temp = "<<< START >>>\r\n"; - $entry.= $temp; - fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); - } - $this->realtime_log_size+= strlen($entry); - if ($this->realtime_log_size > self::LOG_MAX_SIZE) { - fseek($this->realtime_log_file, 0); - $this->realtime_log_size = strlen($entry); - $this->realtime_log_wrap = true; - } - fputs($this->realtime_log_file, $entry); - } - } - - /** - * Sends channel data - * - * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate - * - * @param int $client_channel - * @param string $data - * @return bool - * @access private - */ - protected function send_channel_packet($client_channel, $data) - { - while (strlen($data)) { - if (!$this->window_size_client_to_server[$client_channel]) { - $this->bitmap^= self::MASK_WINDOW_ADJUST; - // using an invalid channel will let the buffers be built up for the valid channels - $this->get_channel_packet(-1); - $this->bitmap^= self::MASK_WINDOW_ADJUST; - } - - /* The maximum amount of data allowed is determined by the maximum - packet size for the channel, and the current window size, whichever - is smaller. - -- http://tools.ietf.org/html/rfc4254#section-5.2 */ - $max_size = min( - $this->packet_size_client_to_server[$client_channel], - $this->window_size_client_to_server[$client_channel] - ); - - $temp = Strings::shift($data, $max_size); - $packet = pack( - 'CN2a*', - NET_SSH2_MSG_CHANNEL_DATA, - $this->server_channels[$client_channel], - strlen($temp), - $temp - ); - $this->window_size_client_to_server[$client_channel]-= strlen($temp); - if (!$this->send_binary_packet($packet)) { - return false; - } - } - - return true; - } - - /** - * Closes and flushes a channel - * - * \phpseclib\Net\SSH2 doesn't properly close most channels. For exec() channels are normally closed by the server - * and for SFTP channels are presumably closed when the client disconnects. This functions is intended - * for SCP more than anything. - * - * @param int $client_channel - * @param bool $want_reply - * @return bool - * @access private - */ - private function close_channel($client_channel, $want_reply = false) - { - // see http://tools.ietf.org/html/rfc4254#section-5.3 - - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - - if (!$want_reply) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); - } - - $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; - - $this->curTimeout = 0; - - while (!is_bool($this->get_channel_packet($client_channel))) { - } - - if ($want_reply) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); - } - - if ($this->bitmap & self::MASK_SHELL) { - $this->bitmap&= ~self::MASK_SHELL; - } - } - - /** - * Disconnect - * - * @param int $reason - * @return bool - * @access private - */ - private function disconnect_helper($reason) - { - if ($this->bitmap & self::MASK_CONNECTED) { - $data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, ''); - $this->send_binary_packet($data); - $this->bitmap = 0; - fclose($this->fsock); - return false; - } - } - - /** - * Define Array - * - * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of - * named constants from it, using the value as the name of the constant and the index as the value of the constant. - * If any of the constants that would be defined already exists, none of the constants will be defined. - * - * @param array $array - * @access private - */ - protected function define_array() - { - $args = func_get_args(); - foreach ($args as $arg) { - foreach ($arg as $key => $value) { - if (!defined($value)) { - define($value, $key); - } else { - break 2; - } - } - } - } - - /** - * Returns a log of the packets that have been sent and received. - * - * Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING') - * - * @access public - * @return array|false|string - */ - public function getLog() - { - if (!defined('NET_SSH2_LOGGING')) { - return false; - } - - switch (NET_SSH2_LOGGING) { - case self::LOG_SIMPLE: - return $this->message_number_log; - case self::LOG_COMPLEX: - $log = $this->_format_log($this->message_log, $this->message_number_log); - return PHP_SAPI == 'cli' ? $log : '
' . $log . '
'; - default: - return false; - } - } - - /** - * Formats a log for printing - * - * @param array $message_log - * @param array $message_number_log - * @access private - * @return string - */ - protected function format_log($message_log, $message_number_log) - { - $output = ''; - for ($i = 0; $i < count($message_log); $i++) { - $output.= $message_number_log[$i] . "\r\n"; - $current_log = $message_log[$i]; - $j = 0; - do { - if (strlen($current_log)) { - $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 '; - } - $fragment = Strings::shift($current_log, $this->log_short_width); - $hex = substr(preg_replace_callback('#.#s', [$this, 'format_log_helper'], $fragment), strlen($this->log_boundary)); - // replace non ASCII printable characters with dots - // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters - // also replace < with a . since < messes up the output on web browsers - $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); - $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n"; - $j++; - } while (strlen($current_log)); - $output.= "\r\n"; - } - - return $output; - } - - /** - * Helper function for _format_log - * - * For use with preg_replace_callback() - * - * @param array $matches - * @access private - * @return string - */ - private function format_log_helper($matches) - { - return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT); - } - - /** - * Helper function for agent->on_channel_open() - * - * Used when channels are created to inform agent - * of said channel opening. Must be called after - * channel open confirmation received - * - * @access private - */ - private function on_channel_open() - { - if (isset($this->agent)) { - Objects::callFunc($this->agent, 'on_channel_open', [$this]); - } - } - - /** - * Returns the first value of the intersection of two arrays or false if - * the intersection is empty. The order is defined by the first parameter. - * - * @param array $array1 - * @param array $array2 - * @return mixed False if intersection is empty, else intersected value. - * @access private - */ - private function array_intersect_first($array1, $array2) - { - foreach ($array1 as $value) { - if (in_array($value, $array2)) { - return $value; - } - } - return false; - } - - /** - * Returns all errors - * - * @return string[] - * @access public - */ - public function getErrors() - { - return $this->errors; - } - - /** - * Returns the last error - * - * @return string - * @access public - */ - public function getLastError() - { - $count = count($this->errors); - - if ($count > 0) { - return $this->errors[$count - 1]; - } - } - - /** - * Return the server identification. - * - * @return string - * @access public - */ - public function getServerIdentification() - { - $this->connect(); - - return $this->server_identifier; - } - - /** - * Return a list of the key exchange algorithms the server supports. - * - * @return array - * @access public - */ - public function getKexAlgorithms() - { - $this->connect(); - - return $this->kex_algorithms; - } - - /** - * Return a list of the host key (public key) algorithms the server supports. - * - * @return array - * @access public - */ - public function getServerHostKeyAlgorithms() - { - $this->connect(); - - return $this->server_host_key_algorithms; - } - - /** - * Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client. - * - * @return array - * @access public - */ - public function getEncryptionAlgorithmsClient2Server() - { - $this->connect(); - - return $this->encryption_algorithms_client_to_server; - } - - /** - * Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client. - * - * @return array - * @access public - */ - public function getEncryptionAlgorithmsServer2Client() - { - $this->connect(); - - return $this->encryption_algorithms_server_to_client; - } - - /** - * Return a list of the MAC algorithms the server supports, when receiving stuff from the client. - * - * @return array - * @access public - */ - public function getMACAlgorithmsClient2Server() - { - $this->connect(); - - return $this->mac_algorithms_client_to_server; - } - - /** - * Return a list of the MAC algorithms the server supports, when sending stuff to the client. - * - * @return array - * @access public - */ - public function getMACAlgorithmsServer2Client() - { - $this->connect(); - - return $this->mac_algorithms_server_to_client; - } - - /** - * Return a list of the compression algorithms the server supports, when receiving stuff from the client. - * - * @return array - * @access public - */ - public function getCompressionAlgorithmsClient2Server() - { - $this->connect(); - - return $this->compression_algorithms_client_to_server; - } - - /** - * Return a list of the compression algorithms the server supports, when sending stuff to the client. - * - * @return array - * @access public - */ - public function getCompressionAlgorithmsServer2Client() - { - $this->connect(); - - return $this->compression_algorithms_server_to_client; - } - - /** - * Return a list of the languages the server supports, when sending stuff to the client. - * - * @return array - * @access public - */ - public function getLanguagesServer2Client() - { - $this->connect(); - - return $this->languages_server_to_client; - } - - /** - * Return a list of the languages the server supports, when receiving stuff from the client. - * - * @return array - * @access public - */ - public function getLanguagesClient2Server() - { - $this->connect(); - - return $this->languages_client_to_server; - } - - /** - * Returns the banner message. - * - * Quoting from the RFC, "in some jurisdictions, sending a warning message before - * authentication may be relevant for getting legal protection." - * - * @return string - * @access public - */ - public function getBannerMessage() - { - return $this->banner_message; - } - - /** - * Returns the server public host key. - * - * Caching this the first time you connect to a server and checking the result on subsequent connections - * is recommended. Returns false if the server signature is not signed correctly with the public host key. - * - * @return mixed - * @throws \RuntimeException on badly formatted keys - * @throws \phpseclib\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format - * @access public - */ - public function getServerPublicHostKey() - { - if (!($this->bitmap & self::MASK_CONSTRUCTOR)) { - if (!$this->connect()) { - return false; - } - } - - $signature = $this->signature; - $server_public_host_key = $this->server_public_host_key; - - if (strlen($server_public_host_key) < 4) { - return false; - } - extract(unpack('Nlength', Strings::shift($server_public_host_key, 4))); - Strings::shift($server_public_host_key, $length); - - if ($this->signature_validated) { - return $this->bitmap ? - $this->signature_format . ' ' . Base64::encode($this->server_public_host_key) : - false; - } - - $this->signature_validated = true; - - switch ($this->signature_format) { - case 'ssh-dss': - $zero = new BigInteger(); - - if (strlen($server_public_host_key) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($server_public_host_key, 4)); - $p = new BigInteger(Strings::shift($server_public_host_key, $temp['length']), -256); - - if (strlen($server_public_host_key) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($server_public_host_key, 4)); - $q = new BigInteger(Strings::shift($server_public_host_key, $temp['length']), -256); - - if (strlen($server_public_host_key) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($server_public_host_key, 4)); - $g = new BigInteger(Strings::shift($server_public_host_key, $temp['length']), -256); - - if (strlen($server_public_host_key) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($server_public_host_key, 4)); - $y = new BigInteger(Strings::shift($server_public_host_key, $temp['length']), -256); - - /* The value for 'dss_signature_blob' is encoded as a string containing - r, followed by s (which are 160-bit integers, without lengths or - padding, unsigned, and in network byte order). */ - $temp = unpack('Nlength', Strings::shift($signature, 4)); - if ($temp['length'] != 40) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Invalid signature'); - } - - $r = new BigInteger(Strings::shift($signature, 20), 256); - $s = new BigInteger(Strings::shift($signature, 20), 256); - - switch (true) { - case $r->equals($zero): - case $r->compare($q) >= 0: - case $s->equals($zero): - case $s->compare($q) >= 0: - $this->disconnectHepler(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Invalid signature'); - } - - $w = $s->modInverse($q); - - $u1 = $w->multiply(new BigInteger(sha1($this->exchange_hash), 16)); - list(, $u1) = $u1->divide($q); - - $u2 = $w->multiply($r); - list(, $u2) = $u2->divide($q); - - $g = $g->modPow($u1, $p); - $y = $y->modPow($u2, $p); - - $v = $g->multiply($y); - list(, $v) = $v->divide($p); - list(, $v) = $v->divide($q); - - if (!$v->equals($r)) { - //user_error('Bad server signature'); - return $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - } - - break; - case 'ssh-rsa': - if (strlen($server_public_host_key) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($server_public_host_key, 4)); - $e = new BigInteger(Strings::shift($server_public_host_key, $temp['length']), -256); - - if (strlen($server_public_host_key) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($server_public_host_key, 4)); - $rawN = Strings::shift($server_public_host_key, $temp['length']); - $n = new BigInteger($rawN, -256); - $nLength = strlen(ltrim($rawN, "\0")); - - /* - if (strlen($signature) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($signature, 4)); - $signature = Strings::shift($signature, $temp['length']); - - $rsa = new RSA(); - $rsa->load(['e' => $e, 'n' => $n], 'raw'); - $rsa->setHash('sha1'); - if (!$rsa->verify($this->exchange_hash, $signature, RSA::PADDING_PKCS1)) { - //user_error('Bad server signature'); - return $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - } - */ - - if (strlen($signature) < 4) { - return false; - } - $temp = unpack('Nlength', Strings::shift($signature, 4)); - $s = new BigInteger(Strings::shift($signature, $temp['length']), 256); - - // validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the - // following URL: - // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf - - // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source. - - if ($s->compare(new BigInteger()) < 0 || $s->compare($n->subtract(new BigInteger(1))) > 0) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Invalid signature'); - } - - $s = $s->modPow($e, $n); - $s = $s->toBytes(); - - $h = pack('N4H*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, sha1($this->exchange_hash)); - $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h; - - if ($s != $h) { - //user_error('Bad server signature'); - return $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - } - break; - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - throw new NoSupportedAlgorithmsException('Unsupported signature format'); - } - - return $this->signature_format . ' ' . Base64::encode($this->server_public_host_key); - } - - /** - * Returns the exit status of an SSH command or false. - * - * @return false|int - * @access public - */ - public function getExitStatus() - { - if (is_null($this->exit_status)) { - return false; - } - return $this->exit_status; - } - - /** - * Returns the number of columns for the terminal window size. - * - * @return int - * @access public - */ - public function getWindowColumns() - { - return $this->windowColumns; - } - - /** - * Returns the number of rows for the terminal window size. - * - * @return int - * @access public - */ - public function getWindowRows() - { - return $this->windowRows; - } - - /** - * Sets the number of columns for the terminal window size. - * - * @param int $value - * @access public - */ - public function setWindowColumns($value) - { - $this->windowColumns = $value; - } - - /** - * Sets the number of rows for the terminal window size. - * - * @param int $value - * @access public - */ - public function setWindowRows($value) - { - $this->windowRows = $value; - } - - /** - * Sets the number of columns and rows for the terminal window size. - * - * @param int $columns - * @param int $rows - * @access public - */ - public function setWindowSize($columns = 80, $rows = 24) - { - $this->windowColumns = $columns; - $this->windowRows = $rows; - } - - /** - * To String Magic Method - * - * @return string - * @access public - */ - public function __toString() - { - return $this->getResourceId(); - } - - /** - * Get Resource ID - * - * We use {} because that symbols should not be in URL according to - * {@link http://tools.ietf.org/html/rfc3986#section-2 RFC}. - * It will safe us from any conflicts, because otherwise regexp will - * match all alphanumeric domains. - * - * @return string - */ - public function getResourceId() - { - return '{' . spl_object_hash($this) . '}'; - } - - /** - * Return existing connection - * - * @param string $id - * - * @return bool|SSH2 will return false if no such connection - */ - public static function getConnectionByResourceId($id) - { - return isset(self::$connections[$id]) ? self::$connections[$id] : false; - } - - /** - * Return all excising connections - * - * @return SSH2[] - */ - public static function getConnections() - { - return self::$connections; - } -} diff --git a/lib/phpaes/phpseclib/System/SSH/Agent.php b/lib/phpaes/phpseclib/System/SSH/Agent.php deleted file mode 100644 index 29182d10cb..0000000000 --- a/lib/phpaes/phpseclib/System/SSH/Agent.php +++ /dev/null @@ -1,340 +0,0 @@ - - * login('username', $agent)) { - * exit('Login Failed'); - * } - * - * echo $ssh->exec('pwd'); - * echo $ssh->exec('ls -la'); - * ?> - * - * - * @category System - * @package SSH\Agent - * @author Jim Wigginton - * @copyright 2014 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - * @internal See http://api.libssh.org/rfc/PROTOCOL.agent - */ - -namespace phpseclib\System\SSH; - -use ParagonIE\ConstantTime\Base64; -use phpseclib\Crypt\RSA; -use phpseclib\Exception\BadConfigurationException; -use phpseclib\System\SSH\Agent\Identity; -use phpseclib\Common\Functions\Objects; - -/** - * Pure-PHP ssh-agent client identity factory - * - * requestIdentities() method pumps out \phpseclib\System\SSH\Agent\Identity objects - * - * @package SSH\Agent - * @author Jim Wigginton - * @access internal - */ -class Agent -{ - /**#@+ - * Message numbers - * - * @access private - */ - // to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1) - const SSH_AGENTC_REQUEST_IDENTITIES = 11; - // this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2). - const SSH_AGENT_IDENTITIES_ANSWER = 12; - // the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3) - const SSH_AGENTC_SIGN_REQUEST = 13; - // the SSH1 response is SSH_AGENT_RSA_RESPONSE (4) - const SSH_AGENT_SIGN_RESPONSE = 14; - /**#@-*/ - - /**@+ - * Agent forwarding status - * - * @access private - */ - // no forwarding requested and not active - const FORWARD_NONE = 0; - // request agent forwarding when opportune - const FORWARD_REQUEST = 1; - // forwarding has been request and is active - const FORWARD_ACTIVE = 2; - /**#@-*/ - - /** - * Unused - */ - const SSH_AGENT_FAILURE = 5; - - /** - * Socket Resource - * - * @var resource - * @access private - */ - private $fsock; - - /** - * Agent forwarding status - * - * @var int - * @access private - */ - private $forward_status = self::FORWARD_NONE; - - /** - * Buffer for accumulating forwarded authentication - * agent data arriving on SSH data channel destined - * for agent unix socket - * - * @var string - * @access private - */ - private $socket_buffer = ''; - - /** - * Tracking the number of bytes we are expecting - * to arrive for the agent socket on the SSH data - * channel - * - * @var int - * @access private - */ - private $expected_bytes = 0; - - /** - * The current request channel - * - * @var int - * @access private - */ - private $request_channel; - - /** - * Default Constructor - * - * @return \phpseclib\System\SSH\Agent - * @throws \phpseclib\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found - * @throws \RuntimeException on connection errors - * @access public - */ - public function __construct() - { - switch (true) { - case isset($_SERVER['SSH_AUTH_SOCK']): - $address = $_SERVER['SSH_AUTH_SOCK']; - break; - case isset($_ENV['SSH_AUTH_SOCK']): - $address = $_ENV['SSH_AUTH_SOCK']; - break; - default: - throw new BadConfigurationException('SSH_AUTH_SOCK not found'); - } - - $this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr); - if (!$this->fsock) { - throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)"); - } - } - - /** - * Request Identities - * - * See "2.5.2 Requesting a list of protocol 2 keys" - * Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects - * - * @return array - * @throws \RuntimeException on receipt of unexpected packets - * @access public - */ - public function requestIdentities() - { - if (!$this->fsock) { - return []; - } - - $packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES); - if (strlen($packet) != fputs($this->fsock, $packet)) { - throw new \RuntimeException('Connection closed while requesting identities'); - } - - $length = current(unpack('N', fread($this->fsock, 4))); - $type = ord(fread($this->fsock, 1)); - if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) { - throw new \RuntimeException('Unable to request identities'); - } - - $identities = []; - $keyCount = current(unpack('N', fread($this->fsock, 4))); - for ($i = 0; $i < $keyCount; $i++) { - $length = current(unpack('N', fread($this->fsock, 4))); - $key_blob = fread($this->fsock, $length); - $key_str = 'ssh-rsa ' . Base64::encode($key_blob); - $length = current(unpack('N', fread($this->fsock, 4))); - if ($length) { - $key_str.= ' ' . fread($this->fsock, $length); - } - $length = current(unpack('N', substr($key_blob, 0, 4))); - $key_type = substr($key_blob, 4, $length); - switch ($key_type) { - case 'ssh-rsa': - $key = new RSA(); - $key->load($key_str); - break; - case 'ssh-dss': - // not currently supported - break; - } - // resources are passed by reference by default - if (isset($key)) { - $identity = new Identity($this->fsock); - $identity->setPublicKey($key); - $identity->setPublicKeyBlob($key_blob); - $identities[] = $identity; - unset($key); - } - } - - return $identities; - } - - /** - * Signal that agent forwarding should - * be requested when a channel is opened - * - * @param Net_SSH2 $ssh - * @return bool - * @access public - */ - public function startSSHForwarding($ssh) - { - if ($this->forward_status == self::FORWARD_NONE) { - $this->forward_status = self::FORWARD_REQUEST; - } - } - - /** - * Request agent forwarding of remote server - * - * @param Net_SSH2 $ssh - * @return bool - * @access private - */ - private function request_forwarding($ssh) - { - $this->request_channel = Objects::callFunc($ssh, 'get_open_channel'); - if ($this->request_channel === false) { - return false; - } - - $packet = pack( - 'CNNa*C', - NET_SSH2_MSG_CHANNEL_REQUEST, - Objects::getVar($ssh, 'server_channels')[$this->request_channel], - strlen('auth-agent-req@openssh.com'), - 'auth-agent-req@openssh.com', - 1 - ); - - $this->update_channel_status($ssh, NET_SSH2_MSG_CHANNEL_REQUEST); - if (!Objects::callFunc($ssh, 'send_binary_packet', [$packet])) { - return false; - } - - $response = Objects::callFunc($ssh, 'get_channel_packet', [$this->request_channel]); - if ($response === false) { - return false; - } - - $this->update_channel_status($ssh, NET_SSH2_MSG_CHANNEL_OPEN); - $this->forward_status = self::FORWARD_ACTIVE; - - return true; - } - - /** - * On successful channel open - * - * This method is called upon successful channel - * open to give the SSH Agent an opportunity - * to take further action. i.e. request agent forwarding - * - * @param Net_SSH2 $ssh - * @access private - */ - private function on_channel_open($ssh) - { - if ($this->forward_status == self::FORWARD_REQUEST) { - $this->request_forwarding($ssh); - } - } - - /** - * Forward data to SSH Agent and return data reply - * - * @param string $data - * @return data from SSH Agent - * @throws \RuntimeException on connection errors - * @access private - */ - private function forward_data($data) - { - if ($this->expected_bytes > 0) { - $this->socket_buffer.= $data; - $this->expected_bytes -= strlen($data); - } else { - $agent_data_bytes = current(unpack('N', $data)); - $current_data_bytes = strlen($data); - $this->socket_buffer = $data; - if ($current_data_bytes != $agent_data_bytes + 4) { - $this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes; - return false; - } - } - - if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) { - throw new \RuntimeException('Connection closed attempting to forward data to SSH agent'); - } - - $this->socket_buffer = ''; - $this->expected_bytes = 0; - - $agent_reply_bytes = current(unpack('N', fread($this->fsock, 4))); - - $agent_reply_data = fread($this->fsock, $agent_reply_bytes); - $agent_reply_data = current(unpack('a*', $agent_reply_data)); - - return pack('Na*', $agent_reply_bytes, $agent_reply_data); - } - - /** - * Forward data to SSH Agent and return data reply - * - * @param \phpseclib\Net\SSH2 $ssh - * @param integer $status - * @access private - */ - private function update_channel_status($ssh, $status) - { - $temp = Objects::getVar($ssh, 'channel_status'); - $temp[$this->request_channel] = $status; - Objects::setVar($ssh, 'channel_status', $temp); - } -} diff --git a/lib/phpaes/phpseclib/System/SSH/Agent/Identity.php b/lib/phpaes/phpseclib/System/SSH/Agent/Identity.php deleted file mode 100644 index fd36fef3f4..0000000000 --- a/lib/phpaes/phpseclib/System/SSH/Agent/Identity.php +++ /dev/null @@ -1,171 +0,0 @@ - - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - * @internal See http://api.libssh.org/rfc/PROTOCOL.agent - */ - -namespace phpseclib\System\SSH\Agent; - -use phpseclib\Crypt\RSA; -use phpseclib\Exception\UnsupportedAlgorithmException; -use phpseclib\System\SSH\Agent; - -/** - * Pure-PHP ssh-agent client identity object - * - * Instantiation should only be performed by \phpseclib\System\SSH\Agent class. - * This could be thought of as implementing an interface that phpseclib\Crypt\RSA - * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something. - * The methods in this interface would be getPublicKey and sign since those are the - * methods phpseclib looks for to perform public key authentication. - * - * @package SSH\Agent - * @author Jim Wigginton - * @access internal - */ -class Identity -{ - /** - * Key Object - * - * @var \phpseclib\Crypt\RSA - * @access private - * @see self::getPublicKey() - */ - private $key; - - /** - * Key Blob - * - * @var string - * @access private - * @see self::sign() - */ - private $key_blob; - - /** - * Socket Resource - * - * @var resource - * @access private - * @see self::sign() - */ - private $fsock; - - /** - * Default Constructor. - * - * @param resource $fsock - * @return \phpseclib\System\SSH\Agent\Identity - * @access private - */ - public function __construct($fsock) - { - $this->fsock = $fsock; - } - - /** - * Set Public Key - * - * Called by \phpseclib\System\SSH\Agent::requestIdentities() - * - * @param \phpseclib\Crypt\RSA $key - * @access private - */ - public function setPublicKey($key) - { - $this->key = $key; - $this->key->setPublicKey(); - } - - /** - * Set Public Key - * - * Called by \phpseclib\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key - * but this saves a small amount of computation. - * - * @param string $key_blob - * @access private - */ - public function setPublicKeyBlob($key_blob) - { - $this->key_blob = $key_blob; - } - - /** - * Get Public Key - * - * Wrapper for $this->key->getPublicKey() - * - * @param int $type optional - * @return mixed - * @access public - */ - public function getPublicKey($type = 'PKCS8') - { - return $this->key->getPublicKey($type); - } - - /** - * Sets the hash - * - * ssh-agent only supports signatures with sha1 hashes but to maintain BC with RSA.php this function exists - * - * @param string $hash optional - * @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @access public - */ - public function setHash($hash = 'sha1') - { - if ($hash != 'sha1') { - throw new UnsupportedAlgorithmException('ssh-agent can only be used with the sha1 hash'); - } - } - - /** - * Create a signature - * - * See "2.6.2 Protocol 2 private key signature request" - * - * @param string $message - * @param int $padding optional - * @return string - * @throws \RuntimeException on connection errors - * @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @access public - */ - public function sign($message, $padding = RSA::PADDING_PKCS1) - { - if ($padding != RSA::PADDING_PKCS1 && $padding != RSA::PADDING_RELAXED_PKCS1) { - throw new UnsupportedAlgorithmException('ssh-agent can only create PKCS1 signatures'); - } - - // the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE - $packet = pack('CNa*Na*N', Agent::SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0); - $packet = pack('Na*', strlen($packet), $packet); - if (strlen($packet) != fputs($this->fsock, $packet)) { - throw new \RuntimeException('Connection closed during signing'); - } - - $length = current(unpack('N', fread($this->fsock, 4))); - $type = ord(fread($this->fsock, 1)); - if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) { - throw new \RuntimeException('Unable to retrieve signature'); - } - - $signature_blob = fread($this->fsock, $length - 1); - // the only other signature format defined - ssh-dss - is the same length as ssh-rsa - // the + 12 is for the other various SSH added length fields - return substr($signature_blob, strlen('ssh-rsa') + 12); - } -} diff --git a/lib/phpaes/phpseclib/bootstrap.php b/lib/phpaes/phpseclib/bootstrap.php deleted file mode 100644 index bd4ba0b5a5..0000000000 --- a/lib/phpaes/phpseclib/bootstrap.php +++ /dev/null @@ -1,20 +0,0 @@ -)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e){return this}if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n){return !n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n)){for(i in n){b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i])}}return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2]){return r.find(e)}this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++){if(null!=(o=arguments[u])){for(i in o){e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r))}}}return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body){return setTimeout(b.ready)}b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return !isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e)){return !1}try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf")){return !1}}catch(n){return !1}var r;for(r in e){}return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e){return !1}return !0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e){return null}"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n){return null}try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++){if(r=t.apply(e[i],n),r===!1){break}}}else{for(i in e){if(r=t.apply(e[i],n),r===!1){break}}}}else{if(a){for(;o>i;i++){if(r=t.call(e[i],i,e[i]),r===!1){break}}}else{for(i in e){if(r=t.call(e[i],i,e[i]),r===!1){break}}}}return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g){return g.call(t,e,n)}for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++){if(n in t&&t[n]===e){return n}}}return -1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r){for(;r>o;o++){e[i++]=n[o]}}else{while(n[o]!==t){e[i++]=n[o++]}}return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++){r=!!t(e[o],o),n!==r&&i.push(e[o])}return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a){for(;o>i;i++){r=t(e[i],i,n),null!=r&&(s[s.length]=r)}}else{for(i in e){r=t(e[i],i,n),null!=r&&(s[s.length]=r)}}return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r){b.access(e,n,u,r[u],!0,a,s)}}else{if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n)){for(;l>u;u++){n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)))}}}return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n){if(n=b.Deferred(),"complete"===o.readyState){setTimeout(b.ready)}else{if(o.addEventListener){o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1)}else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}}}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++){if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1){u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return !u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return !l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return !!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1){for(s=Array(r),u=Array(r),l=Array(r);r>t;t++){n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i}}return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length){return{}}s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in {submit:!0,change:!0,focusin:!0}){d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1}return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="
t
",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t){return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++){delete o[t[r]]}if(!(n?$:b.isEmptyObject)(o)){return}}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType){return !1}var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return !t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++){i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]))}b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else{r=t}}return r}function $(e){var t;for(t in e){if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t){return !1}}return !0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--){r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u))}return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e)){return this.each(function(t){b(this).addClass(e.call(this,t,this.className))})}if(u){for(t=(e||"").match(w)||[];s>a;a++){if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++]){0>r.indexOf(" "+i+" ")&&(r+=i+" ")}n.className=b.trim(r)}}}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e)){return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))})}if(u){for(t=(e||"").match(w)||[];s>a;a++){if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++]){while(r.indexOf(" "+i+" ")>=0){r=r.replace(" "+i+" "," ")}}n.className=e?b.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++]){u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}}else{(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")}})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++){if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0){return !0}}return !1},val:function(e){var n,r,i,o=this[0];if(arguments.length){return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set" in r&&r.set(this,o,"value")!==t||(this.value=o))})}if(o){return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get" in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return !t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++){if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o){return t}a.push(t)}}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u){return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get" in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set" in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType){while(n=o[i++]){r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)}}},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s){return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set" in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get" in o&&null!==(i=o.get(e,n))?i:e[n]}},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return !0}function ot(){return !1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--){s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0}e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--){if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--){a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a))}u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else{for(d in c){b.event.remove(e,d+t[l],n,r,!0)}}}b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode){h.push(l),f=l}f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped()){n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault()}if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped()){(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type)){for(;l!=this;l=l.parentNode||this){if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++){i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i)}o.length&&s.push({elem:l,handlers:o})}}}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando]){return e}var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--){n=r[t],e[n]=a[n]}return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus){try{return this.focus(),!1}catch(e){}}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.defaultPrevented&&e.defaultPrevented()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e){this.on(a,n,r,e[a],o)}return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1){i=ot}else{if(!i){return this}}return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj){return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this}if("object"==typeof e){for(o in e){this.off(o,n,e[o])}return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++){if(this[t]===e){return t}}return -1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++]){n.push(t)}return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return !1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e){return n}if(1!==(s=t.nodeType)&&9!==s){return[]}if(!d&&!r){if(i=J.exec(e)){if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode){return n}if(o.id===a){return n.push(o),n}}else{if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a){return n.push(o),n}}}else{if(i[2]){return H.apply(n,q.call(t.getElementsByTagName(e),0)),n}if((a=i[3])&&T.getByClassName&&t.getElementsByClassName){return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}}}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--){l[u]=g+dt(l[u])}m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v){try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="
",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++]){1===n.nodeType&&r.push(n)}return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t){while(t=t.parentNode){if(t===e){return !0}}}return !1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t){return u=!0,0}if(!o||!a){return e===n?-1:t===n?1:o?-1:a?1:0}if(o===a){return ut(e,t)}r=e;while(r=r.parentNode){s.unshift(r)}r=t;while(r=r.parentNode){l.unshift(r)}while(s[i]===l[i]){i++}return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t))){try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType){return n}}catch(r){}}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++){t===e[r-1]&&(i=n.push(r))}while(i--){e.splice(n[i],1)}}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r){return r}if(n){while(n=n.nextSibling){if(n===t){return -1}}}return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--){n[i=o[a]]&&(n[i]=!(r[i]=n[i]))}})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent){return e.textContent}for(e=e.firstChild;e;e=e.nextSibling){n+=o(e)}}else{if(3===i||4===i){return e.nodeValue}}}else{for(;t=e[r];r++){n+=o(t)}}return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return !0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return !!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g]){if(s?p.nodeName.toLowerCase()===y:1===p.nodeType){return !1}}h=g="only"===e&&!h&&"nextSibling"}return !0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop()){if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}}else{if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N){f=l[1]}else{while(p=++d&&p&&p[g]||(f=d=0)||h.pop()){if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t)){break}}}}return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--){i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--){(o=a[s])&&(e[s]=!(t[s]=o))}}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do{if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang){return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-")}}while((t=t.parentNode)&&1===t.nodeType);return !1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling){if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType){return !1}}return !0},parent:function(e){return !i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2){e.push(n)}return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2){e.push(n)}return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;){e.push(r)}return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;){e.push(r)}return e})}};for(n in {radio:!0,checkbox:!0,file:!0,password:!0,image:!0}){i.pseudos[n]=lt(n)}for(n in {submit:!0,reset:!0}){i.pseudos[n]=ct(n)}function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c){return t?0:c.slice(0)}s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter){!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length))}if(!n){break}}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++){r+=e[t].value}return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i]){if(1===t.nodeType||o){return e(t,n,r)}}}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i]){if((1===t.nodeType||o)&&e(t,n,s)){return !0}}}else{while(t=t[i]){if(1===t.nodeType||o){if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r){return u===!0}}else{if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0){return !0}}}}}}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--){if(!e[i](t,n,r)){return !1}}return !0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++){(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s))}return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--){(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}}if(o){if(i||e){if(i){l=[],c=y.length;while(c--){(p=y[c])&&l.push(m[c]=p)}i(null,y=[],l,u)}c=y.length;while(c--){(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}}else{y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)}})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return !a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++){if(n=i.relative[e[u].type]){f=[ht(gt(f),n)]}else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++){if(i.relative[e[r].type]){break}}return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||0.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++]){if(m(h,u,c)){f.push(h);break}}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++]){m(x,y,u,c)}if(s){if(v>0){while(b--){x[b]||y[b]||(y[b]=L.call(f))}}y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--){o=vt(t[n]),o[x]?r.push(o):i.push(o)}o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++){st(e,t[r],n)}return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t){return n}e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type]){break}if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e){return H.apply(n,q.call(r,0)),n}break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e){return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++){if(b.contains(r[t],this)){return !0}}}))}for(n=[],t=0;i>t;t++){b.find(e,this[t],n)}return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++){if(b.contains(this,n[t])){return !0}}})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return !!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do{e=e[t]}while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r))){1===o.nodeType&&i.push(o),o=o[n]}return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling){1===e.nodeType&&e!==t&&n.push(e)}return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t)){return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n})}if(t.nodeType){return b.grep(e,function(e){return e===t===n})}if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t)){return b.filter(t,r,!n)}t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement){while(t.length){n.createElement(t.pop())}}return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(t){b(this).wrapAll(e.call(this,t))})}if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType){e=e.firstChild}return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++){(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)))}return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild){e.removeChild(e.firstChild)}e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t){return 1===n.nodeType?n.innerHTML.replace(gt,""):t}if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++){n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e)}n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g)){return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)})}if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++){o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c)}if(a){for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++){o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")))}}l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++){b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s){for(r=0,i=s[n].length;i>r;r++){b.event.add(t,n,s[n][r])}}}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events){b.removeEvent(t,r,i.handle)}t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++){n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get())}return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s){for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++){!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n))}}return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e))){for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a){r[a]&&Ft(i,r[a])}}if(t){if(n){for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++){_t(i,r[a])}}else{_t(e,o)}}return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++){if(o=e[h],o||0===o){if("object"===b.type(o)){b.merge(d,o.nodeType?[o]:o)}else{if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--){s=s.lastChild}if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--){b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)}}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild){s.removeChild(s.firstChild)}s=f.lastChild}else{d.push(t.createTextNode(o))}}}}s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++]){if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++]){kt.test(o.type||"")&&n.push(o)}}}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++){if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events){for(r in a.events){f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle)}}l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e){return t}var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--){if(t=en[i]+n,t in e){return t}}return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++){r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))))}for(a=0;s>a;a++){r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"))}return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++){a[n[s]]=b.css(e,n[s],!1,o)}return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t){return s&&"get" in s&&(o=s.get(e,!1,i))!==t?o:l[n]}if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set" in s&&(r=s.set(e,r,i))===t))){try{l[n]=r}catch(c){}}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get" in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t){a[o]=e.style[o],e.style[o]=t[o]}i=n.apply(e,r||[]);for(o in t){e.style[o]=a[o]}return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2){"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)))}return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i)){return i}r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("'),n.waittime>0&&(a.waitTimeout=C(n.waittime,I));var G=document.getElementById(H);G.onload=G.onreadystatechange=function(){var l=!!n.scrollInside;if(a.firstLoad&&z.addClass("modal-loading"),!this.readyState||"complete"==this.readyState){a.firstLoad=!1,n.waittime>0&&clearTimeout(a.waitTimeout);try{z.attr("ref",G.contentWindow.location.href);var r=p.frames[H].$;if(r&&"auto"===n.height&&"fullscreen"!=n.size){var d=r("body").addClass("body-modal").toggleClass("body-modal-scroll-inside",l);n.iframeBodyClass&&d.addClass(n.iframeBodyClass);var o=function(K){z.removeClass("fade");var c=d.outerHeight();if(K===!0&&n.onlyIncreaseHeight&&(c=Math.max(c,E.data("minModalHeight")||0),E.data("minModalHeight",c)),l){var h=w(p).height();c=Math.min(c,h-J.height())}E.css("height",c),n.fade&&z.addClass("fade"),C()};z.callComEvent(a,"loaded",{modalType:"iframe",jQuery:r}),setTimeout(o,100),d.off("resize."+g).on("resize."+g,o),l&&w(p).off("resize."+g).on("resize."+g,o)}else{C()}}catch(y){C()}}}}else{w.ajax(w.extend({url:n.url,success:function(c){try{var h=w(c);h.filter(".modal-dialog").length?B.replaceWith(h):h.filter(".modal-content").length?B.find(".modal-content").replaceWith(h):E.wrapInner(h)}catch(d){p.console&&p.console.warn&&console.warn("ZUI: Cannot recogernize remote content.",{error:d,data:c}),z.html(c)}z.callComEvent(a,"loaded",{modalType:x}),C()},error:I},n.ajaxOptions))}}}z.modal({show:"show",backdrop:n.backdrop,moveable:n.moveable,rememberPos:n.rememberPos,keyboard:n.keyboard})},b.prototype.close=function(a,d){var c=this;(a||d)&&c.$modal.on("hidden"+f,function(){w.isFunction(a)&&a(),typeof d===v&&d.length&&!c.$modal.data("cancel-reload")&&("this"===d?p.location.reload():p.location=d)}),c.$modal.modal("hide")},b.prototype.toggle=function(a){this.isShown?this.close():this.show(a)},b.prototype.ajustPosition=function(a){a=a===k?this.options.position:a,w.isFunction(a)&&(a=a(this)),this.$modal.modal("ajustPosition",a)},w.zui({ModalTrigger:b,modalTrigger:new b}),w.fn.modalTrigger=function(c,a){return w(this).each(function(){var e=w(this),h=e.data(g),d=w.extend({title:e.attr("title")||e.text(),url:e.attr("href"),type:e.hasClass("iframe")?"iframe":""},e.data(),w.isPlainObject(c)&&c);h||e.data(g,h=new b(d,e)),typeof c==v?h[c](a):d.show&&h.show(a),e.on((d.trigger||"click")+".toggle."+g,function(l){d=w.extend(d,{url:e.attr("href")||e.attr("data-url")||e.data("url")||d.url}),h.toggle(d),e.is("a")&&l.preventDefault()})})};var j=w.fn.modal;w.fn.modal=function(c,a){return w(this).each(function(){var d=w(this);d.hasClass("modal")?j.call(d,c,a):d.modalTrigger(c,a)})};var m=function(a){return a=w(a?a:".modal.modal-trigger"),a&&a instanceof w?a:null},u=function(d,e,l){var c=d;if(w.isFunction(d)){var h=l;l=e,e=d,d=h}d=m(d),d&&d.length?d.each(function(){w(this).data(g).close(e,l)}):w("body").hasClass("modal-open")||w(".modal.in").length||w("body").hasClass("body-modal")&&p.parent.$.zui.closeModal(c,e,l)},q=function(a,c){c=m(c),c&&c.length&&c.modal("ajustPosition",a)};w.zui({closeModal:u,ajustModalPosition:q}),w(document).on("click."+g+".data-api",'[data-toggle="modal"]',function(l){var d=w(this),h=d.attr("href"),n=null;try{n=w(d.attr("data-target")||h&&h.replace(/.*(?=#[^\s]+$)/,""))}catch(c){}n&&n.length||(d.data(g)?d.trigger(".toggle."+g):d.modalTrigger({show:!0})),d.is("a")&&l.preventDefault()}).on("click."+g+".data-api",'[data-dismiss="modal"]',function(){w.zui.closeModal()})}(window.jQuery,window,void 0),+function(b){var c=function(d,f){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.init("tooltip",d,f)};c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},c.prototype.init=function(k,g,p){this.enabled=!0,this.type=k,this.$element=b(g),this.options=this.getOptions(p);for(var h=this.options.trigger.split(" "),m=h.length;m--;){var f=h[m];if("click"==f){this.$element.on("click."+this.type,this.options.selector,b.proxy(this.toggle,this))}else{if("manual"!=f){var j="hover"==f?"mouseenter":"focus",d="hover"==f?"mouseleave":"blur";this.$element.on(j+"."+this.type,this.options.selector,b.proxy(this.enter,this)),this.$element.on(d+"."+this.type,this.options.selector,b.proxy(this.leave,this))}}}this.options.selector?this._options=b.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(d){return d=b.extend({},this.getDefaults(),this.$element.data(),d),d.delay&&"number"==typeof d.delay&&(d.delay={show:d.delay,hide:d.delay}),d},c.prototype.getDelegateOptions=function(){var f={},d=this.getDefaults();return this._options&&b.each(this._options,function(e,g){d[e]!=g&&(f[e]=g)}),f},c.prototype.enter=function(f){var d=f instanceof this.constructor?f:b(f.currentTarget)[this.type](this.getDelegateOptions()).data("zui."+this.type);return clearTimeout(d.timeout),d.hoverState="in",d.options.delay&&d.options.delay.show?void (d.timeout=setTimeout(function(){"in"==d.hoverState&&d.show()},d.options.delay.show)):d.show()},c.prototype.leave=function(f){var d=f instanceof this.constructor?f:b(f.currentTarget)[this.type](this.getDelegateOptions()).data("zui."+this.type);return clearTimeout(d.timeout),d.hoverState="out",d.options.delay&&d.options.delay.hide?void (d.timeout=setTimeout(function(){"out"==d.hoverState&&d.hide()},d.options.delay.hide)):d.hide()},c.prototype.show=function(I){var E=b.Event("show.zui."+this.type);if((I||this.hasContent())&&this.enabled){var B=this;if(B.$element.trigger(E),E.isDefaultPrevented()){return}var w=B.tip();B.setContent(I),B.options.animation&&w.addClass("fade");var A="function"==typeof B.options.placement?B.options.placement.call(B,w[0],B.$element[0]):B.options.placement,L=/\s?auto?\s?/i,x=L.test(A);x&&(A=A.replace(L,"")||"top"),w.detach().css({top:0,left:0,display:"block"}).addClass(A),B.options.container?w.appendTo(B.options.container):w.insertAfter(B.$element);var D=B.getPosition(),F=w[0].offsetWidth,K=w[0].offsetHeight;if(x){var J=B.$element.parent(),q=A,z=document.documentElement.scrollTop||document.body.scrollTop,H="body"==B.options.container?window.innerWidth:J.outerWidth(),G="body"==B.options.container?window.innerHeight:J.outerHeight(),C="body"==B.options.container?0:J.offset().left;A="bottom"==A&&D.top+D.height+K-z>G?"top":"top"==A&&D.top-z-K<0?"bottom":"right"==A&&D.right+F>H?"left":"left"==A&&D.left-F

'}),c.prototype=b.extend({},b.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var f=this.tip(),g=this.getTarget();if(g){return g.find(".arrow").length<1&&f.addClass("no-arrow"),void f.html(g.html())}var d=this.getTitle(),h=this.getContent();f.find(".popover-title")[this.options.html?"html":"text"](d),f.find(".popover-content")[this.options.html?"html":"text"](h),f.removeClass("fade top bottom left right in"),this.options.tipId&&f.attr("id",this.options.tipId),this.options.tipClass&&f.addClass(this.options.tipClass),f.find(".popover-title").html()||f.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTarget()||this.getTitle()||this.getContent()},c.prototype.getContent=function(){var d=this.$element,f=this.options;return d.attr("data-content")||("function"==typeof f.content?f.content.call(d[0]):f.content)},c.prototype.getTarget=function(){var f=this.$element,d=this.options,g=f.attr("data-target")||("function"==typeof d.target?d.target.call(f[0]):d.target);return !!g&&("$next"==g?f.next(".popover"):b(g))},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=b(this.options.template)),this.$tip};var a=b.fn.popover;b.fn.popover=function(d){return this.each(function(){var g=b(this),e=g.data("zui.popover"),f="object"==typeof d&&d;e||g.data("zui.popover",e=new c(this,f)),"string"==typeof d&&e[d]()})},b.fn.popover.Constructor=c,b.fn.popover.noConflict=function(){return b.fn.popover=a,this}}(window.jQuery),+function(k){function h(){k(m).remove(),k(c).each(function(l){var a=g(k(this));a.hasClass("open")&&(a.trigger(l=k.Event("hide."+d)),l.isDefaultPrevented()||a.removeClass("open").trigger("hidden."+d))})}function g(o){var a=o.attr("data-target");a||(a=o.attr("href"),a=a&&/#/.test(a)&&a.replace(/.*(?=#[^\s]*$)/,""));var p;try{p=a&&k(a)}catch(l){}return p&&p.length?p:o.parent()}var d="zui.dropdown",m=".dropdown-backdrop",c="[data-toggle=dropdown]",j=function(a){k(a).on("click."+d,this.toggle)};j.prototype.toggle=function(l){var p=k(this);if(!p.is(".disabled, :disabled")){var e=g(p),n=e.hasClass("open");if(h(),!n){if("ontouchstart" in document.documentElement&&!e.closest(".navbar-nav").length&&k('',f={type:"default",placement:"top",time:4000,parent:"body",icon:null,close:!0,fade:!0,scale:!0},v={},b=function(z,s){w.isPlainObject(z)&&(s=z,z=s.message);var a=this;s=a.options=w.extend({},f,s),a.id=s.id||g++;var o=v[a.id];o&&o.destroy(),v[a.id]=a,a.message=(s.icon?' ':"")+z,a.$=w(x.format(s)).toggleClass("fade",s.fade).toggleClass("scale",s.scale).attr("id","messager-"+a.id),s.cssClass&&a.$.addClass(s.cssClass);var B=!1,A=a.$.find(".messager-actions"),n=function(c){var d=w('
";g'+f[this.language].daysMin[g++%7]+""}h+="",this.picker.find(".datetimepicker-days thead").append(h)},fillMonths:function(){for(var g="",h=0;h<12;){g+=''+f[this.language].monthsShort[h++]+""}this.picker.find(".datetimepicker-months td").html(g)},fill:function(){if(null!=this.date&&null!=this.viewDate){var X=new Date(this.viewDate),R=X.getUTCFullYear(),ae=X.getUTCMonth(),O=X.getUTCDate(),V=X.getUTCHours(),Y=X.getUTCMinutes(),ac=this.startDate!==-(1/0)?this.startDate.getUTCFullYear():-(1/0),ab=this.startDate!==-(1/0)?this.startDate.getUTCMonth():-(1/0),J=this.endDate!==1/0?this.endDate.getUTCFullYear():1/0,Q=this.endDate!==1/0?this.endDate.getUTCMonth():1/0,aa=new d(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate()).valueOf(),Z=new Date;if(this.picker.find(".datetimepicker-days thead th:eq(1)").text(f[this.language].months[ae]+" "+R),"time"==this.formatViewType){var U=V%12?V%12:12,H=(U<10?"0":"")+U,B=(Y<10?"0":"")+Y,ad=f[this.language].meridiem[V<12?0:1];this.picker.find(".datetimepicker-hours thead th:eq(1)").text(H+":"+B+" "+ad.toUpperCase()),this.picker.find(".datetimepicker-minutes thead th:eq(1)").text(H+":"+B+" "+ad.toUpperCase())}else{this.picker.find(".datetimepicker-hours thead th:eq(1)").text(O+" "+f[this.language].months[ae]+" "+R),this.picker.find(".datetimepicker-minutes thead th:eq(1)").text(O+" "+f[this.language].months[ae]+" "+R)}this.picker.find("tfoot th.today").text(f[this.language].today).toggle(this.todayBtn!==!1),this.updateNavArrows(),this.fillMonths();var G=d(R,ae-1,28,0,0,0,0),E=c.getDaysInMonth(G.getUTCFullYear(),G.getUTCMonth());G.setUTCDate(E),G.setUTCDate(E-(G.getUTCDay()-this.weekStart+7)%7);var N=new Date(G);N.setUTCDate(N.getUTCDate()+42),N=N.valueOf();for(var af,W=[];G.valueOf()"),af="",G.getUTCFullYear()R||G.getUTCFullYear()==R&&G.getUTCMonth()>ae)&&(af+=" new"),this.todayHighlight&&G.getUTCFullYear()==Z.getFullYear()&&G.getUTCMonth()==Z.getMonth()&&G.getUTCDate()==Z.getDate()&&(af+=" today"),G.valueOf()==aa&&(af+=" active"),(G.valueOf()+86400000<=this.startDate||G.valueOf()>this.endDate||b.inArray(G.getUTCDay(),this.daysOfWeekDisabled)!==-1)&&(af+=" disabled"),W.push('"),G.getUTCDay()==this.weekEnd&&W.push(""),G.setUTCDate(G.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(W.join("")),W=[];for(var e="",j="",K="",q=0;q<24;q++){var n=d(R,ae,O,q);af="",n.valueOf()+3600000<=this.startDate||n.valueOf()>this.endDate?af+=" disabled":V==q&&(af+=" active"),this.showMeridian&&2==f[this.language].meridiem.length?(j=q<12?f[this.language].meridiem[0]:f[this.language].meridiem[1],j!=K&&(""!=K&&W.push(""),W.push('
'+j.toUpperCase()+"")),K=j,e=q%12?q%12:12,W.push(''+e+""),23==q&&W.push("
")):(e=q+":00",W.push(''+e+""))}this.picker.find(".datetimepicker-hours td").html(W.join("")),W=[],e="",j="",K="";for(var q=0;q<60;q+=this.minuteStep){var n=d(R,ae,O,V,q,0);af="",n.valueOf()this.endDate?af+=" disabled":Math.floor(Y/this.minuteStep)==Math.floor(q/this.minuteStep)&&(af+=" active"),this.showMeridian&&2==f[this.language].meridiem.length?(j=V<12?f[this.language].meridiem[0]:f[this.language].meridiem[1],j!=K&&(""!=K&&W.push(""),W.push('
'+j.toUpperCase()+"")),K=j,e=V%12?V%12:12,W.push(''+e+":"+(q<10?"0"+q:q)+""),59==q&&W.push("
")):(e=q+":00",W.push(''+V+":"+(q<10?"0"+q:q)+""))}this.picker.find(".datetimepicker-minutes td").html(W.join(""));var I=this.date.getUTCFullYear(),s=this.picker.find(".datetimepicker-months").find("th:eq(1)").text(R).end().find("span").removeClass("active");I==R&&s.eq(this.date.getUTCMonth()).addClass("active"),(RJ)&&s.addClass("disabled"),R==ac&&s.slice(0,ab).addClass("disabled"),R==J&&s.slice(Q+1).addClass("disabled"),W="",R=10*parseInt(R/10,10);var A=this.picker.find(".datetimepicker-years").find("th:eq(1)").text(R+"-"+(R+9)).end().find("td");R-=1;for(var q=-1;q<11;q++){W+='J?" disabled":"")+'">'+R+"",R+=1}A.html(W),this.place()}},updateNavArrows:function(){var h=new Date(this.viewDate),k=h.getUTCFullYear(),g=h.getUTCMonth(),l=h.getUTCDate(),j=h.getUTCHours();switch(this.viewMode){case 0:this.startDate!==-(1/0)&&k<=this.startDate.getUTCFullYear()&&g<=this.startDate.getUTCMonth()&&l<=this.startDate.getUTCDate()&&j<=this.startDate.getUTCHours()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&k>=this.endDate.getUTCFullYear()&&g>=this.endDate.getUTCMonth()&&l>=this.endDate.getUTCDate()&&j>=this.endDate.getUTCHours()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:this.startDate!==-(1/0)&&k<=this.startDate.getUTCFullYear()&&g<=this.startDate.getUTCMonth()&&l<=this.startDate.getUTCDate()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&k>=this.endDate.getUTCFullYear()&&g>=this.endDate.getUTCMonth()&&l>=this.endDate.getUTCDate()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 2:this.startDate!==-(1/0)&&k<=this.startDate.getUTCFullYear()&&g<=this.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&k>=this.endDate.getUTCFullYear()&&g>=this.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 3:case 4:this.startDate!==-(1/0)&&k<=this.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&k>=this.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}},mousewheel:function(j){if(j.preventDefault(),j.stopPropagation(),!this.wheelPause){this.wheelPause=!0;var g=j.originalEvent,k=g.wheelDelta,h=k>0?1:0===k?0:-1;this.wheelViewModeNavigationInverseDirection&&(h=-h),this.showMode(h),setTimeout(b.proxy(function(){this.wheelPause=!1},this),this.wheelViewModeNavigationDelay)}},click:function(q){q.stopPropagation(),q.preventDefault();var k=b(q.target).closest("span, td, th, legend");if(1==k.length){if(k.is(".disabled")){return void this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate})}switch(k[0].nodeName.toLowerCase()){case"th":switch(k[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var j=c.modes[this.viewMode].navStep*("prev"==k[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,j);break;case 1:this.viewDate=this.moveDate(this.viewDate,j);break;case 2:this.viewDate=this.moveMonth(this.viewDate,j);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,j)}this.fill();break;case"today":var x=new Date;x=d(x.getFullYear(),x.getMonth(),x.getDate(),x.getHours(),x.getMinutes(),x.getSeconds(),0),xthis.endDate&&(x=this.endDate),this.viewMode=this.startViewMode,this.showMode(0),this._setDate(x),this.fill(),this.autoclose&&this.hide()}break;case"span":if(!k.is(".disabled")){var e=this.viewDate.getUTCFullYear(),m=this.viewDate.getUTCMonth(),s=this.viewDate.getUTCDate(),w=this.viewDate.getUTCHours(),v=this.viewDate.getUTCMinutes(),y=this.viewDate.getUTCSeconds();if(k.is(".month")?(this.viewDate.setUTCDate(1),m=k.parent().find("span").index(k),s=this.viewDate.getUTCDate(),this.viewDate.setUTCMonth(m),this.element.trigger({type:"changeMonth",date:this.viewDate}),this.viewSelect>=3&&this._setDate(d(e,m,s,w,v,y,0))):k.is(".year")?(this.viewDate.setUTCDate(1),e=parseInt(k.text(),10)||0,this.viewDate.setUTCFullYear(e),this.element.trigger({type:"changeYear",date:this.viewDate}),this.viewSelect>=4&&this._setDate(d(e,m,s,w,v,y,0))):k.is(".hour")?(w=parseInt(k.text(),10)||0,(k.hasClass("hour_am")||k.hasClass("hour_pm"))&&(12==w&&k.hasClass("hour_am")?w=0:12!=w&&k.hasClass("hour_pm")&&(w+=12)),this.viewDate.setUTCHours(w),this.element.trigger({type:"changeHour",date:this.viewDate}),this.viewSelect>=1&&this._setDate(d(e,m,s,w,v,y,0))):k.is(".minute")&&(v=parseInt(k.text().substr(k.text().indexOf(":")+1),10)||0,this.viewDate.setUTCMinutes(v),this.element.trigger({type:"changeMinute",date:this.viewDate}),this.viewSelect>=0&&this._setDate(d(e,m,s,w,v,y,0))),0!=this.viewMode){var g=this.viewMode;this.showMode(-1),this.fill(),g==this.viewMode&&this.autoclose&&this.hide()}else{this.fill(),this.autoclose&&this.hide()}}break;case"td":if(k.is(".day")&&!k.is(".disabled")){var s=parseInt(k.text(),10)||1,e=this.viewDate.getUTCFullYear(),m=this.viewDate.getUTCMonth(),w=this.viewDate.getUTCHours(),v=this.viewDate.getUTCMinutes(),y=this.viewDate.getUTCSeconds();k.is(".old")?0===m?(m=11,e-=1):m-=1:k.is(".new")&&(11==m?(m=0,e+=1):m+=1),this.viewDate.setUTCFullYear(e),this.viewDate.setUTCMonth(m,s),this.element.trigger({type:"changeDay",date:this.viewDate}),this.viewSelect>=2&&this._setDate(d(e,m,s,w,v,y,0))}var g=this.viewMode;this.showMode(-1),this.fill(),g==this.viewMode&&this.autoclose&&this.hide()}}},_setDate:function(h,j){j&&"date"!=j||(this.date=h),j&&"view"!=j||(this.viewDate=h),this.fill(),this.setValue();var g;this.isInput?g=this.element:this.component&&(g=this.element.find("input")),g&&(g.change(),this.autoclose&&(!j||"date"==j)),this.element.trigger({type:"changeDate",date:this.date}),null===h&&(this.date=this.viewDate)},moveMinute:function(h,j){if(!j){return h}var g=new Date(h.valueOf());return g.setUTCMinutes(g.getUTCMinutes()+j*this.minuteStep),g},moveHour:function(h,j){if(!j){return h}var g=new Date(h.valueOf());return g.setUTCHours(g.getUTCHours()+j),g},moveDate:function(h,j){if(!j){return h}var g=new Date(h.valueOf());return g.setUTCDate(g.getUTCDate()+j),g},moveMonth:function(u,p){if(!p){return u}var m,j,v=new Date(u.valueOf()),h=v.getUTCDate(),q=v.getUTCMonth(),g=Math.abs(p);if(p=p>0?1:-1,1==g){j=p==-1?function(){return v.getUTCMonth()==q}:function(){return v.getUTCMonth()!=m},m=q+p,v.setUTCMonth(m),(m<0||m>11)&&(m=(m+12)%12)}else{for(var k=0;k=this.startDate&&e<=this.endDate},keydown:function(j){if(this.picker.is(":not(:visible)")){return void (27==j.keyCode&&this.show())}var l,h,p,k=!1;switch(j.keyCode){case 27:this.hide(),j.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}l=37==j.keyCode?-1:1,viewMode=this.viewMode,j.ctrlKey?viewMode+=2:j.shiftKey&&(viewMode+=1),4==viewMode?(h=this.moveYear(this.date,l),p=this.moveYear(this.viewDate,l)):3==viewMode?(h=this.moveMonth(this.date,l),p=this.moveMonth(this.viewDate,l)):2==viewMode?(h=this.moveDate(this.date,l),p=this.moveDate(this.viewDate,l)):1==viewMode?(h=this.moveHour(this.date,l),p=this.moveHour(this.viewDate,l)):0==viewMode&&(h=this.moveMinute(this.date,l),p=this.moveMinute(this.viewDate,l)),this.dateWithinRange(h)&&(this.date=h,this.viewDate=p,this.setValue(),this.update(),j.preventDefault(),k=!0);break;case 38:case 40:if(!this.keyboardNavigation){break}l=38==j.keyCode?-1:1,viewMode=this.viewMode,j.ctrlKey?viewMode+=2:j.shiftKey&&(viewMode+=1),4==viewMode?(h=this.moveYear(this.date,l),p=this.moveYear(this.viewDate,l)):3==viewMode?(h=this.moveMonth(this.date,l),p=this.moveMonth(this.viewDate,l)):2==viewMode?(h=this.moveDate(this.date,7*l),p=this.moveDate(this.viewDate,7*l)):1==viewMode?this.showMeridian?(h=this.moveHour(this.date,6*l),p=this.moveHour(this.viewDate,6*l)):(h=this.moveHour(this.date,4*l),p=this.moveHour(this.viewDate,4*l)):0==viewMode&&(h=this.moveMinute(this.date,4*l),p=this.moveMinute(this.viewDate,4*l)),this.dateWithinRange(h)&&(this.date=h,this.viewDate=p,this.setValue(),this.update(),j.preventDefault(),k=!0);break;case 13:if(0!=this.viewMode){var m=this.viewMode;this.showMode(-1),this.fill(),m==this.viewMode&&this.autoclose&&this.hide()}else{this.fill(),this.autoclose&&this.hide()}j.preventDefault();break;case 9:this.hide()}if(k){var g;this.isInput?g=this.element:this.component&&(g=this.element.find("input")),g&&g.change(),this.element.trigger({type:"changeDate",date:this.date})}},showMode:function(g){if(g){var h=Math.max(0,Math.min(c.modes.length-1,this.viewMode+g));h>=this.minView&&h<=this.maxView&&(this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:h}),this.viewMode=h)}this.picker.find(">div").hide().filter(".datetimepicker-"+c.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()},reset:function(e){this._setDate(null,"date")}},b.fn.datetimepicker=function(g){var h=Array.apply(null,arguments);return h.shift(),this.each(function(){var j=b(this),k=j.data("datetimepicker"),e="object"==typeof g&&g;k||j.data("datetimepicker",k=new a(this,b.extend({},b.fn.datetimepicker.defaults,j.data(),e))),"string"==typeof g&&"function"==typeof k[g]&&k[g].apply(k,h)})},b.fn.datetimepicker.defaults={pickerPosition:"auto-right"},b.fn.datetimepicker.Constructor=a;var f=b.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today"}};f["zh-cn"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"],daysShort:["周日","周一","周二","周三","周四","周五","周六","周日"],daysMin:["日","一","二","三","四","五","六","日"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],today:"今日",suffix:[],meridiem:[]},f["zh-tw"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"],daysShort:["周日","周一","周二","周三","周四","周五","周六","周日"],daysMin:["日","一","二","三","四","五","六","日"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],today:"今天",suffix:[],meridiem:["上午","下午"]};var c={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(e){return e%4===0&&e%100!==0||e%400===0},getDaysInMonth:function(g,h){return[31,c.isLeapYear(g)?29:28,31,30,31,30,31,31,30,31,30,31][h]},getDefaultFormat:function(g,h){if("standard"==g){return"input"==h?"yyyy-mm-dd hh:ii":"yyyy-mm-dd hh:ii:ss"}if("php"==g){return"input"==h?"Y-m-d H:i":"Y-m-d H:i:s"}throw new Error("Invalid format type.")},validParts:function(e){if("standard"==e){return/hh?|HH?|p|P|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}if("php"==e){return/[dDjlNwzFmMnStyYaABgGhHis]/g}throw new Error("Invalid format type.")},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(h,j){var g=h.replace(this.validParts(j),"\0").split("\0"),k=h.match(this.validParts(j));if(!g||!g.length||!k||0==k.length){throw new Error("Invalid date format.")}return{separators:g,parts:k}},parseDate:function(J,k,F,e){if(J instanceof Date){var q=new Date(J.valueOf()-60000*J.getTimezoneOffset());return q.setMilliseconds(0),q}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(J)&&(k=this.parseFormat("yyyy-mm-dd",e)),/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(J)&&(k=this.parseFormat("yyyy-mm-dd hh:ii",e)),/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(J)&&(k=this.parseFormat("yyyy-mm-dd hh:ii:ss",e)),/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(J)){var x,C,B=/([-+]\d+)([dmwy])/,I=J.match(/([-+]\d+)([dmwy])/g);J=new Date;for(var j=0;j
',contTemplate:'',footTemplate:''};c.template='
'+G.getUTCDate()+"
'+c.headTemplate+c.contTemplate+c.footTemplate+'
'+c.headTemplate+c.contTemplate+c.footTemplate+'
'+c.headTemplate+""+c.footTemplate+'
'+c.headTemplate+c.contTemplate+c.footTemplate+'
'+c.headTemplate+c.contTemplate+c.footTemplate+"
",b.fn.datetimepicker.DPGlobal=c,b.fn.datetimepicker.noConflict=function(){return b.fn.datetimepicker=old,this},b(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(h){var g=b(this);g.data("datetimepicker")||(h.preventDefault(),g.datetimepicker("show"))}),b(function(){b('[data-provide="datetimepicker-inline"]').datetimepicker()})}(window.jQuery), -/*! bootbox.js v4.4.0 http://bootboxjs.com/license.txt */ -function(a,b){"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function t(B,x){function q(a){var c=v[A.locale];return c?c[a]:v.en[a]}function G(c,a,e){c.stopPropagation(),c.preventDefault();var d=B.isFunction(e)&&e.call(a,c)===!1;d||a.modal("hide")}function k(c){var d,a=0;for(d in c){a++}return a}function E(c,a){var d=0;B.each(c,function(f,g){a(f,g,d++)})}function b(c){var a,d;if("object"!=typeof c){throw new Error("Please supply an object of options")}if(!c.message){throw new Error("Please specify a message")}return c=B.extend({},A,c),c.buttons||(c.buttons={}),a=c.buttons,d=k(a),E(a,function(e,f,g){if(B.isFunction(f)&&(f=a[e]={callback:f}),"object"!==B.type(f)){throw new Error("button with key "+e+" must be an object")}f.label||(f.label=e),f.className||(2===d&&("ok"===e||"confirm"===e)||1===d?f.className="btn-primary":f.className="btn-default")}),c}function w(c,d){var a=c.length,f={};if(a<1||a>2){throw new Error("Invalid argument length")}return 2===a||"string"==typeof c[0]?(f[d[0]]=c[0],f[d[1]]=c[1]):f=c[0],f}function y(c,a,d){return B.extend(!0,{},c,w(a,d))}function D(c,f,a,g){var d={className:"bootbox-"+c,buttons:C.apply(null,f)};return F(y(d,g,a),f)}function C(){for(var f={},h=0,d=arguments.length;h",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},A={locale:B.zui&&B.zui.clientLang?B.zui.clientLang():"zh_cn",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},z={};z.alert=function(){var a;if(a=D("alert",["ok"],["message","callback"],arguments),a.callback&&!B.isFunction(a.callback)){throw new Error("alert requires callback property to be a function when provided")}return a.buttons.ok.callback=a.onEscape=function(){return !B.isFunction(a.callback)||a.callback.call(this)},z.dialog(a)},z.confirm=function(){var a;if(a=D("confirm",["confirm","cancel"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!B.isFunction(a.callback)){throw new Error("confirm requires a callback")}return z.dialog(a)},z.prompt=function(){var H,e,I,d,a,h,u;if(d=B(j.form),e={className:"bootbox-prompt",buttons:C("cancel","confirm"),value:"",inputType:"text"},H=F(y(e,arguments,["title","callback"]),["confirm","cancel"]),h=H.show===x||H.show,H.message=d,H.buttons.cancel.callback=H.onEscape=function(){return H.callback.call(this,null)},H.buttons.confirm.callback=function(){var c;switch(H.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=a.val();break;case"checkbox":var f=a.find("input:checked");c=[],E(f,function(l,m){c.push(B(m).val())})}return H.callback.call(this,c)},H.show=!1,!H.title){throw new Error("prompt requires a title")}if(!B.isFunction(H.callback)){throw new Error("prompt requires a callback")}if(!j.inputs[H.inputType]){throw new Error("invalid prompt type")}switch(a=B(j.inputs[H.inputType]),H.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":a.val(H.value);break;case"select":var p={};if(u=H.inputOptions||[],!B.isArray(u)){throw new Error("Please pass an array of input options")}if(!u.length){throw new Error("prompt with select requires options")}E(u,function(c,l){var f=a;if(l.value===x||l.text===x){throw new Error("given options in wrong format")}l.group&&(p[l.group]||(p[l.group]=B("").attr("label",l.group)),f=p[l.group]),f.append("")}),E(p,function(c,f){a.append(f)}),a.val(H.value);break;case"checkbox":var g=B.isArray(H.value)?H.value:[H.value];if(u=H.inputOptions||[],!u.length){throw new Error("prompt with checkbox requires options")}if(!u[0].value||!u[0].text){throw new Error("given options in wrong format")}a=B("
"),E(u,function(c,l){var f=B(j.inputs[H.inputType]);f.find("input").attr("value",l.value),f.find("label").append(l.text),E(g,function(m,n){n===l.value&&f.find("input").prop("checked",!0)}),a.append(f)})}return H.placeholder&&a.attr("placeholder",H.placeholder),H.pattern&&a.attr("pattern",H.pattern),H.maxlength&&a.attr("maxlength",H.maxlength),d.append(a),d.on("submit",function(c){c.preventDefault(),c.stopPropagation(),I.find(".btn-primary").click()}),I=z.dialog(H),I.off("shown.zui.modal"),I.on("shown.zui.modal",function(){a.focus()}),h===!0&&I.modal("show"),I},z.dialog=function(f){f=b(f);var s=B(j.dialog),p=s.find(".modal-dialog"),a=s.find(".modal-body"),g=f.buttons,r="",m={onEscape:f.onEscape};if(B.fn.modal===x){throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.")}if(E(g,function(c,d){r+="",m[c]=d.callback}),a.find(".bootbox-body").html(f.message),f.animate===!0&&s.addClass("fade"),f.className&&s.addClass(f.className),"large"===f.size?p.addClass("modal-lg"):"small"===f.size&&p.addClass("modal-sm"),f.title&&a.before(j.header),f.closeButton){var e=B(j.closeButton);f.title?s.find(".modal-header").prepend(e):e.css("margin-top","-10px").prependTo(a)}return f.title&&s.find(".modal-title").html(f.title),r.length&&(a.after(j.footer),s.find(".modal-footer").html(r)),s.on("hidden.zui.modal",function(c){c.target===this&&s.remove()}),s.on("shown.zui.modal",function(){s.find(".btn-primary:first").focus()}),"static"!==f.backdrop&&s.on("click.dismiss.zui.modal",function(c){s.children(".modal-backdrop").length&&(c.currentTarget=s.children(".modal-backdrop").get(0)),c.target===c.currentTarget&&s.trigger("escape.close.bb")}),s.on("escape.close.bb",function(c){m.onEscape&&G(c,s,m.onEscape)}),s.on("click",".modal-footer button",function(d){var c=B(this).data("bb-handler");G(d,s,m[c])}),s.on("click",".bootbox-close-button",function(c){G(c,s,m.onEscape)}),s.on("keyup",function(c){27===c.which&&s.trigger("escape.close.bb")}),B(f.container).append(s),s.modal({backdrop:!!f.backdrop&&"static",keyboard:!1,show:!1}),f.show&&s.modal("show"),s},z.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],B.extend(A,a)},z.hideAll=function(){return B(".bootbox").modal("hide"),z};var v={en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},zh_cn:{OK:"确认",CANCEL:"取消",CONFIRM:"确认"},zh_tw:{OK:"確認",CANCEL:"取消",CONFIRM:"確認"}};return z.addLocale=function(c,a){return B.each(["OK","CANCEL","CONFIRM"],function(d,f){if(!a[f]){throw new Error("Please supply a translation for '"+f+"'")}}),v[c]={OK:a.OK,CANCEL:a.CANCEL,CONFIRM:a.CONFIRM},z},z.removeLocale=function(a){return delete v[a],z},z.setLocale=function(a){return z.setDefaults("locale",a)},z.init=function(a){return t(a||B)},z}), -/*! -Chosen, a Select Box Enhancer for jQuery and Prototype -by Patrick Filler for Harvest, http://getharvest.com - -Version 1.1.0 -Full source at https://github.com/harvesthq/chosen -Copyright (c) 2011 Harvest http://getharvest.com - -MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md -*/ -function(){var d,h,c,k,f,j={}.hasOwnProperty,b=function(l,m){function a(){this.constructor=l}for(var o in m){j.call(m,o)&&(l[o]=m[o])}return a.prototype=m.prototype,l.prototype=new a,l.__super__=m.prototype,l},g={zh_cn:{no_results_text:"没有找到"},zh_tw:{no_results_text:"沒有找到"},en:{no_results_text:"No results match"}};k=function(){function a(){this.options_index=0,this.parsed=[]}return a.prototype.add_node=function(e){return"OPTGROUP"===e.nodeName.toUpperCase()?this.add_group(e):this.add_option(e)},a.prototype.add_group=function(u){var m,w,p,v,l,q;for(m=this.parsed.length,this.parsed.push({array_index:m,group:!0,label:this.escapeExpression(u.label),children:0,disabled:u.disabled,title:u.title,search_keys:d.trim(u.getAttribute("data-keys")||"").replace(/,/g," ")}),l=u.childNodes,q=[],p=0,v=l.length;p\"\'\`]/.test(m)?(n={"<":"<",">":">",'"':""","'":"'","`":"`"},l=/&(?!\w+;)|[\<\>\"\'\`]/g,m.replace(l,function(e){return n[e]||"&"})):m},a}(),k.select_to_array=function(n){var q,m,p,r,l;for(m=new k,l=n.childNodes,p=0,r=l.length;p0?(m=document.createElement("li"),m.className="group-result",m.title=l.title,m.innerHTML=l.search_text,this.outerHTML(m)):""},a.prototype.results_update_field=function(){if(this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing){return this.winnow_results()}},a.prototype.reset_single_select_options=function(){var m,p,l,q,o;for(q=this.results_data,o=[],p=0,l=q.length;p"+y.search_text.substr(x+m.length),y.search_text=z.substr(0,x)+""+z.substr(x)):y.search_keys_match&&y.search_keys.length&&(x=y.search_keys.search(C),z=y.search_keys.substr(0,x+m.length)+""+y.search_keys.substr(x+m.length),y.search_text+='  '+z.substr(0,x)+""+z.substr(x)+""),null!=D&&(D.group_match=!0)):null!=y.group_array_index&&this.results_data[y.group_array_index].search_match&&(y.search_match=!0)))}return this.result_clear_highlight(),v<1&&m.length?(this.update_results_content(""),this.no_results(m)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight(F))},a.prototype.search_string_match=function(m,q){var l,u,p,r;if(q.test(m)){return !0}if(this.enable_split_word_search&&(m.indexOf(" ")>=0||0===m.indexOf("["))&&(u=m.replace(/\[|\]/g,"").split(" "),u.length)){for(p=0,r=u.length;p0){return this.keydown_backstroke()}if(!this.pending_backstroke){return this.result_clear_highlight(),this.results_search()}break;case 13:if(m.preventDefault(),this.results_showing){return this.result_select(m)}break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},a.prototype.clipboard_event_checker=function(l){var m=this;return setTimeout(function(){return m.results_search()},50)},a.prototype.container_width=function(){return null!=this.options.width?this.options.width:this.form_field&&this.form_field.classList&&this.form_field.classList.contains("form-control")?"100%":""+this.form_field.offsetWidth+"px"},a.prototype.include_option_in_results=function(e){return !(this.is_multiple&&!this.display_selected_options&&e.selected)&&(!(!this.display_disabled_options&&e.disabled)&&!e.empty)},a.prototype.search_results_touchstart=function(e){return this.touch_started=!0,this.search_results_mouseover(e)},a.prototype.search_results_touchmove=function(e){return this.touch_started=!1,this.search_results_mouseout(e)},a.prototype.search_results_touchend=function(e){if(this.touch_started){return this.search_results_mouseup(e)}},a.prototype.outerHTML=function(l){var m;return l.outerHTML?l.outerHTML:(m=document.createElement("div"),m.appendChild(l),m.innerHTML)},a.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!/iP(od|hone)/i.test(window.navigator.userAgent)&&(!/Android/i.test(window.navigator.userAgent)||!/Mobile/i.test(window.navigator.userAgent))},a.default_multiple_text="",a.default_single_text="",a.default_no_result_text="No results match",a}(),d=jQuery,d.fn.extend({chosen:function(a){return h.browser_is_supported()?this.each(function(m){var l,n;l=d(this),n=l.data("chosen"),"destroy"===a&&n?n.destroy():n||l.data("chosen",new c(this,a))}):this}}),c=function(l){function a(){return f=a.__super__.constructor.apply(this,arguments)}return b(a,l),a.prototype.setup=function(){return this.form_field_jq=d(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},a.prototype.set_up_html=function(){var o,m;o=["chosen-container"],o.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&o.push(this.form_field.className),this.is_rtl&&o.push("chosen-rtl");var p=this.form_field.getAttribute("data-css-class");return p&&o.push(p),m={"class":o.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(m.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=d("
",m),this.is_multiple?this.container.html('
    '):this.container.html(''+this.default_text+'
      '),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.options.drop_width&&this.dropdown.css("width",this.options.drop_width).addClass("chosen-drop-size-limited"),this.results_build(),this.set_tab_index(),this.set_label_behavior(),this.form_field_jq.trigger("chosen:ready",{chosen:this})},a.prototype.register_observers=function(){var e=this;return this.container.bind("mousedown.chosen",function(m){e.container_mousedown(m)}),this.container.bind("mouseup.chosen",function(m){e.container_mouseup(m)}),this.container.bind("mouseenter.chosen",function(m){e.mouse_enter(m)}),this.container.bind("mouseleave.chosen",function(m){e.mouse_leave(m)}),this.search_results.bind("mouseup.chosen",function(m){e.search_results_mouseup(m)}),this.search_results.bind("mouseover.chosen",function(m){e.search_results_mouseover(m)}),this.search_results.bind("mouseout.chosen",function(m){e.search_results_mouseout(m)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(m){e.search_results_mousewheel(m)}),this.search_results.bind("touchstart.chosen",function(m){e.search_results_touchstart(m)}),this.search_results.bind("touchmove.chosen",function(m){e.search_results_touchmove(m)}),this.search_results.bind("touchend.chosen",function(m){e.search_results_touchend(m)}),this.form_field_jq.bind("chosen:updated.chosen",function(m){e.results_update_field(m)}),this.form_field_jq.bind("chosen:activate.chosen",function(m){e.activate_field(m)}),this.form_field_jq.bind("chosen:open.chosen",function(m){e.container_mousedown(m)}),this.form_field_jq.bind("chosen:close.chosen",function(m){e.input_blur(m)}),this.search_field.bind("blur.chosen",function(m){e.input_blur(m)}),this.search_field.bind("keyup.chosen",function(m){e.keyup_checker(m)}),this.search_field.bind("keydown.chosen",function(m){e.keydown_checker(m)}),this.search_field.bind("focus.chosen",function(m){e.input_focus(m)}),this.search_field.bind("cut.chosen",function(m){e.clipboard_event_checker(m)}),this.search_field.bind("paste.chosen",function(m){e.clipboard_event_checker(m)}),this.is_multiple?this.search_choices.bind("click.chosen",function(m){e.choices_click(m)}):this.container.bind("click.chosen",function(m){m.preventDefault()})},a.prototype.destroy=function(){return d(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},a.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},a.prototype.container_mousedown=function(m){if(!this.is_disabled&&(m&&"mousedown"===m.type&&!this.results_showing&&m.preventDefault(),null==m||!d(m.target).hasClass("search-choice-close"))){return this.active_field?this.is_multiple||!m||d(m.target)[0]!==this.selected_item[0]&&!d(m.target).parents("a.chosen-single").length||(m.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),d(this.container[0].ownerDocument).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field()}},a.prototype.container_mouseup=function(e){if("ABBR"===e.target.nodeName&&!this.is_disabled){return this.results_reset(e)}},a.prototype.search_results_mousewheel=function(m){var n;if(m.originalEvent&&(n=-m.originalEvent.wheelDelta||m.originalEvent.detail),null!=n){return m.preventDefault(),"DOMMouseScroll"===m.type&&(n=40*n),this.search_results.scrollTop(n+this.search_results.scrollTop())}},a.prototype.blur_test=function(e){if(!this.active_field&&this.container.hasClass("chosen-container-active")){return this.close_field()}},a.prototype.close_field=function(){return d(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},a.prototype.activate_field=function(){this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val())},a.prototype.test_active_click=function(n){var m;return m=d(n.target).closest(".chosen-container"),m.length&&this.container[0]===m[0]?this.active_field=!0:this.close_field()},a.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=k.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},a.prototype.result_do_highlight=function(y,w){var v,q,z,p,x,m,u=-1;y.length&&(this.result_clear_highlight(),this.result_highlight=y,this.result_highlight.addClass("highlighted"),z=parseInt(this.search_results.css("maxHeight"),10),m=this.result_highlight.outerHeight(),x=this.search_results.scrollTop(),p=z+x,q=this.result_highlight.position().top+this.search_results.scrollTop(),v=q+m,this.middle_highlight&&(w||"always"===this.middle_highlight||v>=p||q=p?u=v-z>0?v-z:0:q-1&&this.search_results.scrollTop(u))},a.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},a.prototype.results_show=function(){if(this.is_multiple&&this.max_selected_options<=this.choices_count()){return this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1}this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results(1);var o=this.drop_direction;if(d.isFunction(o)&&(o=o.call(this)),"auto"===o){if(this.drop_directionFixed){o=this.drop_directionFixed}else{var m=this.container.find(".chosen-drop"),p=this.container.offset();p.top+m.outerHeight()+30>d(window).height()+d(window).scrollTop()&&(o="up"),this.drop_directionFixed=o}}return this.container.toggleClass("chosen-up","up"===o).addClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this})},a.prototype.update_results_content=function(e){return this.search_results.html(e)},a.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this}),this.drop_directionFixed=0),this.results_showing=!1},a.prototype.set_tab_index=function(m){var n;if(this.form_field.tabIndex){return n=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=n}},a.prototype.set_label_behavior=function(){var m=this;if(this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=d("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0){return this.form_field_label.bind("click.chosen",function(e){return m.is_multiple?m.container_mousedown(e):m.activate_field()})}},a.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},a.prototype.search_results_mouseup=function(n){var m;m=d(n.target).hasClass("active-result")?d(n.target):d(n.target).parents(".active-result").first(),m.length&&(this.result_highlight=m,this.result_select(n))},a.prototype.search_results_mouseover=function(n){var m;if(m=d(n.target).hasClass("active-result")?d(n.target):d(n.target).parents(".active-result").first()){return this.result_do_highlight(m)}},a.prototype.search_results_mouseout=function(m){if(d(m.target).hasClass("active-result")){return this.result_clear_highlight()}},a.prototype.choice_build=function(p){var m,q,o=this;return m=d("
    • ",{"class":"search-choice"}).html(""+p.html+""),p.disabled?m.addClass("search-choice-disabled"):(q=d("",{"class":"search-choice-close","data-option-array-index":p.array_index}),q.bind("click.chosen",function(e){return o.choice_destroy_link_click(e)}),m.append(q)),this.search_container.before(m)},a.prototype.choice_destroy_link_click=function(m){if(m.preventDefault(),m.stopPropagation(),!this.is_disabled){return this.choice_destroy(d(m.target))}},a.prototype.choice_destroy=function(e){if(this.result_deselect(e[0].getAttribute("data-option-array-index"))){return this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),e.parents("li").first().remove(),this.search_field_scale()}},a.prototype.results_reset=function(){if(this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change"),this.active_field){return this.results_hide()}},a.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},a.prototype.result_select=function(n){var o,m;if(this.result_highlight){return o=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?o.removeClass("active-result"):this.reset_single_select_options(),m=this.results_data[o[0].getAttribute("data-option-array-index")],m.selected=!0,this.form_field.options[m.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(m):this.single_set_selected_text(m.text),(n.metaKey||n.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[m.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,this.search_field_scale())}},a.prototype.single_set_selected_text=function(e){return null==e&&(e=this.default_text),e===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").attr("title",e).text(e)},a.prototype.result_deselect=function(m){var n;return n=this.results_data[m],!this.form_field.options[n.options_index].disabled&&(n.selected=!1,this.form_field.options[n.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[n.options_index].value}),this.search_field_scale(),!0)},a.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect){return this.selected_item.find("abbr").length||this.selected_item.find("span").first().after(''),this.selected_item.addClass("chosen-single-with-deselect")}},a.prototype.get_search_text=function(){return this.search_field.val()===this.default_text?"":d("
      ").text(d.trim(this.search_field.val())).html()},a.prototype.winnow_results_set_highlight=function(n){var o,m;if(m=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),o=m.length?m.first():this.search_results.find(".active-result").first(),null!=o){return this.result_do_highlight(o,n)}},a.prototype.no_results=function(n){var m;return m=d('
    • '+this.results_none_found+' ""
    • '),m.find("span").first().html(n),this.search_results.append(m),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},a.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},a.prototype.keydown_arrow=function(){var e;return this.results_showing&&this.result_highlight?(e=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(e):void 0:this.results_show()},a.prototype.keyup_arrow=function(){var e;return this.results_showing||this.is_multiple?this.result_highlight?(e=this.result_highlight.prevAll("li.active-result"),e.length?this.result_do_highlight(e.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},a.prototype.keydown_backstroke=function(){var e;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(e=this.search_container.siblings("li.search-choice").last(),e.length&&!e.hasClass("search-choice-disabled")?(this.pending_backstroke=e,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},a.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},a.prototype.keydown_checker=function(n){var o,m;switch(o=null!=(m=n.which)?m:n.keyCode,this.search_field_scale(),8!==o&&this.pending_backstroke&&this.clear_backstroke(),o){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(n),this.mouse_on_container=!1;break;case 13:n.preventDefault();break;case 38:n.preventDefault(),this.keyup_arrow();break;case 40:n.preventDefault(),this.keydown_arrow()}},a.prototype.search_field_scale=function(){var x,v,q,z,p,y,m,u,w;if(this.is_multiple){for(q=0,m=0,p="position:absolute; left: -1000px; top: -1000px; display:none;",y=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],u=0,w=y.length;u",{style:p}),x.text(this.search_field.val()),d("body").append(x),m=x.width()+25,x.remove(),v=this.container.outerWidth(),m>v-10&&(m=v-10),this.search_field.css({width:m+"px"})}},a}(h)}.call(this),function(b){var d="zui.selectable",a=function(e,g){this.name=d,this.$=b(e),this.id=b.zui.uuid(),this.selectOrder=1,this.selections={},this.getOptions(g),this._init()},f=function(h,j,g){return h>=g.left&&h<=g.left+g.width&&j>=g.top&&j<=g.top+g.height},c=function(j,l){var h=Math.max(j.left,l.left),k=Math.max(j.top,l.top),m=Math.min(j.left+j.width,l.left+l.width),g=Math.min(j.top+j.height,l.top+l.height);return f(h,k,j)&&f(m,g,j)&&f(h,k,l)&&f(m,g,l)};a.DEFAULTS={selector:"li,tr,div",trigger:"",selectClass:"active",rangeStyle:{border:"1px solid "+(b.zui.colorset?b.zui.colorset.primary:"#3280fc"),backgroundColor:b.zui.colorset?new b.zui.Color(b.zui.colorset.primary).fade(20).toCssStr():"rgba(50, 128, 252, 0.2)"},clickBehavior:"toggle",ignoreVal:3,listenClick:!0},a.prototype.getOptions=function(g){this.options=b.extend({},a.DEFAULTS,this.$.data(),g)},a.prototype.select=function(e){this.toggle(e,!0)},a.prototype.unselect=function(e){this.toggle(e,!1)},a.prototype.toggle=function(p,j,u){var k,q,h=this.options.selector,m=this;if(void 0===p){return void this.$.find(h).each(function(){m.toggle(this,j)})}if("object"==typeof p?(k=b(p).closest(h),q=k.data("id")):(q=p,k=m.$.find('.slectable-item[data-id="'+q+'"]')),k&&k.length){if(q||(q=b.zui.uuid(),k.attr("data-id",q)),void 0!==j&&null!==j||(j=!m.selections[q]),!!j!=!!m.selections[q]){var g;b.isFunction(u)&&(g=u(j)),g!==!0&&(m.selections[q]=!!j&&m.selectOrder++,m.callEvent(j?"select":"unselect",{id:q,selections:m.selections,target:k,selected:m.getSelectedArray()},m))}m.options.selectClass&&k.toggleClass(m.options.selectClass,j)}},a.prototype.getSelectedArray=function(){var g=[];return b.each(this.selections,function(h,e){e&&g.push(h)}),g},a.prototype.syncSelectionsFromClass=function(){var g=this;g.$children=g.$.find(g.options.selector);g.selections={},g.$children.each(function(){var e=b(this);g.selections[e.data("id")]=e.hasClass(g.options.selectClass)})},a.prototype._init=function(){var M,I,F,E,Q,B,H,J=this.options,O=this,N=J.ignoreVal,z=!0,D="."+this.name+"."+this.id,L=b.isFunction(J.checkFunc)?J.checkFunc:null,K=b.isFunction(J.rangeFunc)?J.rangeFunc:null,G=!1,s=null,j="mousedown"+D,P=function(){E&&O.$children.each(function(){var l=b(this),h=l.offset();h.width=l.outerWidth(),h.height=l.outerHeight();var m=K?K.call(this,E,h):c(E,h);if(L){var g=L.call(O,{intersect:m,target:l,range:E,targetRange:h});g===!0?O.select(l):g===!1&&O.unselect(l)}else{m?O.select(l):O.multiKey||O.unselect(l)}})},q=function(e){G&&(Q=e.pageX,B=e.pageY,E={width:Math.abs(Q-M),height:Math.abs(B-I),left:Q>M?M:Q,top:B>I?I:B},z&&E.width
      ').css(b.extend({zIndex:1060,position:"absolute",top:M,left:I,pointerEvents:"none"},O.options.rangeStyle)).appendTo(b("body")))),F.css(E),clearTimeout(H),H=setTimeout(P,10),z=!1))},k=function(g){b(document).off(D),clearTimeout(s),G&&(G=!1,F&&F.remove(),z||E&&(clearTimeout(H),P(),E=null),O.callEvent("finish",{selections:O.selections,selected:O.getSelectedArray()}),g.preventDefault())},A=function(g){if(G){return k(g)}var l=b.zui.getMouseButtonCode(J.mouseButton);if(!(l>-1&&g.button!==l||O.altKey||3===g.which||O.callEvent("start",g)===!1)){var e=O.$children=O.$.find(J.selector);e.addClass("slectable-item");var h=O.multiKey?"multi":J.clickBehavior;if("single"===h&&O.unselect(),J.listenClick&&("multi"===h?O.toggle(g.target):"single"===h?O.select(g.target):"toggle"===h&&O.toggle(g.target,null,function(m){O.unselect()})),O.callEvent("startDrag",g)===!1){return void O.callEvent("finish",{selections:O.selections,selected:O.getSelectedArray()})}M=g.pageX,I=g.pageY,F=null,z=!0,G=!0,b(document).on("mousemove"+D,q).on("mouseup"+D,k),s=setTimeout(function(){b(document).on(j,k)},10),g.preventDefault()}},R=J.container&&"default"!==J.container?b(J.container):this.$;J.trigger?R.on(j,J.trigger,A):R.on(j,A),b(document).on("keydown",function(g){var h=g.keyCode;17===h||91==h?O.multiKey=h:18===h&&(O.altKey=!0)}).on("keyup",function(e){O.multiKey=!1,O.altKey=!1})},a.prototype.callEvent=function(j,g){var l=b.Event(j+"."+this.name);this.$.trigger(l,g);var h=l.result,k=this.options[j];return b.isFunction(k)&&(h=k.apply(this,b.isArray(g)?g:[g])),h},b.fn.selectable=function(e){return this.each(function(){var h=b(this),j=h.data(d),g="object"==typeof e&&e;j||h.data(d,j=new a(this,g)),"string"==typeof e&&j[e]()})},b.fn.selectable.Constructor=a,b(function(){b('[data-ride="selectable"]').selectable()})}(jQuery),+function(d,g,c){if(!d.fn.droppable){return void console.error("Sortable requires droppable.js")}var j="zui.sortable",f={selector:"li,div",dragCssClass:"invisible",sortingClass:"sortable-sorting"},h="order",b=function(k,a){var l=this;l.$=d(k),l.options=d.extend({},f,l.$.data(),a),l.init()};b.DEFAULTS=f,b.NAME=j,b.prototype.init=function(){var v,p=this,m=p.$,A=p.options,y=A.selector,k=A.containerSelector,o=A.sortingClass,q=A.dragCssClass,x=A.targetSelector,w=A.reverse,z=function(a){a=a||p.getItems(1);var l=a.length;l&&a.each(function(r){var n=w?l-r:r;d(this).attr("data-"+h,n).data(h,n)})};z(),m.droppable({handle:A.trigger,target:x?x:k?y+","+k:y,selector:y,container:m,always:A.always,flex:!0,lazy:A.lazy,canMoveHere:A.canMoveHere,dropToClass:A.dropToClass,before:A.before,nested:!!k,mouseButton:A.mouseButton,stopPropagation:A.stopPropagation,start:function(a){q&&a.element.addClass(q),v=!1,p.trigger("start",a)},drag:function(a){if(m.addClass(o),a.isIn){var l=a.element,e=a.target,B=k&&e.is(k);if(B){if(!e.children(y).filter(".dragging").length){e.append(l);var u=p.getItems(1);z(u),p.trigger(h,{list:u,element:l})}return}var r=l.data(h),n=e.data(h);if(r===n){return z(u)}r>n?e[w?"after":"before"](l):e[w?"before":"after"](l),v=!0;var u=p.getItems(1);z(u),p.trigger(h,{list:u,element:l})}},finish:function(a){q&&a.element&&a.element.removeClass(q),m.removeClass(o),p.trigger("finish",{list:p.getItems(),element:a.element,changed:v})}})},b.prototype.destroy=function(){this.$.droppable("destroy"),this.$.data(j,null)},b.prototype.reset=function(){this.destroy(),this.init()},b.prototype.getItems=function(k){var a=this.$.find(this.options.selector).not(".drag-shadow");return k?a:a.map(function(){var l=d(this);return{item:l,order:l.data("order")}})},b.prototype.trigger=function(k,a){return d.zui.callEvent(this.options[k],a,this)},d.fn.sortable=function(a){return this.each(function(){var e=d(this),k=e.data(j),l="object"==typeof a&&a;k?"object"==typeof a&&k.reset():e.data(j,k=new b(this,l)),"string"==typeof a&&k[a]()})},d.fn.sortable.Constructor=b}(jQuery,window,document), -/*! - * jQuery Form Plugin - * version: 4.2.2 - * Requires jQuery v1.7.2 or later - * Project repository: https://github.com/jquery-form/form - - * Copyright 2017 Kevin Morris - * Copyright 2006 M. Alsup - - * Dual licensed under the LGPL-2.1+ or MIT licenses - * https://github.com/jquery-form/form#license - - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ -!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(c,b){return void 0===b&&(b="undefined"!=typeof window?require("jquery"):require("jquery")(c)),a(b),b}:a(jQuery)}(function(t){function e(e){var i=e.data;e.isDefaultPrevented()||(e.preventDefault(),t(e.target).closest("form").ajaxSubmit(i))}function i(e){var i=e.target,n=t(i);if(!n.is("[type=submit],[type=image]")){var s=n.closest("[type=submit]");if(0===s.length){return}i=s[0]}var o=i.form;if(o.clk=i,"image"===i.type){if(void 0!==e.offsetX){o.clk_x=e.offsetX,o.clk_y=e.offsetY}else{if("function"==typeof t.fn.offset){var a=n.offset();o.clk_x=e.pageX-a.left,o.clk_y=e.pageY-a.top}else{o.clk_x=e.pageX-i.offsetLeft,o.clk_y=e.pageY-i.offsetTop}}}setTimeout(function(){o.clk=o.clk_x=o.clk_y=null},100)}function n(){if(t.fn.ajaxSubmit.debug){var e="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(e):window.opera&&window.opera.postError&&window.opera.postError(e)}}var s=/\r?\n/g,o={};o.fileapi=void 0!==t('').get(0).files,o.formdata=void 0!==window.FormData;var a=!!t.fn.prop;t.fn.attr2=function(){if(!a){return this.attr.apply(this,arguments)}var t=this.prop.apply(this,arguments);return t&&t.jquery||"string"==typeof t?t:this.attr.apply(this,arguments)},t.fn.ajaxSubmit=function(e,i,s,r){function l(i){var n,s,o=t.param(i,e.traditional).split("&"),a=o.length,r=[];for(n=0;n',T).val(d.extraData[l].value).appendTo(_)[0]):a.push(h('',T).val(d.extraData[l]).appendTo(_)[0]))}}d.iframeTarget||g.appendTo(S),m.attachEvent?m.attachEvent("onload",r):m.addEventListener("load",r,!1),setTimeout(t,15);try{_.submit()}catch(h){document.createElement("form").submit.apply(_)}}finally{_.setAttribute("action",i),_.setAttribute("enctype",o),e?_.setAttribute("target",e):p.removeAttr("target"),h(a).remove()}}function r(t){if(!y.aborted&&!I){if((z=s(m))||(n("cannot access response document"),t=M),t===D&&y){return y.abort("timeout"),void k.reject(y,"timeout")}if(t===M&&y){return y.abort("server abort"),void k.reject(y,"error","server abort")}if(z&&z.location.href!==d.iframeSrc||x){m.detachEvent?m.detachEvent("onload",r):m.removeEventListener("load",r,!1);var e,i="success";try{if(x){throw"timeout"}var o="xml"===d.dataType||z.XMLDocument||v.isXMLDoc(z);if(n("isXml="+o),!o&&window.opera&&(null===z.body||!z.body.innerHTML)&&--E){return n("requeing onLoad callback, DOM not available"),void setTimeout(r,250)}var a=z.body?z.body:z.documentElement;y.responseText=a?a.innerHTML:null,y.responseXML=z.XMLDocument?z.XMLDocument:z,o&&(d.dataType="xml"),y.getResponseHeader=function(t){return{"content-type":d.dataType}[t.toLowerCase()]},a&&(y.status=Number(a.getAttribute("status"))||y.status,y.statusText=a.getAttribute("statusText")||y.statusText);var l=(d.dataType||"").toLowerCase(),h=/(json|script|text)/.test(l);if(h||d.textarea){var c=z.getElementsByTagName("textarea")[0];if(c){y.responseText=c.value,y.status=Number(c.getAttribute("status"))||y.status,y.statusText=c.getAttribute("statusText")||y.statusText}else{if(h){var p=z.getElementsByTagName("pre")[0],f=z.getElementsByTagName("body")[0];p?y.responseText=p.textContent?p.textContent:p.innerText:f&&(y.responseText=f.textContent?f.textContent:f.innerText)}}}else{"xml"===l&&!y.responseXML&&y.responseText&&(y.responseXML=$(y.responseText))}try{L=j(y,l,d)}catch(v){i="parsererror",y.error=e=v||i}}catch(v){n("error caught: ",v),i="error",y.error=e=v||i}y.aborted&&(n("upload aborted"),i=null),y.status&&(i=y.status>=200&&y.status<300||304===y.status?"success":"error"),"success"===i?(d.success&&d.success.call(d.context,L,"success",y),k.resolve(y.responseText,"success",y),u&&v.event.trigger("ajaxSuccess",[y,d])):i&&(void 0===e&&(e=y.statusText),d.error&&d.error.call(d.context,y,i,e),k.reject(y,"error",e),u&&v.event.trigger("ajaxError",[y,d,e])),u&&v.event.trigger("ajaxComplete",[y,d]),u&&!--v.active&&v.event.trigger("ajaxStop"),d.complete&&d.complete.call(d.context,y,i),I=!0,d.timeout&&clearTimeout(C),setTimeout(function(){d.iframeTarget?g.attr("src",d.iframeSrc):g.remove(),y.responseXML=null},100)}}}var l,h,d,u,f,g,m,y,b,w,x,C,_=p[0],k=t.Deferred();if(k.abort=function(t){y.abort(t)},i){for(h=0;h',T)).css({position:"absolute",top:"-1000px",left:"-1000px"}),m=g[0],y={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var e="timeout"===t?"timeout":"aborted";n("aborting upload... "+e),this.aborted=1;try{m.contentWindow.document.execCommand&&m.contentWindow.document.execCommand("Stop")}catch(i){}g.attr("src",d.iframeSrc),y.error=e,d.error&&d.error.call(d.context,y,e,t),u&&i.event.trigger("ajaxError",[y,d,e]),d.complete&&d.complete.call(d.context,y,e)}},(u=d.global)&&0==t.active++&&t.event.trigger("ajaxStart"),u&&t.event.trigger("ajaxSend",[y,d]),d.beforeSend&&!1===d.beforeSend.call(d.context,y,d)){return d.global&&t.active--,k.reject(),k}if(y.aborted){return k.reject(),k}(b=_.clk)&&(w=b.name)&&!b.disabled&&(d.extraData=d.extraData||{},d.extraData[w]=b.value,"image"===b.type&&(d.extraData[w+".x"]=_.clk_x,d.extraData[w+".y"]=_.clk_y));var D=1,M=2,P=t("meta[name=csrf-token]").attr("content"),F=t("meta[name=csrf-param]").attr("content");F&&P&&(d.extraData=d.extraData||{},d.extraData[F]=P),d.forceSync?o():setTimeout(o,10);var L,z,I,E=50,$=t.parseXML||function(t,e){return window.ActiveXObject?((e=new ActiveXObject("Microsoft.XMLDOM")).async="false",e.loadXML(t)):e=(new DOMParser).parseFromString(t,"text/xml"),e&&e.documentElement&&"parsererror"!==e.documentElement.nodeName?e:null},A=t.parseJSON||function(t){return window.eval("("+t+")")},j=function(e,i,n){var s=e.getResponseHeader("content-type")||"",o=("xml"===i||!i)&&s.indexOf("xml")>=0,a=o?e.responseXML:e.responseText;return o&&"parsererror"===a.documentElement.nodeName&&t.error&&t.error("parsererror"),n&&n.dataFilter&&(a=n.dataFilter(a,i)),"string"==typeof a&&(("json"===i||!i)&&s.indexOf("json")>=0?a=A(a):("script"===i||!i)&&s.indexOf("javascript")>=0&&t.globalEval(a)),a};return k}if(!this.length){return n("ajaxSubmit: skipping submit process - no element selected"),this}var c,d,u,p=this;"function"==typeof e?e={success:e}:"string"==typeof e||!1===e&&arguments.length>0?(e={url:e,data:i,dataType:s},"function"==typeof r&&(e.success=r)):void 0===e&&(e={}),c=e.method||e.type||this.attr2("method"),(u=(u="string"==typeof(d=e.url||this.attr2("action"))?t.trim(d):"")||window.location.href||"")&&(u=(u.match(/^([^#]+)/)||[])[1]),e=t.extend(!0,{url:u,success:t.ajaxSettings.success,type:c||t.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},e);var f={};if(this.trigger("form-pre-serialize",[this,e,f]),f.veto){return n("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this}if(e.beforeSerialize&&!1===e.beforeSerialize(this,e)){return n("ajaxSubmit: submit aborted via beforeSerialize callback"),this}var g=e.traditional;void 0===g&&(g=t.ajaxSettings.traditional);var m,v=[],y=this.formToArray(e.semantic,v,e.filtering);if(e.data){var b=t.isFunction(e.data)?e.data(y):e.data;e.extraData=b,m=t.param(b,g)}if(e.beforeSubmit&&!1===e.beforeSubmit(y,this,e)){return n("ajaxSubmit: submit aborted via beforeSubmit callback"),this}if(this.trigger("form-submit-validate",[y,this,e,f]),f.veto){return n("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this}var w=t.param(y,g);m&&(w=w?w+"&"+m:m),"GET"===e.type.toUpperCase()?(e.url+=(e.url.indexOf("?")>=0?"&":"?")+w,e.data=null):e.data=w;var x=[];if(e.resetForm&&x.push(function(){p.resetForm()}),e.clearForm&&x.push(function(){p.clearForm(e.includeHidden)}),!e.dataType&&e.target){var C=e.success||function(){};x.push(function(i,n,s){var o=arguments,a=e.replaceTarget?"replaceWith":"html";t(e.target)[a](i).each(function(){C.apply(this,o)})})}else{e.success&&(t.isArray(e.success)?t.merge(x,e.success):x.push(e.success))}if(e.success=function(t,i,n){for(var s=e.context||this,o=0,a=x.length;o0,S="multipart/form-data",D=p.attr("enctype")===S||p.attr("encoding")===S,M=o.fileapi&&o.formdata;n("fileAPI :"+M);var P,F=(T||D)&&!M;!1!==e.iframe&&(e.iframe||F)?e.closeKeepAlive?t.get(e.closeKeepAlive,function(){P=h(y)}):P=h(y):P=(T||D)&&M?function(i){for(var n=new FormData,s=0;s0)&&(s={url:s,data:o,dataType:a},"function"==typeof r&&(s.success=r)),s=s||{},s.delegation=s.delegation&&t.isFunction(t.fn.on),!s.delegation&&0===this.length){var l={s:this.selector,c:this.context};return !t.isReady&&l.s?(n("DOM not ready, queuing ajaxForm"),t(function(){t(l.s,l.c).ajaxForm(s)}),this):(n("terminating; zero elements found by selector"+(t.isReady?"":" (DOM not ready)")),this)}return s.delegation?(t(document).off("submit.form-plugin",this.selector,e).off("click.form-plugin",this.selector,i).on("submit.form-plugin",this.selector,s,e).on("click.form-plugin",this.selector,s,i),this):this.ajaxFormUnbind().on("submit.form-plugin",s,e).on("click.form-plugin",s,i)},t.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},t.fn.formToArray=function(e,i,n){var s=[];if(0===this.length){return s}var a,r=this[0],l=this.attr("id"),h=e||void 0===r.elements?r.getElementsByTagName("*"):r.elements;if(h&&(h=t.makeArray(h)),l&&(e||/(Edge|Trident)\//.test(navigator.userAgent))&&(a=t(':input[form="'+l+'"]').get()).length&&(h=(h||[]).concat(a)),!h||!h.length){return s}t.isFunction(n)&&(h=t.map(h,n));var c,d,u,p,f,g,m;for(c=0,g=h.length;c","/":"?","\\":"|"}},a.each(["keydown","keyup","keypress"],function(){a.event.special[this]={add:b}})}(jQuery),function(d){function g(k,a){if(k===!1){return k}if(!k){return a}k===!0?k={add:!0,"delete":!0,edit:!0,sort:!0}:"string"==typeof k&&(k=k.split(","));var l;return d.isArray(k)&&(l={},d.each(k,function(n,m){d.isPlainObject(m)?l[m.action]=m:l[m]=!0}),k=l),d.isPlainObject(k)&&(l={},d.each(k,function(n,m){m?l[n]=d.extend({type:n},b[n],d.isPlainObject(m)?m:null):l[n]=!1}),k=l),a?d.extend(!0,{},a,k):k}function c(k,a,l){return a=a||k.type,d(l||k.template).addClass("tree-action").attr(d.extend({"data-type":a,title:k.title||""},k.attr)).data("action",k)}var j="zui.tree",f=0,h=function(k,a){this.name=j,this.$=d(k),this.getOptions(a),this._init()},b={sort:{template:''},add:{template:''},edit:{template:''},"delete":{template:''}};h.DEFAULTS={animate:null,initialState:"normal",toggleTemplate:''},h.prototype.add=function(w,u,p,y,m){var x,k=d(w),q=this.options;if(k.is("li")?(x=k.children("ul"),x.length||(x=d("
        "),k.append(x),this._initList(x,k))):x=k,x){var v=this;d.isArray(u)||(u=[u]),d.each(u,function(r,a){var A=d("
      • ").data(a).appendTo(x);void 0!==a.id&&A.attr("data-id",a.id);var l=q.itemWrapper?d(q.itemWrapper===!0?'
      • ').append(c(m.add,"add",m.add.templateInList)).appendTo(w)}m.sort&&w.sortable(d.extend({dragCssClass:"tree-drag-holder",trigger:".sort-handler",selector:"li:not(.tree-action-item)",finish:function(a){q.callEvent("action",{action:m.sort,$list:w,target:a.target,item:k})}},m.sort.options,d.isPlainObject(this.options.sortable)?this.options.sortable:null))}p&&(p.hasClass("open")||k&&k.open)&&p.addClass("open in")},h.prototype._initItem=function(m,x,k,w){if(void 0===x){var e=m.prev("li");x=e.length?e.data("idx")+1:1}if(k=k||m.closest("ul"),m.attr("data-idx",x).removeClass("tree-single-item"),!m.data("id")){var p=x;k.hasClass("tree")||(p=k.parent("li").data("id")+"-"+p),m.attr("data-id",p)}w=w||m.data();var q=g(w.actions,this.actions);if(q){var v=m.find(".tree-actions");v.length||(v=d('
        ').appendTo(this.options.itemWrapper?m.find(".tree-item-wrapper"):m),d.each(q,function(a,l){l&&v.append(c(l,a))}))}var u=m.children("ul");u.length&&this._initList(u,m,x,w)},h.prototype._init=function(){var k=this.options,m=this;this.actions=g(k.actions),this.$.addClass("tree"),k.animate&&this.$.addClass("tree-animate"),this._initList(this.$);var e=k.initialState,l=d.zui&&d.zui.store&&d.zui.store.enable;l&&(this.selector=j+"::"+(k.name||"")+"#"+(this.$.attr("id")||f++),this.store=d.zui.store[k.name?"get":"pageGet"](this.selector,{})),"preserve"===e&&(l?this.isPreserve=!0:this.options.initialState=e="normal"),this.reload(k.data),l&&(this.isPreserve=!0),"expand"===e?this.expand():"collapse"===e&&this.collapse(),this.$.on("click",'.list-toggle,a[href="#"],.tree-toggle',function(o){var a=d(this),p=a.parent("li");m.callEvent("hit",{target:p,item:p.data()}),m.toggle(p),a.is("a")&&o.preventDefault()}).on("click",".tree-action",function(){var o=d(this),a=o.data();if(a.action&&(a=a.action),"sort"!==a.type){var p=o.closest("li:not(.tree-action-item)");m.callEvent("action",{action:a,target:this,$item:p,item:p.data()})}})},h.prototype.preserve=function(l,a,m){if(this.isPreserve){if(l){a=a||l.data("id"),m=void 0===m&&l.hasClass("open"),m?this.store[a]=m:delete this.store[a],this.store.time=(new Date).getTime(),d.zui.store[this.options.name?"set":"pageSet"](this.selector,this.store)}else{var k=this;this.store={},this.$.find("li").each(function(){k.preserve(d(this))})}}},h.prototype.expand=function(k,l,a){k?(k.addClass("open"),!l&&this.options.animate?setTimeout(function(){k.addClass("in")},10):k.addClass("in")):k=this.$.find("li.has-list").addClass("open in"),a||this.preserve(k),this.callEvent("expand",k,this)},h.prototype.show=function(l,a,m){var k=this;l.each(function(){var p=d(this);if(k.expand(p,a,m),p){for(var q=p.parent("ul");q&&q.length&&!q.hasClass("tree");){var n=q.parent("li");n.length?(k.expand(n,a,m),q=n.parent("ul")):q=!1}}})},h.prototype.collapse=function(k,l,a){k?!l&&this.options.animate?(k.removeClass("in"),setTimeout(function(){k.removeClass("open")},300)):k.removeClass("open in"):k=this.$.find("li.has-list").removeClass("open in"),a||this.preserve(k),this.callEvent("collapse",k,this)},h.prototype.toggle=function(a){var k=a&&a.hasClass("open")||a===!1||void 0===a&&this.$.find("li.has-list.open").length;this[k?"collapse":"expand"](a)},h.prototype.getOptions=function(a){this.options=d.extend({},h.DEFAULTS,this.$.data(),a),null===this.options.animate&&this.$.hasClass("tree-animate")&&(this.options.animate=!0)},h.prototype.toData=function(k,a){d.isFunction(k)&&(a=k,k=null),k=k||this.$;var l=this;return k.children("li:not(.tree-action-item)").map(function(){var n=d(this),m=n.data();delete m["zui.droppable"];var p=n.children("ul");return p.length&&(m.children=l.toData(p)),d.isFunction(a)?a(m,n):m}).get()},h.prototype.callEvent=function(k,a){var l;return d.isFunction(this.options[k])&&(l=this.options[k](a,this)),this.$.trigger(d.Event(k+"."+this.name,a)),l},d.fn.tree=function(k,a){return this.each(function(){var l=d(this),e=l.data(j),m="object"==typeof k&&k;e||l.data(j,e=new h(this,m)),"string"==typeof k&&e[k](a)})},d.fn.tree.Constructor=h,d(function(){d('[data-ride="tree"]').tree()})}(jQuery),function(b){var d="zui.colorPicker",a='
        ',f={zh_cn:{errorTip:"不是有效的颜色值"},zh_tw:{errorTip:"不是有效的顏色值"},en:{errorTip:"Not a valid color value"}},c=function(e,g){this.name=d,this.$=b(e),this.getOptions(g),this.init()};c.DEFAULTS={colors:["#00BCD4","#388E3C","#3280fc","#3F51B5","#9C27B0","#795548","#F57C00","#F44336","#E91E63"],pullMenuRight:!0,wrapper:"btn-wrapper",tileSize:30,lineCount:5,optional:!0,tooltip:"top",icon:"caret-down",updateBtn:"auto"},c.prototype.init=function(){var k=this,m=k.options,h=k.$,l=h.parent(),g=!1;l.hasClass("colorpicker")?k.$picker=l:(k.$picker=b(m.template||a),g=!0),k.$picker.addClass(m.wrapper).find(".cp-title").toggle(void 0!==m.title).text(m.title),k.$menu=k.$picker.find(".dropdown-menu").toggleClass("pull-right",m.pullMenuRight),k.$btn=k.$picker.find(".btn.dropdown-toggle"),k.$btn.find(".ic").addClass("icon-"+m.icon),m.btnTip&&k.$picker.attr("data-toggle","tooltip").tooltip({title:m.btnTip,placement:m.tooltip,container:"body"}),h.attr("data-provide",null),g&&h.after(k.$picker),k.colors={},b.each(m.colors,function(e,p){if(b.zui.Color.isColor(p)){var o=new b.zui.Color(p);k.colors[o.toCssStr()]=o}}),k.updateColors(),k.$picker.on("click",".cp-tile",function(){k.setValue(b(this).data("color"))});var j=function(){var e=h.val(),n=b.zui.Color.isColor(e);h.parent().toggleClass("has-error",!(n||m.optional&&""===e)),n?k.setValue(e,!0):m.optional&&""===e?h.tooltip("hide"):h.is(":focus")||h.tooltip("show",m.errorTip)};h.is("input:not([type=hidden])")?(m.tooltip&&h.attr("data-toggle","tooltip").tooltip({trigger:"manual",placement:m.tooltip,tipClass:"tooltip-danger",container:"body"}),h.on("keyup paste input change",j)):h.appendTo(k.$picker),j()},c.prototype.addColor=function(j){j instanceof b.zui.Color||(j=new b.zui.Color(j));var g=j.toCssStr(),k=this.options;this.colors[g]||(this.colors[g]=j);var h=b('
        ',{titile:j}).data("color",j).css({color:j.contrast().toCssStr(),background:g,"border-color":j.luma()>0.43?"#ccc":"transparent"}).attr("data-color",g);this.$menu.append(b("
      • ").css({width:k.tileSize,height:k.tileSize}).append(h)),k.optional&&this.$menu.find(".cp-tile.empty").parent().detach().appendTo(this.$menu)},c.prototype.updateColors=function(k){var h=(this.$picker,this.$menu.children("li:not(.heading)").remove()),m=this.options,k=k||this.colors,j=this,l=0;if(b.each(k,function(n,o){j.addColor(o),l++}),m.optional){var g=b('
      • ').css({width:m.tileSize,height:m.tileSize});this.$menu.append(g),l++}h.css("width",Math.min(l,m.lineCount)*m.tileSize+6)},c.prototype.setValue=function(u,p){var k=this,w=k.options,j=k.$btn;k.$menu.find(".cp-tile.active").removeClass("active");var v="",g=w.updateBtn;if("auto"===g){var m=j.find(".color-bar");g=!m.length||function(e){m.css("background",e||"")}}if(u){var q=new b.zui.Color(u);v=q.toCssStr().toLowerCase(),g&&(b.isFunction(g)?g(v,j,k):j.css({background:v,color:q.contrast().toCssStr(),borderColor:q.luma()>0.43?"#ccc":v})),k.colors[v]||k.addColor(q),p||k.$.val().toLowerCase()===v||k.$.val(v).trigger("change"),k.$menu.find('.cp-tile[data-color="'+v+'"]').addClass("active"),k.$.tooltip("hide"),k.$.trigger("colorchange",q)}else{g&&(b.isFunction(g)?g(null,j,k):j.attr("style",null)),p||""===k.$.val()||k.$.val(v).trigger("change"),w.optional&&k.$.tooltip("hide"),k.$menu.find(".cp-tile.empty").addClass("active"),k.$.trigger("colorchange",null)}w.updateBorder&&b(w.updateBorder).css("border-color",v),w.updateBackground&&b(w.updateBackground).css("background-color",v),w.updateColor&&b(w.updateColor).css("color",v),w.updateText&&b(w.updateText).text(v)},c.prototype.getOptions=function(h){var g=b.extend({},c.DEFAULTS,this.$.data(),h);"string"==typeof g.colors&&(g.colors=g.colors.split(","));var j=(g.lang||b.zui.clientLang()).toLowerCase();g.errorTip||(g.errorTip=f[j].errorTip),b.fn.tooltip||(g.btnTip=!1),this.options=g},b.fn.colorPicker=function(e){return this.each(function(){var j=b(this),h=j.data(d),g="object"==typeof e&&e;h||j.data(d,h=new c(this,g)),"string"==typeof e&&h[e]()})},b.fn.colorPicker.Constructor=c,b(function(){b('[data-provide="colorpicker"]').colorPicker()})}(jQuery),function(b,d){function a(e){return e===d&&(e=g+=1),c[e%c.length]}var g=0,c=["#00a9fc","#ff5d5d","#fdc137","#00da88","#7ec5ff","#8666b8","#bd7b46","#ff9100","#ff3d00","#f57f17","#00e5ff","#00b0ff","#2979ff","#3d5afe","#651fff","#d500f9","#f50057","#ff1744"];jQuery.fn.tableChart=function(){b(this).each(function(){var u=b(this),m=u.data(),y=m.chart||"pie",k=b(m.target);if(k.length){var x=null;if("pie"===y){m=b.extend({scaleShowLabels:!0,scaleLabel:"<%=label%>: <%=value%>"},m);var j=[],p=u.find("tbody > tr").each(function(l){var o=b(this),h=a();o.attr("data-id",l).find(".chart-color-dot").css("background",h),j.push({label:o.find(".chart-label").text(),value:parseInt(o.find(".chart-value").text()),color:h,id:l})});j.length>1?m.scaleLabelPlacement="outside":1===j.length&&(m.scaleLabelPlacement="inside",j.push({label:"",value:j[0].value/2000,color:"#fff",showLabel:!1})),x=k.pieChart(j,m),k.on("mousemove",function(h){var l=x.getSegmentsAtEvent(h);p.removeClass("active"),l.length&&p.filter('[data-id="'+l[0].id+'"]').addClass("active")})}else{if("bar"===y){var q=a(),w=[],v={label:u.find("thead .chart-label").text(),color:q,data:[]},p=u.find("tbody > tr").each(function(l){var h=b(this);w.push(h.find(".chart-label").text()),v.data.push(parseInt(h.find(".chart-value").text())),h.find(".chart-color-dot").css("background",q)}),j={labels:w,datasets:[v]};w.length&&(m.barValueSpacing=5),x=k.barChart(j,m)}else{if("line"===y){var q=a(),w=[],v={label:u.find("thead .chart-label").text(),color:q,data:[]},p=u.find("tbody > tr").each(function(l){var h=b(this);w.push(h.find(".chart-label").text()),v.data.push(parseInt(h.find(".chart-value").text())),h.find(".chart-color-dot").css("background",q)}),j={labels:w,datasets:[v]};w.length&&(m.barValueSpacing=5),x=k.lineChart(j,m)}}}null!==x&&u.data("zui.chart",x)}})};var f=function(j,q){var k=b(j);if(!k.data("initProgressPie")){k.data("initProgressPie",1);var p=k.is("canvas")?k:k.find("canvas"),h=b.extend({value:0,color:b.getThemeColor("primary")||"#006af1",backColor:b.getThemeColor("pale")||"#E9F2FB",doughnut:!0,doughnutSize:85,width:20,height:20,showTip:!1,name:"",tipTemplate:"<%=value%>%",animation:"auto",realValue:parseFloat(k.find(".progress-value").text())},q,k.data()),m=p.length;m||(p=b("").appendTo(k)),p.attr("width")!==d?h.width=p.attr("width"):p.attr("width",h.width),p.attr("height")!==d?h.height=p.attr("height"):p.attr("height",h.height),m||8!=b.zui.browser.ie||G_vmlCanvasManager.initElement(p[0]),"auto"===h.animation&&(h.animation=h.width>30),h.value=Math.max(0,Math.min(100,h.value)),k.addClass("progress-pie-"+h.width);var e=[{value:h.value,label:h.name,color:h.color,circleBeginEnd:!0},{value:100-h.value,label:"",color:h.backColor}];p[h.doughnut?"doughnutChart":"pieChart"](e,b.extend({segmentShowStroke:!1,animation:h.animation,showTooltips:h.showTip,tooltipTemplate:h.tipTemplate,percentageInnerCutout:h.doughnutSize,reverseDrawOrder:!0,animationEasing:"easeInOutQuart",onAnimationProgress:h.realValue?function(l){k.find(".progress-value").text(Math.floor(h.realValue*l))}:d,onAnimationComplete:h.realValue?function(l){k.find(".progress-value").text(h.realValue)}:d},h.chartOptions))}};jQuery.fn.progressPie=function(h){b(this).each(function(){var e=b(this);if(!e.closest(".hidden").length){var j=e.closest(".tab-pane");j.length&&!j.hasClass("active")?b('[data-toggle="tab"][data-target="#'+j.attr("id")+'"]').one("shown.zui.tab",function(){f(e,h)}):f(this,h)}})},b(function(){b(".table-chart").tableChart();var h=b(".progress-pie");h.length>100?setTimeout(function(){h.progressPie()},1000):h.progressPie()})}(jQuery,void 0),function(a){jQuery.fn.sparkline=function(b){a(this).each(function(){var v=a(this),m=a.extend({values:v.attr("values"),width:v.width()-4,height:v.height()-4},v.data(),b),D=m.height,k=[],B=m.width,e=m.values.split(","),q=0;for(var w in e){var A=parseFloat(e[w]);NaN!=A&&(k.push(A),q=Math.max(A,q))}var z=(Math.min(q,30),Math.min(B,Math.max(10,k.length*B/30))),C=v.children("canvas");C.length||(v.append(''),C=v.children("canvas")),C.attr("width",z).attr("height",D);var j={labels:k,datasets:[{fillColor:a.getThemeColor("pale")||"rgba(0,0,255,0.05)",strokeColor:a.getThemeColor("primary")||"#0054EC",pointColor:a.getThemeColor("secondary")||"rgba(255,136,0,1)",pointStrokeColor:"#fff",data:k}]},y={animation:!0,scaleOverride:!0,scaleStepWidth:Math.ceil(q/10),scaleSteps:10,scaleStartValue:0,showScale:!1,showTooltips:!1,pointDot:!1,scaleShowGridLines:!1,datasetStrokeWidth:1},x=a(C).lineChart(j,y);v.data("sparklineChart",x)})},a(function(){a(".sparkline").sparkline()})}(jQuery),function(a){a(function(){a.fn.fixedDate=function(){return a(this).each(function(){var f=a(this).attr("autocomplete","off");"0000-00-00"==f.val()&&f.focus(function(){"0000-00-00"==f.val()&&f.val("").datetimepicker("update")}).blur(function(){""==f.val()&&f.val("0000-00-00")})})};var c={language:a("html").attr("lang"),weekStart:1,todayBtn:1,autoclose:1,todayHighlight:1,startView:2,forceParse:0,showMeridian:1,format:"yyyy-mm-dd hh:ii",startDate:"1970-1-1"},b=a.extend({},c,{minView:2,format:"yyyy-mm-dd"}),d=a.extend({},c,{startView:1,minView:0,maxView:1,format:"hh:ii"});a(".datepicker-wrapper").click(function(){a(this).find(".form-date, .form-datetime, .form-time").datetimepicker("show").focus()}),window.datepickerOptions=c,a.fn.datepicker=function(f){return this.datetimepicker(a.extend({},b,f))},a.fn.timepicker=function(f){return this.datetimepicker(a.extend({},d,f))},a.fn.datepickerAll=function(){return this.find(".form-datetime").fixedDate().datetimepicker(c),this.find(".form-date").fixedDate().datepicker(),this.find(".form-time").fixedDate().timepicker(),this},a("body").datepickerAll()})}(jQuery),function(a){var b=function(w,q){q=a.extend({idStart:0,idEnd:9,chosen:!0,datetimepicker:!0,colorPicker:!0,hotkeys:!0},q,w.data());var k=w.find(".template");!k.length&&q.template&&(k=a(q.template));var B=0,j=0,z=function(c){c.is("select.chosen")?c.next(".chosen-container").find("input").focus():c.focus()},f=function(d){var c=w.find("[data-ctrl-index]:focus,.chosen-container-active").first();if(c.length){if(c.is(".chosen-container-active")){if(c.hasClass("chosen-with-drop")&&("down"===d||"up"===d)){return}c=c.prev("select.chosen")}var h=c.data("ctrlIndex"),e=c.closest("tr").data("row");"down"===d?e0?e-=1:e=j-1:"left"===d?h>0?h-=1:h=B-1:"right"===d&&(h").html(c);return h.attr("data-row",l).addClass(k.attr("class")).removeClass("template"),q.rowCreator&&q.rowCreator(h,l,q),d?d.after(h):v.append(h),y(h),h};a.extend(m,{createRow:A,template:x});for(var g=q.idStart;g<=q.idEnd;++g){A(g)}}else{y(w)}w.on("click",".btn-copy",function(){var d=a(this),c=a(d.data("copyFrom")).val(),h=a(d.data("copyTo")).val(c).addClass("highlight");setTimeout(function(){h.removeClass("highlight")},2000)}),q.hotkeys&&a(document).on("keydown",function(d){var h={"Ctrl+#37":"left","Ctrl+#39":"right","#38":"up","#40":"down","Ctrl+#38":"up","Ctrl+#40":"down"},c=[];d.ctrlKey&&c.push("Ctrl"),c.push("#"+d.keyCode);var l=h[c.join("+")];l&&(f(l),d.ctrlKey&&(d.stopPropagation(),d.preventDefault()))}),w.data("zui.batchActionForm",m)};a.fn.batchActionForm=function(c){return this.each(function(){b(a(this),c)})}}(jQuery),function(b,d){var a="zui.table",g={zh_cn:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},zh_tw:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},en:{selectedItems:"Seleted {0} items",attrTotal:"{0} total {1}"}},c=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),f=function(p,n){var k=this;k.name=a;var o=k.$=b(p);n=k.options=b.extend({},f.DEFAULTS,this.$.data(),n);var j=n.lang||"zh_cn";k.lang=b.isPlainObject(j)?b.extend(!0,{},g[j.lang||b.zui.clientLang()],j):g[j],o.attr("id")||(o.attr("id","table-"+b.zui.uuid()),n.hot&&console.warn("ZUI: table hot replace id not defined, the element id attribute should be set.")),o.attr("data-ride")||o.attr("data-ride","table"),k.getTable().find("thead>tr>th").each(function(){var l=b(this);if(!l.attr("title")){var h=b.trim(l.find("a").text()||l.text()||"");h.length&&l.attr("title",h)}}),n.checkable&&(o.on("click",".check-all",function(){k.checkAll(!b(this).hasClass("checked"))}).on("click","tbody>tr",function(h){b(h.target).closest('.btn,a,.not-check,.form-control,input[type="text"],.chosen-container').length||k.checkRow(b(this))}).on("click",'tbody input[type="checkbox"],tbody label[for]',function(l){l.stopPropagation();var h=b(this);h.is("label")&&(h=h.closest(".checkbox-primary").find('input[type="checkbox"]')),k.checkRow(h.closest("tr"),h.is(":checked"))}),n.selectable&&o.selectable(b.extend({},{selector:k.isDataTable?".fixed-left tbody>tr":"tbody>tr",selectClass:"",trigger:".c-id",clickBehavior:"multi",listenClick:!1,select:function(h){k.checkRow(h.target,!0),b.cookie("ajax_dragSelected")||(b.cookie("ajax_dragSelected","on",{expires:config.cookieLife,path:config.webRoot}),b.ajaxSendScore("dragSelected"))},unselect:function(e){k.checkRow(e.target,!1)},rangeStyle:{border:"1px solid #006af1",backgroundColor:"rgba(50,128,252,0.2)",borderRadius:"2px"}},b.isPlainObject(n.selectable)?n.selectable:null)));var m=k.$form=o.is("form")?o:o.find("form");m.length&&(n.ajaxForm?m.ajaxForm(b.isPlainObject(n.ajaxForm)?n.ajaxForm:null):m.on("click","[data-form-action]",function(){m.attr("action",b(this).data("formAction")).submit()})),(n.fixFooter||n.fixHeader)&&(k.pageFooterHeight=b("#footer").outerHeight(),k.updateFixUI(),b(window).on("scroll resize",function(){k.updateFixUI()}).on("sidebar.toggle",function(){setTimeout(function(){k.updateFixUI()},200)})),n.group&&(o.on("click",".group-toggle",function(){k.toggleRowGroup(b(this).closest("tr").data("id"))}),b(document).on("click",".group-collapse-all",function(){k.toggleGroups(!1)}).on("click",".group-expand-all",function(){k.toggleGroups(!0)})),k.defaultStatistic=o.find(".table-statistic").html(),k.updateStatistic(),k.initModals(),k.checkItems={},k.updateCheckUI()};f.prototype.reload=function(k){var h=this,m=h.options,j=m.replaceId;if(!j){return k&&k()}"self"===j&&(j=h.$.attr("id"));var l=b("
        ");h.$.addClass("load-indicator loading"),l.load(window.location.href+" #"+j,function(){h.$.empty().html(l.children().html()).removeClass("load-indicator loading"),h.$.trigger("beforeTableReload"),h.updateStatistic(),h.initModals(),h.$.datepickerAll();var n=h.$.find("tbody>tr"),e=!1;b.each(h.checkItems,function(p,q){q&&(h.checkRow(n.filter('[data-id="'+p+'"]'),!0,!0),e=!0)}),e&&h.updateCheckUI(),h.$.trigger("tableReload");var o=b("#mainMenu>.btn-toolbar>.btn-active-text>.label");o.length&&o.text(h.getTable().find("tbody:first>tr:not(.table-children)").length),h.$.find('[data-ride="pager"]').pager(),k&&k(),m.afterReload&&m.afterReload()})},f.prototype.initModals=function(){var k=this,h=k.options,l=k.$.find(h.iframeModalTrigger);if(l.length){var j={type:"iframe",onHide:h.replaceId?function(){var e=b.cookie("selfClose");(1==e||h.hot)&&(b("#triggerModal").data("cancel-reload",1),k.reload(function(){b.cookie("selfClose",0)}))}:null};l.modalTrigger(j)}},f.prototype.getTable=function(){var h=this.$;if(this.isDataTable){return h.find("div.datatable")}var j=h.is("table")?h:h.find("table:not(.fixed-header-copy)").first();return j.is(".datatable")&&(this.isDataTable=!0,j=h.find("div.datatable")),j},f.prototype.toggleGroups=function(j){var h=this,k={};h.$.find("tbody>tr").each(function(){var e=b(this).closest("tr").data("id");k[e]||h.toggleRowGroup(e,j)})},f.prototype.toggleRowGroup=function(h,l){var j=this.$.find('tbody>tr[data-id="'+h+'"]'),k=j.filter(".group-summary"),e=l===d?!k.hasClass("hidden"):!!l;j.not(".group-summary").toggleClass("hidden",!e),k.toggleClass("hidden",e),b("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},f.prototype.updateStatistic=function(){var h=this,m=h.$.find(".table-statistic");if(m.length){if(h.defaultStatistic===d&&(h.defaultStatistic=m.html()),h.options.statisticCreator){return void m.html(h.options.statisticCreator(h)||h.defaultStatistic)}var j=h.statisticCols;if(!j&&j!==!1){j={};var l=!1;h.getTable().find("thead th").each(function(p){var o=b(this),q=o.data("statistic");q&&(l=!0,j[p]={format:q,name:o.text()})}),h.statisticCols=!!l&&j}var e=0;j&&b.each(j,function(n){j[n].total=0,j[n].checkedTotal=0}),h.$.find(h.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var p=b(this),o=p.hasClass("checked"),q=p.children("td");o&&e++,j&&b.each(j,function(n){var r=parseFloat(q.eq(n).text());isNaN(r)&&(r=0),j[n].total+=r,o&&(j[n].checkedTotal+=r)})});var k=[];if(e){k.push(h.lang.selectedItems.format(e))}else{if(h.defaultStatistic){return void m.html(h.defaultStatistic)}}j&&b.each(j,function(o){var p=j[o],q=p[e?"checkedTotal":"total"];p.format&&(q=p.format.format(q)),k.push(h.lang.attrTotal.format(p.name,q))}),m.html(k.join(", "))}},f.prototype.updateFixUI=function(l){var j=this,p=(new Date).getTime();if(!l&&(j.lastUpdateCall&&clearTimeout(j.lastUpdateCall),!j.lastUpdateTime||p-j.lastUpdateTime<100)){return void (j.lastUpdateCall=setTimeout(function(){j.updateFixUI(!0)},30))}if(j.lastUpdateTime=p,j.lastUpdateCall&&(clearTimeout(j.lastUpdateCall),j.lastUpdateCall=null),c){var m=j.getTable();if(m.parent().is(".table-responsive")){var h=m.find("thead"),k=0;h.find("th").each(function(){k+=b(this).outerWidth()}),m.css("min-width",k)}}j.options.fixHeader&&!j.isDataTable&&j.fixHeader(),j.options.fixFooter&&j.fixFooter()},f.prototype.fixHeader=function(){var v=this,q=v.getTable(),m=q.find("thead"),z=m[0].getBoundingClientRect(),k=v.options.fixFooter,y=b.isFunction(k)?k(z,m):z.top<("number"==typeof k?k:-5),j=v.$.find(".fix-table-copy-wrapper"),p=q.parent(),u=p.is(".table-responsive");if(y){if(j.length||(j=b('
        ').append(b('
        ').addClass(q.attr("class")).append(m.clone())).insertAfter(q)),u){var x=p[0].getBoundingClientRect();j.css({left:x.left,width:p.width()}),j.find(".fixed-header-copy").css({left:z.left-x.left,position:"relative",minWidth:q.width()}),p.data("fixHeaderScroll")||p.data("fixHeaderScroll",1).on("scroll",function(){v.fixHeader()})}else{j.css({left:z.left,width:z.width})}var w=j.find("th");m.find("th").each(function(h){w.eq(h).css("width",b(this).outerWidth())})}else{j.remove()}},f.prototype.fixFooter=function(){var v,q=this,m=q.getTable(),z=q.$.find(".table-footer");if(q.isDataTable){v=m[0].getBoundingClientRect()}else{var k=m.find("tbody");if(!k.length){return}v=k[0].getBoundingClientRect(),v=k[0].getBoundingClientRect()}var y=q.options.fixFooter;z.toggleClass("fixed-footer",!!j);var j=b.isFunction(y)?y(v,z):v.bottom>window.innerHeight-50-("number"==typeof y?y:q.pageFooterHeight||5);z.toggleClass("fixed-footer",!!j),m.toggleClass("with-footer-fixed",!!j),m.trigger("fixFooter",j);var p=b("body"),u=p.hasClass("body-modal");if(j){var x=m.parent(),w=x.is(".table-responsive");z.css({bottom:q.pageFooterHeight||0,left:w?x[0].getBoundingClientRect().left:v.left,width:w?x.width():v.width}),u&&p.css("padding-bottom",40)}else{z.css({width:"",left:0,bottom:0}),u&&p.css("padding-bottom",0)}},f.prototype.checkAll=function(j){var h=this,k=h.$.find(h.isDataTable?".fixed-left tbody>tr":"tbody>tr");k.each(function(){h.checkRow(b(this),j,!0)}),h.updateCheckUI()},f.prototype.checkRow=function(h,e,l){var j=this;j.isDataTable&&!h.is(".datatable-row-left")&&(h=j.getTable().find('.datatable-row-left[data-index="'+h.data("index")+'"]'));var k=h.find('input[type="checkbox"]');k.length&&(e===d&&(e=!k.is(":checked")),j.isDataTable?j.getTable().find('.datatable-row[data-index="'+h.data("index")+'"]').toggleClass("checked",e):h.toggleClass("checked",e),this.checkItems[h.data("id")]=e,k.prop("checked",e).trigger("change"),l||j.updateCheckUI())},f.prototype.updateCheckUI=function(){var q=this,k=q.getTable(),v=k.find(q.isDataTable?".fixed-left tbody>tr":"tbody>tr"),m=!1,u=null,j=0,p=!1,h=v.length;v.each(function(r){var e=b(this),o=e.find('input[type="checkbox"]');p=o.is(":checked");var l=q.isDataTable?k.find('.datatable-row[data-index="'+e.data("index")+'"]'):e;l.toggleClass("checked",p),l.toggleClass("row-check-begin",p&&!m),u&&u.toggleClass("row-check-end",!p&&m),p&&(j+=1),u=l,m=p,h===r+1&&l.toggleClass("row-check-end",p)}),q.$.toggleClass("has-row-checked",j>0).find(".check-all").toggleClass("checked",!(!h||j!==h)),q.updateStatistic(),q.options.onCheckChange&&q.options.onCheckChange()},f.DEFAULTS={checkable:!0,ajaxForm:!1,selectable:!0,fixHeader:!0,fixFooter:!0,iframeWidth:900,replaceId:"self",hot:!1,iframeModalTrigger:".iframe"},b.fn.table=function(h){return this.each(function(){var k=b(this),j=k.data(a),e="object"==typeof h&&h;j||k.data(a,j=new f(this,e)),"string"==typeof h&&j[h]()})},f.NAME=a,b.fn.table.Constructor=f,b(function(){b('[data-ride="table"]').table()})}(jQuery,void 0),function(b,d,a){b.fn._ajaxForm=b.fn.ajaxForm;var g={timeout:d.config?d.config.timeout:0,dataType:"json"},c="";b.fn.enableForm=function(h,j){return h===a&&(h=!0),this.each(function(){var e=b(this);j||e.find('[type="submit"]').attr("disabled",h?null:"disabled"),e.hasClass("load-indicator")&&e.toggleClass("loading",!h)})};var f=function(j,h,k){"string"==typeof h&&(k=h,h=null),k=k||"show",b.zui.messager?b.zui.messager[k](j,h):alert(j)};b.ajaxForm=function(j,n){var e=b(j);if(e.length>1){return e.each(function(){b.ajaxForm(this,n)})}b.isFunction(n)&&(n={complete:n}),n=b.extend({},g,e.data(),n);var m=n.beforeSubmit,p=n.error,o=n.success,k=n.finish;delete n.finish,delete n.success,delete n.onError,delete n.beforeSubmit,n=b.extend({beforeSubmit:function(s,q,A){if(e.enableForm(!1),(m&&m(s,q,A))!==!1){var h={},z=q.find('[type="file"]');h.fileapi=z.length&&z[0].files!==a,h.formdata=d.FormData!==a;var y=h.fileapi&&q.find('input[type="file"]:enabled').filter(function(){return""!==b(this).val()}),B=y.length,l="multipart/form-data",x=q.attr("enctype")==l||q.attr("encoding")==l,w=h.fileapi&&h.formdata,v=(B||x)&&!w;v&&(""==c&&(c=A.url),A.url!=c&&(A.url=c),A.url=A.url.indexOf("&")>=0?A.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":A.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(z,r,L){if((o&&o(z,r,L,e))!==!1){try{"string"==typeof z&&(z=JSON.parse(z))}catch(I){}if(null===z||"object"!=typeof z){return z?alert(z):f("No response.","danger")}var A=n.responser?b(n.responser):e.find(".form-responser");A.length||(A=b("#responser"));var E=z.message;if("success"===z.result){if(e.enableForm(!0,1),E){var q=e.find('[type="submit"]'),D=!1;q.length&&(q.popover({container:"body",trigger:"manual",content:E,tipClass:"popover-in-modal popover-success text-success",placement:z.placement||n.popoverPlacement||"right"}).popover("show"),setTimeout(function(){q.popover("destroy")},n.popoverTime||2000),D=!0),A.length&&(A.html(''+E+"").show().delay(3000).fadeOut(100),D=!0),D||f(E,"success")}if(k){return k(z,!0,e)}if((n.closeModal||z.closeModal)&&setTimeout(b.zui.closeModal,n.closeModalTime||2000),z.callback){var B=d[z.callback];if(b.isFunction(B)&&B()===!1){return}}var u=n.locate||z.locate;if(u){if("loadInModal"==u){var K=b(".modal");setTimeout(function(){K.load(K.attr("ref"),function(){b(this).find(".modal-dialog").css("width",b(this).data("width")),b.zui.ajustModalPosition()})},1000)}else{var G="reload"==u?d.location.href:u;setTimeout(function(){d.location.href=G},1200)}}var F=n.ajaxReload||z.ajaxReload;if(F){var J=b(F);J.length&&J.load(d.location.href+" "+F,function(){J.find('[data-toggle="modal"]').modalTrigger()})}}else{if(e.enableForm(),"string"==typeof E){A.length?A.html(''+E+"").show().delay(3000).fadeOut(100):f(E,"danger")}else{if("object"==typeof E){var H=!1,l=[];b.each(E,function(N,C){var x=b.isArray(C)?C.join(";"):C,P=b("#"+N);if(!P.length){return void l.push(x)}var w=N+"Label",O=b("#"+w);if(!O.length){var v=P.closest(".input-group").length;O=b('
        ').appendTo(v?P.closest(".input-group").parent():P.parent())}O.empty().append(x),P.addClass("has-error");var y=function(){var h=b("#"+w);if(h.length){return h.remove(),P.removeClass("has-error"),!0}};P.on("change input mousedown",y);var M=b("#"+N+"_chosen");M.length&&M.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){y()===!0&&b(this).removeClass("has-error")}),H||(P.focus(),H=!0)}),l.length&&f(l.join(";"),"danger")}}if(k){return k(z,!1,e)}}}},error:function(l,h,r){if((p&&p(l,h,r,e))!==!1){e.enableForm();var q="timeout"==h||"error"==h?d.lang?d.lang.timeout:h:l.responseText+h+r;f(q,"danger")}}},n),e._ajaxForm(n),e.on("click","[data-form-action]",function(){e.attr("action",b(this).data("formAction")).submit()})},b.fn.ajaxForm=function(h){return this.each(function(){b.ajaxForm(this,h)})},b.fn.setInputRequired=function(){return this.each(function(){var j=b(this),h=j.parent();h.is(".input-control,td")?h.addClass("required"):j.is(".chosen")?j.attr("required",null).next(".chosen-container").addClass("required"):h.addClass("required"),j.attr("required",null);var k=h.closest(".input-group");k.length&&1===k.find(".required,input[required],select[required]").length&&k.addClass("required")})},b(function(){b('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var e=d.config.requiredFields,h=b("form");e&&(e=e.split(",")),e&&e.length&&b.each(e,function(j,k){h.find("#"+k).attr("required","required")}),h.find("input[required],select[required],textarea[required]").setInputRequired()},400)})}(jQuery,window,void 0),function(b){var c="zui.searchList",a=function(g,h){if(g&&g.length){for(var f=0;f
        ').append(e)),f.$menu.append(e),f.$menu.removeClass("loading"),f.isLoaded=!0,g&&g(!0)},error:function(){f.$menu.removeClass("loading").append('
        '+(h.errorText||window.lang&&window.lang.timeout)+"
        "),g&&g(!1)}},h.ajax))},d.prototype.scrollTo=function(e){e.length&&e[0].scrollIntoView({behavior:"smooth"})},d.prototype.getItems=function(){return this.$.find(this.options.selector)},d.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},d.prototype.search=function(h){var k=this,g=void 0===h||null===h||""===h,j=k.getItems().removeClass("active");if(g){j.removeClass("hidden")}else{var f=b.trim(h).split(" ");j.each(function(){var l=b(this),m=l.text()+" "+(l.data("key")||l.data("filter"));l.toggleClass("hidden",!a(f,m))})}k.scrollTo(j.not(".hidden").first().addClass("active"))},d.DEFAULTS={selector:".list-group a",searchBox:".search-box",onSelectItem:null},b.fn.searchList=function(e){return this.each(function(){var g=b(this),h=g.data(c),f="object"==typeof e&&e;h||g.data(c,h=new d(this,f)),"string"==typeof e&&h[e]()})},d.NAME=c,b.fn.searchList.Constructor=d,b(function(){b('[data-ride="searchList"]').searchList()})}(jQuery),function(b){var c="zui.labelSelector",a=function(f,d){var e=this;e.name=c,e.$=b(f),d=e.options=b.extend({},a.DEFAULTS,this.$.data(),d),e.$.hide(),e.update()};a.prototype.select=function(d){d+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+d+'"]').addClass("active"),this.$.val(d).trigger("change")},a.prototype.update=function(){var g=this,d=g.options,j=g.$wrapper;if(!j){if(d.wrapper){j=b(d.wrapper)}else{var f=g.$.next();j=f.hasClass(".label-selector")?f:b('
        ')}j.parent().length||g.$.after(j),g.$wrapper=j,j.on("click",".label",function(e){var l=g.$.val(),k=b(this).data("value");g.hasEmptyValue!==!1&&k==l&&(k=g.hasEmptyValue),g.select(k),e.preventDefault()})}j.empty();var h=g.$.val();g.hasEmptyValue=!1,g.$.children("option").each(function(){var m=b(this),k={label:m.text(),value:m.val()},n=""===k.value||"0"===k.value;if(!n||(g.hasEmptyValue=k.value,k.label)){var e=b(d.labelTemplate||'');d.labelClass&&!n&&e.addClass(d.labelClass),d.labelCreator?e=d.labelCreator(e):(e.data("option",k).attr("data-value",k.value),n&&!k.label?e.addClass("empty").append(''):e.text(k.label).toggleClass("active",h===k.value)),j.append(e)}})},a.DEFAULTS={},b.fn.labelSelector=function(d){return this.each(function(){var f=b(this),g=f.data(c),e="object"==typeof d&&d;g||f.data(c,g=new a(this,e)),"string"==typeof d&&g[d]()})},a.NAME=c,b.fn.labelSelector.Constructor=a,b(function(){b('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(d){var h="zui.fileInput",c=d.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},k=d.formatBytes=function(a,l,m){return void 0===l&&(l=2),m||(m=am.fileMaxSize&&(o.val(""),(window.bootbox||window).alert(m.fileSizeError.format(k(m.fileMaxSize)))),p.update()}),p.update()};j.prototype.getFile=function(){var a=this.$input.prop("files");return a&&a[0]},j.prototype.update=function(l){var n=this,a=n.$,m=n.getFile(),p=!m;a.toggleClass("normal",!p).toggleClass("empty",p),m?(n.oldName=m.name,a.find(".file-title").text(m.name).attr("title",m.name),a.find(".file-size").text(k(m.size)),a.find(".file-editbox").val(m.name).attr("size",m.name.length),n.options.onSelect&&n.options.onSelect(m,n)):a.find(".file-editbox").val("")},j.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},d.fn.fileInput=function(a){return this.each(function(){var m=d(this),l=m.data(h),e="object"==typeof a&&a;l||m.data(h,l=new j(this,e)),"string"==typeof a&&l[a]()})},j.NAME=h,d.fn.fileInput.Constructor=j,d(function(){d('[data-provide="fileInput"]').fileInput()});var b="zui.fileInputList",g=function(m,a){var o=this;o.name=b;var l=o.$=d(m);a=o.options=d.extend({},g.DEFAULTS,this.$.data(),a),o.$template=l.find(".file-input").detach(),o.add()};g.prototype.add=function(){var l=this,m=l.options,a=l.$template.clone();"before"===m.appendWay?l.$.prepend(a):l.$.append(a),a.fileInput({fileMaxSize:m.eachFileMaxSize,fileSizeError:m.fileSizeError,onDelete:function(n){n.$.remove(),l.options.onDelete&&l.options.onDelete(n,l)},onSelect:function(o,n){l.add(),l.options.onSelect&&l.options.onSelect(o,n,l)}})},g.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},d.fn.fileInputList=function(a){return this.each(function(){var e=d(this),m=e.data(b),l="object"==typeof a&&a;m||e.data(b,m=new g(this,l)),"string"==typeof a&&m[a]()})},g.NAME=b,d.fn.fileInputList.Constructor=g,d(function(){d('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(E){window.config||(window.config={}),E.createLink=window.createLink=function(d,h,m,f,k){if(f||(f=config.defaultView),k||(k=!1),m){for(m=m.split("&"),i=0;i'+m+"")}}}s.val()||(time=R(e.format("hh:mm")),time=time-time%10+10,s.val(K(time)))};E.fn.timeSpanControl=function(a){return this.each(function(){var e=E(this),k=E.extend({},a,e.data()),b=e.find('[name="begin"],.control-time-begin'),g=e.find('[name="end"],.control-time-end'),n=function(){var d=b.val();if(e.find(".hide-empty-begin").toggleClass("hide",!d),d){var c=K(R(d)+30);g.find('option[value="'+c+'"]').length&&g.val(c),k.onChange&&k.onChange(g,c)}};if(e.data("timeSpanControlInit")){if(k.begin){var m=F(k.begin).format("hh:mm");b.find('option[value="'+m+'"]').length&&b.val(m),k.onChange&&k.onChange(b,m)}if(k.end){var f=F(k.end).format("hh:mm");g.find('option[value="'+f+'"]').length&&g.val(f),k.onChange&&k.onChange(g,f)}}else{b.on("change",n),J(b,k.begin),J(g,k.end),e.data("timeSpanControlInit",!0)}k.end||n()})},E.timeSpanControl={convertTimeToNum:R,convertNumToTime:K,initTimeSelect:J,createTime:F};var W=E.setSearchType=function(f,c){var h=E("#searchType");f||(f=h.val()),f=f||"bug",h.val(f);var d=E("#searchTypeMenu");d.find("li.selected").removeClass("selected");var g=d.find('a[data-value="'+f+'"]'),b=g.text();g.parent().addClass("selected"),E("#searchTypeName").text(b),c||E("#searchInput").focus()};E.gotoObject=function(b,a){b||(b=E("#searchType").val()),a||(a=E("#searchInput").val()),a&&b&&(window.location.href=E.createLink(b,"testsuite"===b?"library":"view","id="+a))},E(function(){W(null,!0),E(document).on("keydown",function(a){a.ctrlKey&&71===a.keyCode&&(E("#searchInput").val("").focus(),a.stopPropagation(),a.preventDefault())})}),E.removeAnchor=window.removeAnchor=function(a){var b=a.lastIndexOf("#");return b>-1?a.substr(0,b):a},E.refreshPage=function(){location.href=removeAnchor(location.href)},E.selectLang=window.selectLang=function(a){E.cookie("lang",a,{expires:config.cookieLife,path:config.webRoot}),E.ajaxSendScore("selectLang"),E.refreshPage()},E.selectTheme=window.selectTheme=function(a){E.cookie("theme",a,{expires:config.cookieLife,path:config.webRoot}),E.ajaxSendScore("selectTheme"),E.refreshPage()},E.chosenDefaultOptions={disable_search_threshold:1,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,drop_direction:function(){var c=E(this.container).closest(".table-responsive");if(c.length){if(this.drop_directionFixed){return this.drop_directionFixed}var a="down",f=this.container.find(".chosen-drop"),b=this.container.position(),d=f.outerHeight();return b.top>=d&&b.top+d{page}/{totalPage}
      ',"next_icon","last_icon"],onPageChange:function(b,a){b.recPerPage!==a.recPerPage&&E.cookie(this.options.pageCookie,b.recPerPage,{expires:config.cookieLife,path:config.webRoot}),b.recPerPage!==a.recPerPage&&(window.location.href=this.createLink())}}),E.zui.Messager.DEFAULTS.cssClass="messagger-zt",E.fn.reverseOrder=function(){return this.each(function(){var a=E(this);a.prependTo(a.parent())})};var H=function(h,d){var m=E(h);d=E.extend({},m.data(),d);var f=m.find(".histories-list"),k=!0,c=!1;m.on("click",".btn-reverse",function(){f.children("li").reverseOrder(),k=!k,E(this).find(".icon").toggleClass("icon-arrow-up",k).toggleClass("icon-arrow-down",!k)}).on("click",".btn-expand-all",function(){var a=E(this).find(".icon");c=!c,a.toggleClass("icon-plus",!c).toggleClass("icon-minus",c),f.children("li").toggleClass("show-changes",c)}).on("click",".btn-expand",function(){E(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var l=E(this),o=l.find(".icon"),a=o.hasClass("icon-code");o.toggleClass("icon-code",!a).toggleClass("icon-text",a),l.attr("title",a?d.original:d.textdiff),l.closest("li").toggleClass("show-original",a)}),f.find(".btn-strip").attr("title",d.original);var g=m.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var a=g.find("#comment");a.length&&(a.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var a=g.find("#comment");a.length&&!a.data("keditor")&&E.fn.kindeditor&&a.kindeditor()});m.on("click",".btn-comment",function(a){g.modal("toggle"),a.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){E(this).closest("li").toggleClass("show-form")});var b=m.find(".comment-edit-form");b.ajaxForm({success:function(l,o,a,p){setTimeout(function(){b.closest("li").removeClass("show-form")},2000)}})};E.fn.histories=function(a){return this.each(function(){H(this,a)})},E(function(){E(".histories").histories()});var M=0,O=0;E.toggleSidebar=function(b){var a=E("#sidebar");if(a.length){var c=E("main");if(void 0===b){b=c.hasClass("hide-sidebar")}else{if(b&&!c.hasClass("hide-sidebar")){return}}c.toggleClass("hide-sidebar",!b),clearTimeout(M),b?(a.addClass("showing"),M=setTimeout(function(){a.removeClass("showing"),a.trigger("sidebar.toggle",b)},210)):a.trigger("sidebar.toggle",b),E.zui.store.set(O,b)}};var U=E.initSidebar=function(){var c=E("#sidebar");if(c.length){if(c.data("init")){return !0}O="sidebar:"+(c.data("id")||config.currentModule+"/"+config.currentMethod);var a=E("main");a.on("click",".sidebar-toggle",function(){E.toggleSidebar(a.hasClass("hide-sidebar"))});var d=E.zui.store.get(O,c.data("hide")!==!1);d===!1&&c.addClass("no-animate"),E.toggleSidebar(d),d===!1&&setTimeout(function(){c.removeClass("no-animate")},500);var b=function(){var e=c.find(".sidebar-toggle");if(e.length){var h=e[0].getBoundingClientRect(),f=E(window).height(),g=Math.max(0,Math.floor(Math.min(f-40,h.top+h.height)-Math.max(h.top,0))/2)+(h.top<0?0-h.top:0);e.find(".icon").css("top",g)}};return b(),E(window).on("resize",b).on("scroll",b),c.data("init",1),!0}};U()||E(U),E.toggleQueryBox=function(b,a){var c=E(a||"#queryBox");c.length&&(void 0===b&&(b=!c.hasClass("show")),c.toggleClass("show",!!b),c.data("init")||(c.addClass("load-indicator loading").data("init",1),E.get(E.createLink("search","buildForm"),function(d){c.html(d).removeClass("loading")})),E(".querybox-toggle").toggleClass("querybox-opened",b))},E(function(){var a=E("#queryBox");a.length&&(E(document).on("click",".querybox-toggle",function(){E.toggleQueryBox()}),a.hasClass("show")&&E.toggleQueryBox(!0))}),E.extend(E.fn.colorPicker.Constructor.DEFAULTS,{colors:["#3DA7F5","#75C941","#2DBDB2","#797EC9","#FFAF38","#FF4E3E"]}),window.setCheckedCookie=function(){var b=[],a=E('#mainContent .main-table tbody>tr input[type="checkbox"]:checked');a.each(function(){var c=parseInt(E(this).val(),10);NaN!==c&&b.push(c)}),E.cookie("checkedItem",b.join(","),{expires:config.cookieLife,path:config.webRoot})},E.extend(E.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static"}),E(function(){E("a.iframe,.export").each(function(){var b=E(this);if(!b.parents('[data-ride="table"],.skip-iframe-modal').length){var a={type:"iframe"};b.hasClass("export")&&E.extend(a,{width:800,shown:setCheckedCookie}),b.modalTrigger(a)}})});var S=function(){var f,c,h=E(this),d=E.extend({limitSize:40,suffix:"…"},h.data()),g=h.text();if(g.length>d.limitSize){f=g,c=g.substr(0,d.limitSize)+d.suffix,h.text(c).addClass("limit-text-on");var b=d.toggleBtn?E(d.toggleBtn):h.next(".text-limit-toggle");b.text(b.data("textExpand")),b.on("click",function(){var a=h.toggleClass("limit-text-on").hasClass("limit-text-on");h.text(a?c:f),b.text(b.data(a?"textExpand":"textCollapse"))})}else{(d.toggleBtn?E(d.toggleBtn):h.next(".text-limit-toggle")).hide()}};E.fn.textLimit=function(){return this.each(S)},E(function(){E(".text-limit").textLimit()}),E.fixedTableHead=window.fixedTableHead=function(f,c){var h=E(f);if(h.is("table")||(h=h.find("table")),h.length){var d=E(c||window),g=null,b=function(){var u=h.children("thead"),n=u[0].getBoundingClientRect(),o=h.next(".fixed-head-table");if(n.top<0){var m=u.width();if(o.length){if(g!==m){g=m;var p=o.find("th");u.find("th").each(function(a){p.eq(a).width(E(this).width())})}}else{var o=E("
      ").addClass(h.attr("class")),k=u.clone(),p=k.find("th");u.find("th").each(function(a){p.eq(a).width(E(this).width())}),o.append(k).insertAfter(h)}o.css({left:n.left,width:n.width}).show()}else{o.hide()}};d.on("scroll",b).on("resize",b),b()}},E(document).on("click","tr[data-url]",function(){var b=E(this),a=b.data("href")||b.data("url");a&&(window.location.href=a)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),E(function(){E("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var D,I,Q,P,L,B=function(){D||(D=E("#subNavbar"),I=E("#pageNav"),Q=E("#pageActions"),P=D.children(".nav"),L=P.outerWidth());var g=D.outerWidth(),c=I.outerWidth()||0,k=Q.outerWidth()||0;if(c=c?c+15:0,k=k?k+15:0,!c&&!k){return void P.css({maxWidth:null,left:null,position:"static"})}var d=Math.max(300,g-c-k),h=Math.min(d,L),b=(g-h)/2,f=c&&b.btn-toolbar");if(c.length){var a,d=!1,b=null;c.children().each(function(){a=E(this);var f=a.is(".divider");f&&!b&&a.hide(),d||f||(d=!0),b=f?null:a}),a.is(".divider")&&a.hide(),d||c.hide()}};E(function(){E(".input-group,.btn-group").fixInputGroup(),N()}),window.holders&&E.each(window.holders,function(b){var a=E("#"+b);a.length&&a.is("input")&&a.attr("placeholder",window.holders[b])});var j=function(){var g,c="en"==config.clientLang?"https://www.zentao.pm/book/zentaomanual/8.html?fullScreen=zentao":"https://www.zentao.pm/book/zentaopmshelp.html?fullScreen=zentao",k=E("#navbar > .nav").first(),d=10000,h=function(){clearTimeout(g),E("#helpContent").removeClass("show-error")},b=E.openHelp=function(){h(),k.children("li.active:not(#helpMenuItem)").removeClass("active").addClass("close-help-tab"),E("#helpMenuItem").addClass("active");var e=E("#helpContent");if(e.length){if(E("body").hasClass("show-help-tab")){return void E("#helpIframe").get(0).contentWindow.location.replace(c)}}else{e=E('

      '+lang.timeout+'

      '+c+'

      '),E("#header").after(e);var l=E("#helpIframe").get(0);g=setTimeout(function(){E("#helpContent").addClass("show-error")},d),l.onload=l.onreadystatechange=function(){this.readyState&&"complete"!=this.readyState||h()}}E("body").addClass("show-help-tab")},f=E.closeHelp=function(){E("body").removeClass("show-help-tab"),E("#helpMenuItem").removeClass("active"),k.find("li.close-help-tab").removeClass("close-help-tab").addClass("active").find("a").focus()};E(document).on("click",".open-help-tab",function(l){var a=E("#helpMenuItem");a.length||(a=E('
    • '+E(this).text()+'
    • '),k.append('
    • ').append(a)),b(),l.preventDefault()}).on("click",".close-help-tab",function(a){f(),a.stopPropagation(),a.preventDefault()})};E(j),E(function(){var b=E(".table-responsive"),a=function(){b.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?E(this).css("overflow","visible"):E(this).css("overflow","auto")})};b.length&&(a(),E(window).on("resize",a))})}(jQuery);function setPing(){$("#hiddenwin").attr("src",createLink("misc","ping"))}function setForm(){var a=false;$("form").submit(function(){submitObj=$(this).find(":submit");if($(submitObj).size()>=1){var c=submitObj.prop("tagName")=="BUTTON";submitLabel=c?$(submitObj).html():$(submitObj).attr("value");$(submitObj).attr("disabled","disabled");var b=submitObj.attr("data-submitting")||lang.submitting;if(c){submitObj.text(b)}else{$(submitObj).attr("value",b)}a=true}});$("body").click(function(){if(a){$(submitObj).removeAttr("disabled");if(submitObj.prop("tagName")=="BUTTON"){submitObj.text(submitLabel)}else{$(submitObj).attr("value",submitLabel)}$(submitObj).removeClass("button-d")}a=false})}function setFormAction(b,c,f){$form=typeof(f)=="undefined"?$("form"):$(f).closest("form");if(c){$form.attr("target",c)}else{$form.removeAttr("target")}$form.attr("action",b);var d=navigator.userAgent;var a=d.indexOf("AppleWebKit")>-1&&d.indexOf("Safari")>-1&&d.indexOf("Chrome")<0;if(a){var e="checkbox-fix-"+$.zui.uuid();$form.find("[data-fix-checkbox]").remove();$form.find('input[type="checkbox"]:not(.rows-selector)').each(function(){var g=$(this);var h=e+g.val();g.clone().attr("data-fix-checkbox",h).css("display","none").after('
      ').appendTo($form)})}$form.submit()}function setImageSize(b,a){if(!a){bodyWidth=$("body").width();a=bodyWidth-470}if($(b).width()>a){$(b).attr("width",a)}$(b).wrap('')}function setMailto(a,b){link=createLink("user","ajaxGetContactUsers","listID="+b);$.get(link,function(c){$("#"+a).replaceWith(c);$("#"+a+"_chosen").remove();$("#"+a).chosen()})}function ajaxGetContacts(a){link=createLink("user","ajaxGetContactList");$.get(link,function(b){if(!b){return false}$inputgroup=$(a).closest(".input-group");$inputgroup.find(".input-group-btn").remove();$inputgroup.append(b);$inputgroup.find("select:last").chosen().fixInputGroup()})}function addItem(d,b){ItemList=document.getElementById(d);Target=document.getElementById(b);for(var a=0;a=0;a--){var b=ItemList.options[a];if(b.selected){ItemList.options[a]=null}}}function upItem(c){ItemList=document.getElementById(c);for(var a=1;a=0;a--){var b=ItemList.options[a];b.selected=true}}function ajaxDelete(a,c,b){if(confirm(b)){$.ajax({type:"GET",url:a,dataType:"json",success:function(d){if(d.result=="success"){$.get(document.location.href,function(e){if(!($(e).find("#"+c).length)){location.reload()}$("#"+c).html($(e).find("#"+c).html());if(typeof sortTable=="function"){sortTable()}$("#"+c).find("[data-toggle=modal], a.iframe").modalTrigger();if($("#"+c).find("table.datatable").length){$("#"+c).find("table.datatable").datatable()}})}}})}}function isNum(b){if(b!=null){var c,a;a=/\d*/i;c=b.match(a);return(c==b)?true:false}return false}function startCron(a){if(typeof(a)=="undefined"){a=0}$.ajax({type:"GET",timeout:100,url:createLink("cron","ajaxExec","restart="+a)})}function computePasswordStrength(b){if(b.length==0){return 0}var h=0;var e=b.length;var c="";var a=new Array();for(i=0;i=48&&d<=57){a[2]=2}else{if((d>=65&&d<=90)){a[1]=2}else{if(d>=97&&d<=122){a[0]=1}else{a[3]=3}}}if(c.indexOf(letter)==-1){c+=letter}}if(c.length>4){h+=c.length-4}var g=0;var f=0;for(i in a){f+=1;g+=a[i]}h+=g+(2*(f-1));if(e<6&&h>=10){h=9}h=h>29?29:h;h=Math.floor(h/10);return h}function checkOnlybodyPage(){if(self==parent){href=location.href.replace("?onlybody=yes","");location.href=href.replace("&onlybody=yes","")}}function fixedTheadOfList(d){if($(d).size()==0){return false}if($(d).css("display")=="none"){return false}if($(d).find("thead").size()==0){return false}e();$(window).scroll(g);$(".side-handle").click(function(){setTimeout(e,300)});var b,f,c,a;function g(){f=$(d).find("thead").offset().top;a=$(d).parent().find(".fixedTheadOfList");if(a.size()<=0&&f<$(window).scrollTop()){b=$(d).width();c=""+$(d).find("thead").html()+"
      ";$(d).before(c);$(".fixedTheadOfList").addClass($(d).attr("class")).width(b)}if(a.size()>0&&f>=$(window).scrollTop()){a.remove()}}function e(){a=$(d).parent().find(".fixedTheadOfList");if(a.size()>0){a.remove()}g()}}function applyCssStyle(e,b){b=b||"default";var d="applyStyle-"+b;var c=$("style#"+d);if(!c.length){c=$('