├── .gitignore
├── Dockerfile
├── README-PHP.md
├── README.md
├── assets
├── cacer.gif
├── license.gif
├── my-cert.gif
├── rest.gif
├── show-certs.gif
├── sign.gif
├── unsign.gif
└── verify.gif
├── certificates
├── .gitkeep
├── bundle-cert-only.zip
├── bundle-cosign.zip
├── bundle-cyrillic.zip
├── bundle-no-pin.zip
├── bundle-pin.zip
└── bundle-private-key-only.zip
├── demo-cli.sh
├── demo-php.sh
├── demo-rest.sh
├── devel
├── attach.sh
├── build.sh
├── install-certs.sh
├── reflection.php
└── rest.sh
├── scripts
├── lib
│ ├── colors.sh
│ ├── functions.sh
│ └── root.exp
├── my
├── root
├── sign
├── unsign
└── verify
└── www
├── .gitignore
├── CONTRIBUTING.md
├── README.md
├── app
├── Certificate
│ ├── Finder.php
│ └── Info.php
├── Controller.php
└── Exception.php
├── composer.json
├── composer.lock
├── docker-compose.yml
├── logs
└── README.md
├── phpunit.xml
├── public
├── dependencies.php
├── index.php
├── routes.php
└── settings.php
├── templates
└── index.phtml
├── test_extension.php
└── tests
└── Functional
├── BaseTestCase.php
└── HomepageTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /certificates
2 | /dist
3 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Базовый образ с КриптоПро
2 | FROM debian:stretch-slim as cryptopro-generic
3 |
4 | # Устанавливаем timezone
5 | ENV TZ="Europe/Moscow" \
6 | docker="1"
7 |
8 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
9 | echo $TZ > /etc/timezone
10 |
11 | # необходимо скачать со страницы https://www.cryptopro.ru/products/csp/downloads
12 | # `КриптоПро CSP 4.0 для Linux (x64, deb)` и скопировать `linux-amd64_deb.tgz` в каталог `dist`
13 |
14 | ADD dist /tmp/src
15 | RUN cd /tmp/src && \
16 | tar -xf linux-amd64_deb.tgz && \
17 | linux-amd64_deb/install.sh && \
18 | # делаем симлинки
19 | cd /bin && \
20 | ln -s /opt/cprocsp/bin/amd64/certmgr && \
21 | ln -s /opt/cprocsp/bin/amd64/cpverify && \
22 | ln -s /opt/cprocsp/bin/amd64/cryptcp && \
23 | ln -s /opt/cprocsp/bin/amd64/csptest && \
24 | ln -s /opt/cprocsp/bin/amd64/csptestf && \
25 | ln -s /opt/cprocsp/bin/amd64/der2xer && \
26 | ln -s /opt/cprocsp/bin/amd64/inittst && \
27 | ln -s /opt/cprocsp/bin/amd64/wipefile && \
28 | ln -s /opt/cprocsp/sbin/amd64/cpconfig && \
29 | # прибираемся
30 | rm -rf /tmp/src
31 |
32 | # Образ с PHP cli и скриптами
33 | FROM cryptopro-generic
34 | ADD dist /tmp/src
35 |
36 | RUN apt-get update && \
37 | apt-get install -y --no-install-recommends expect alien php7.0-cli php7.0-dev libboost-dev unzip g++ curl && \
38 | cd /tmp/src && \
39 | tar -xf cades_linux_amd64.tar.gz && \
40 | alien -kci lsb-cprocsp-devel-4.0.9921-5.noarch.rpm && \
41 | alien -kci cprocsp-pki-2.0.0-amd64-phpcades.rpm && \
42 | alien -kci cprocsp-pki-2.0.0-amd64-cades.rpm && \
43 | # меняем Makefile.unix
44 | PHP_BUILD=`php -i | grep 'PHP Extension => ' | awk '{print $4}'` && \
45 | EXT_DIR=`php -i | grep 'extension_dir => ' | awk '{print $3}'` && \
46 | # /usr/include/php/20151012/
47 | sed -i "s#PHPDIR=/php#PHPDIR=/usr/include/php/$PHP_BUILD#g" /opt/cprocsp/src/phpcades/Makefile.unix && \
48 | # копируем недостающую библиотеку
49 | ln -s /opt/cprocsp/lib/amd64/libcppcades.so.2 /opt/cprocsp/lib/amd64/libcppcades.so && \
50 | # начинаем сборку
51 | cd /opt/cprocsp/src/phpcades && \
52 | # применяем патч
53 | unzip /tmp/src/php7_support.patch.zip && \
54 | patch < php7_support.patch && \
55 | # собираем
56 | eval `/opt/cprocsp/src/doxygen/CSP/../setenv.sh --64`; make -f Makefile.unix && \
57 | # делаем симлинк собранной библиотеки
58 | mv libphpcades.so "$EXT_DIR" && \
59 | # включаем расширение
60 | echo "extension=libphpcades.so" > /etc/php/7.0/cli/conf.d/20-libphpcades.ini && \
61 | # проверяем наличие класса CPStore
62 | php -r "var_dump(class_exists('CPStore'));" | grep -q 'bool(true)' && \
63 | # прибираемся
64 | cd / && \
65 | apt-get purge -y php7.0-dev cprocsp-pki-phpcades lsb-cprocsp-devel g++ && \
66 | apt-get autoremove -y && \
67 | rm -rf /opt/cprocsp/src/phpcades && \
68 | rm -rf /tmp/src && \
69 | rm -rf /var/lib/apt/lists/
70 |
71 | ADD scripts /scripts
72 | ADD www /www
73 |
74 | # composer
75 | # RUN apt-get update && \
76 | # apt-get install -y --no-install-recommends curl ca-certificates && \
77 | # # composer
78 | # curl "https://getcomposer.org/installer" > composer-setup.php && \
79 | # php composer-setup.php && \
80 | # rm -f composer-setup.php && \
81 | # chmod +x composer.phar && \
82 | # mv composer.phar /bin/composer && \
83 | # # прибираемся
84 | # cd / && \
85 | # apt-get purge -y curl ca-certificates && \
86 |
87 | HEALTHCHECK --interval=60s --timeout=5s CMD ["curl", "-m5", "-f", "http://localhost:8080/healthcheck"]
88 |
89 | CMD ["php", "-S", "0.0.0.0:8080", "-t", "/www/public/"]
90 |
--------------------------------------------------------------------------------
/README-PHP.md:
--------------------------------------------------------------------------------
1 | # PHP КриптоПро
2 |
3 | Документация по использованию PHP КриптоПро скудна.
4 |
5 | Попытки достать параметры методов через [Reflection API](http://php.net/manual/ru/book.reflection.php) не приводят к успеху:
6 |
7 | ```PHP
8 | // Работает
9 | $r = new \ReflectionMethod('DateTime', '__construct');
10 | var_dump($r->getParameters());
11 |
12 | // Возвращает пустой массив
13 | $r = new \ReflectionMethod('CPSignedData', 'get_Content');
14 | var_export($r->getParameters());
15 | ```
16 |
17 | ## Список классов и методов
18 |
19 | ### Через Reflection API
20 |
21 | С помощью `devel/reflection.php` получен такой список классов и методов:
22 |
23 | ```
24 | CPStore
25 | Open()
26 | Close()
27 | get_Certificates()
28 | get_Location()
29 | get_Name()
30 |
31 | CPCertificates
32 | Find()
33 | Item()
34 | Count()
35 |
36 | CPCertificate
37 | GetInfo()
38 | FindPrivateKey()
39 | HasPrivateKey()
40 | IsValid()
41 | ExtendedKeyUsage()
42 | KeyUsage()
43 | Export()
44 | Import()
45 | get_SerialNumber()
46 | get_Thumbprint()
47 | get_SubjectName()
48 | get_IssuerName()
49 | get_Version()
50 | get_ValidToDate()
51 | get_ValidFromDate()
52 | BasicConstraints()
53 | PublicKey()
54 | PrivateKey()
55 |
56 | CPKeyUsage
57 | get_IsPresent()
58 | get_IsCritical()
59 | get_IsDigitalSignatureEnabled()
60 | get_IsNonRepudiationEnabled()
61 | get_IsKeyEnciphermentEnabled()
62 | get_IsDataEnciphermentEnabled()
63 | get_IsKeyAgreementEnabled()
64 | get_IsKeyCertSignEnabled()
65 | get_IsCRLSignEnabled()
66 | get_IsEncipherOnlyEnabled()
67 | get_IsDecipherOnlyEnabled()
68 |
69 | CPExtendedKeyUsage
70 | get_IsPresent()
71 | get_IsCritical()
72 | get_EKUs()
73 |
74 | CPEKU
75 | get_Name()
76 | set_Name()
77 | get_OID()
78 | set_OID()
79 |
80 | CPAlgorithm
81 | get_Name()
82 | set_Name()
83 | get_KeyLength()
84 | set_KeyLength()
85 |
86 | CPPrivateKey
87 | get_ContainerName()
88 | get_UniqueContainerName()
89 | get_ProviderName()
90 | get_ProviderType()
91 | get_KeySpec()
92 |
93 | CPEncodedData
94 | Format()
95 | get_Value()
96 |
97 | CPPublicKey
98 | get_Algorithm()
99 | get_Length()
100 | get_EncodedKey()
101 | get_EncodedParameters()
102 |
103 | CPOID
104 | get_Value()
105 | set_Value()
106 | get_FriendlyName()
107 |
108 | CPAttribute
109 | set_OID()
110 | get_OID()
111 | set_Value()
112 | get_Value()
113 | set_Name()
114 | get_Name()
115 | set_ValueEncoding()
116 | get_ValueEncoding()
117 |
118 | CPBasicConstraints
119 | set_IsPresent()
120 | get_IsPresent()
121 | set_IsCritical()
122 | get_IsCritical()
123 | get_IsCertificateAuthority()
124 | get_IsPathLenConstraintPresent()
125 | get_PathLenConstraint()
126 |
127 | CPCertificateStatus
128 | get_Result()
129 | get_CheckFlag()
130 | set_CheckFlag()
131 | EKU()
132 | get_VerificationTime()
133 | set_VerificationTime()
134 | get_UrlRetrievalTimeout()
135 | set_UrlRetrievalTimeout()
136 | CertificatePolicies()
137 | ApplicationPolicies()
138 | get_ValidationCertificates()
139 |
140 | CPEnvelopedData
141 | get_Content()
142 | set_Content()
143 | get_ContentEncoding()
144 | set_ContentEncoding()
145 | Encrypt()
146 | Decrypt()
147 | get_Recipients()
148 |
149 | CPSigner
150 | get_Certificate()
151 | set_Certificate()
152 | get_Options()
153 | set_Options()
154 | get_AuthenticatedAttributes()
155 | get_UnauthenticatedAttributes()
156 | get_TSAAddress()
157 | set_TSAAddress()
158 | get_CRLs()
159 | get_OCSPResponses()
160 | get_SigningTime()
161 | get_SignatureTimeStampTime()
162 | set_KeyPin()
163 |
164 | CPEKUs
165 | Add()
166 | get_Count()
167 | get_Item()
168 | Clear()
169 | Remove()
170 |
171 | CPAttributes
172 | Add()
173 | get_Count()
174 | get_Item()
175 | Clear()
176 | Remove()
177 | Assign()
178 |
179 | CPSigners
180 | get_Count()
181 | get_Item()
182 |
183 | CPRecipients
184 | Add()
185 | get_Count()
186 | get_Item()
187 | Clear()
188 |
189 | CPSignedData
190 | SignCades()
191 | SignHash()
192 | Sign()
193 | CoSign()
194 | CoSignCades()
195 | CoSignHash()
196 | EnhanceCades()
197 | VerifyCades()
198 | VerifyHash()
199 | Verify()
200 | set_ContentEncoding()
201 | get_ContentEncoding()
202 | set_Content()
203 | get_Content()
204 | get_Signers()
205 | get_Certificates()
206 |
207 | CPHashedData
208 | Hash()
209 | SetHashValue()
210 | get_Value()
211 | set_Algorithm()
212 | get_Algorithm()
213 | set_DataEncoding()
214 | get_DataEncoding()
215 |
216 | CPRawSignature
217 | VerifyHash()
218 | SignHash()
219 |
220 | CPSignedXML
221 | set_Content()
222 | get_Content()
223 | set_SignatureType()
224 | set_DigestMethod()
225 | set_SignatureMethod()
226 | get_Signers()
227 | Sign()
228 | Verify()
229 | ```
230 |
231 | Константы `php_CPCSP`:
232 |
233 | ```
234 | MEMORY_STORE = 0
235 | LOCAL_MACHINE_STORE = 1
236 | CURRENT_USER_STORE = 2
237 | ACTIVE_DIRECTORY_USER_STORE = 3
238 | SMART_CARD_USER_STORE = 4
239 | STORE_OPEN_READ_ONLY = 0
240 | STORE_OPEN_READ_WRITE = 1
241 | STORE_OPEN_MAXIMUM_ALLOWED = 2
242 | STORE_OPEN_EXISTING_ONLY = 128
243 | STORE_OPEN_INCLUDE_ARCHIVED = 256
244 | CERTIFICATE_FIND_SHA1_HASH = 0
245 | CERTIFICATE_FIND_SUBJECT_NAME = 1
246 | CERTIFICATE_FIND_ISSUER_NAME = 2
247 | CERTIFICATE_FIND_ROOT_NAME = 3
248 | CERTIFICATE_FIND_TEMPLATE_NAME = 4
249 | CERTIFICATE_FIND_EXTENSION = 5
250 | CERTIFICATE_FIND_EXTENDED_PROPERTY = 6
251 | CERTIFICATE_FIND_APPLICATION_POLICY = 7
252 | CERTIFICATE_FIND_CERTIFICATE_POLICY = 8
253 | CERTIFICATE_FIND_TIME_VALID = 9
254 | CERTIFICATE_FIND_TIME_NOT_YET_VALID = 10
255 | CERTIFICATE_FIND_TIME_EXPIRED = 11
256 | CERTIFICATE_FIND_KEY_USAGE = 12
257 | CERT_INFO_SUBJECT_SIMPLE_NAME = 0
258 | CERT_INFO_ISSUER_SIMPLE_NAME = 1
259 | CERT_INFO_SUBJECT_EMAIL_NAME = 2
260 | CERT_INFO_ISSUER_EMAIL_NAME = 3
261 | CERT_INFO_SUBJECT_UPN = 4
262 | CERT_INFO_ISSUER_UPN = 5
263 | CERT_INFO_SUBJECT_DNS_NAME = 6
264 | CERT_INFO_ISSUER_DNS_NAME = 7
265 | DIGITAL_SIGNATURE_KEY_USAGE = 128
266 | NON_REPUDIATION_KEY_USAGE = 64
267 | KEY_ENCIPHERMENT_KEY_USAGE = 32
268 | DATA_ENCIPHERMENT_KEY_USAGE = 16
269 | KEY_AGREEMENT_KEY_USAGE = 8
270 | KEY_CERT_SIGN_KEY_USAGE = 4
271 | OFFLINE_CRL_SIGN_KEY_USAGE = 2
272 | CRL_SIGN_KEY_USAGE = 2
273 | ENCIPHER_ONLY_KEY_USAGE = 1
274 | DECIPHER_ONLY_KEY_USAGE = 32768
275 | ENCODE_BASE64 = 0
276 | ENCODE_BINARY = 1
277 | ENCODE_ANY = 4294967295
278 | CADESCOM_ENCRYPTION_ALGORITHM_RC2 = 0
279 | CADESCOM_ENCRYPTION_ALGORITHM_RC4 = 1
280 | CADESCOM_ENCRYPTION_ALGORITHM_DES = 2
281 | CADESCOM_ENCRYPTION_ALGORITHM_3DES = 3
282 | CADESCOM_ENCRYPTION_ALGORITHM_AES = 4
283 | CADESCOM_ENCRYPTION_ALGORITHM_GOST_28147_89 = 25
284 | ENCRYPTION_KEY_LENGTH_MAXIMUM = 0
285 | ENCRYPTION_KEY_LENGTH_40_BITS = 1
286 | ENCRYPTION_KEY_LENGTH_56_BITS = 2
287 | ENCRYPTION_KEY_LENGTH_128_BITS = 3
288 | ENCRYPTION_KEY_LENGTH_192_BITS = 4
289 | ENCRYPTION_KEY_LENGTH_256_BITS = 5
290 | EKU_OTHER = 0
291 | EKU_SERVER_AUTH = 1
292 | EKU_CLIENT_AUTH = 2
293 | EKU_CODE_SIGNING = 3
294 | EKU_EMAIL_PROTECTION = 4
295 | EKU_SMARTCARD_LOGON = 5
296 | EKU_ENCRYPTING_FILE_SYSTEM = 6
297 | SEX_NOT_KNOWN = 0
298 | SEX_MALE = 1
299 | SEX_FEMALE = 2
300 | SEX_NOT_APPLICABLE = 9
301 | PROV_RSA_FULL = 1
302 | PROV_RSA_SIG = 2
303 | PROV_DSS = 3
304 | PROV_FORTEZZA = 4
305 | PROV_MS_EXCHANGE = 5
306 | PROV_SSL = 6
307 | PROV_RSA_SCHANNEL = 12
308 | PROV_DSS_DH = 13
309 | PROV_EC_ECDSA_SIG = 14
310 | PROV_EC_ECNRA_SIG = 15
311 | PROV_EC_ECDSA_FULL = 16
312 | PROV_EC_ECNRA_FULL = 17
313 | PROV_DH_SCHANNEL = 18
314 | PROV_SPYRUS_LYNKS = 20
315 | PROV_RNG = 21
316 | PROV_INTEL_SEC = 22
317 | PROV_REPLACE_OWF = 23
318 | PROV_RSA_AES = 24
319 | KEY_SPEC_KEYEXCHANGE = 1
320 | KEY_SPEC_SIGNATURE = 2
321 | OID_OTHER = 0
322 | OID_AUTHORITY_KEY_IDENTIFIER_EXTENSION = 1
323 | OID_KEY_ATTRIBUTES_EXTENSION = 2
324 | OID_CERT_POLICIES_95_EXTENSION = 3
325 | OID_KEY_USAGE_RESTRICTION_EXTENSION = 4
326 | OID_LEGACY_POLICY_MAPPINGS_EXTENSION = 5
327 | OID_SUBJECT_ALT_NAME_EXTENSION = 6
328 | OID_ISSUER_ALT_NAME_EXTENSION = 7
329 | OID_BASIC_CONSTRAINTS_EXTENSION = 8
330 | OID_SUBJECT_KEY_IDENTIFIER_EXTENSION = 9
331 | OID_KEY_USAGE_EXTENSION = 10
332 | OID_PRIVATEKEY_USAGE_PERIOD_EXTENSION = 11
333 | OID_SUBJECT_ALT_NAME2_EXTENSION = 12
334 | OID_ISSUER_ALT_NAME2_EXTENSION = 13
335 | OID_BASIC_CONSTRAINTS2_EXTENSION = 14
336 | OID_NAME_CONSTRAINTS_EXTENSION = 15
337 | OID_CRL_DIST_POINTS_EXTENSION = 16
338 | OID_CERT_POLICIES_EXTENSION = 17
339 | OID_POLICY_MAPPINGS_EXTENSION = 18
340 | OID_AUTHORITY_KEY_IDENTIFIER2_EXTENSION = 19
341 | OID_POLICY_CONSTRAINTS_EXTENSION = 20
342 | OID_ENHANCED_KEY_USAGE_EXTENSION = 21
343 | OID_CERTIFICATE_TEMPLATE_EXTENSION = 22
344 | OID_APPLICATION_CERT_POLICIES_EXTENSION = 23
345 | OID_APPLICATION_POLICY_MAPPINGS_EXTENSION = 24
346 | OID_APPLICATION_POLICY_CONSTRAINTS_EXTENSION = 25
347 | OID_AUTHORITY_INFO_ACCESS_EXTENSION = 26
348 | OID_SERVER_AUTH_eku = 100
349 | OID_CLIENT_AUTH_eku = 101
350 | OID_CODE_SIGNING_eku = 102
351 | OID_EMAIL_PROTECTION_eku = 103
352 | OID_IPSEC_END_SYSTEM_eku = 104
353 | OID_IPSEC_TUNNEL_eku = 105
354 | OID_IPSEC_USER_eku = 106
355 | OID_TIME_STAMPING_eku = 107
356 | OID_CTL_USAGE_SIGNING_eku = 108
357 | OID_TIME_STAMP_SIGNING_eku = 109
358 | OID_SERVER_GATED_CRYPTO_eku = 110
359 | OID_ENCRYPTING_FILE_SYSTEM_eku = 111
360 | OID_EFS_RECOVERY_eku = 112
361 | OID_WHQL_CRYPTO_eku = 113
362 | OID_NT5_CRYPTO_eku = 114
363 | OID_OEM_WHQL_CRYPTO_eku = 115
364 | OID_EMBEDED_NT_CRYPTO_eku = 116
365 | OID_ROOT_LIST_SIGNER_eku = 117
366 | OID_QUALIFIED_SUBORDINATION_eku = 118
367 | OID_KEY_RECOVERY_eku = 119
368 | OID_DIGITAL_RIGHTS_eku = 120
369 | OID_LICENSES_eku = 121
370 | OID_LICENSE_SERVER_eku = 122
371 | OID_SMART_CARD_LOGON_eku = 123
372 | OID_PKIX_POLICY_QUALIFIER_CPS = 124
373 | OID_PKIX_POLICY_QUALIFIER_USERNOTICE = 125
374 | AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0
375 | AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME = 1
376 | AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION = 2
377 | ATTRIBUTE_OTHER = 4294967295
378 | CHECK_NONE = 0
379 | CHECK_TRUSTED_ROOT = 1
380 | CHECK_TIME_VALIDITY = 2
381 | CHECK_SIGNATURE_VALIDITY = 4
382 | CHECK_ONLINE_REVOCATION_STATUS = 8
383 | CHECK_OFFLINE_REVOCATION_STATUS = 16
384 | CHECK_COMPLETE_CHAIN = 32
385 | CHECK_NAME_CONSTRAINTS = 64
386 | CHECK_BASIC_CONSTRAINTS = 128
387 | CHECK_NESTED_VALIDITY_PERIOD = 256
388 | CHECK_ONLINE_ALL = 495
389 | CHECK_OFFLINE_ALL = 503
390 | STRING_TO_UCS2LE = 0
391 | BASE64_TO_BINARY = 1
392 | CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT = 0
393 | CERTIFICATE_INCLUDE_WHOLE_CHAIN = 1
394 | CERTIFICATE_INCLUDE_END_ENTITY_ONLY = 2
395 | CADES_DEFAULT = 0
396 | CADES_BES = 1
397 | CADES_X_LONG_TYPE_1 = 93
398 | CADES_T = 5
399 | VERIFY_SIGNATURE_ONLY = 0
400 | VERIFY_SIGNATURE_AND_CERTIFICATE = 1
401 | HASH_ALGORITHM_SHA1 = 0
402 | HASH_ALGORITHM_MD2 = 1
403 | HASH_ALGORITHM_MD4 = 2
404 | HASH_ALGORITHM_MD5 = 3
405 | HASH_ALGORITHM_SHA_256 = 4
406 | HASH_ALGORITHM_SHA_384 = 5
407 | HASH_ALGORITHM_SHA_512 = 6
408 | HASH_ALGORITHM_GOSTR_3411 = 100
409 | CADESCOM_HASH_ALGORITHM_CP_GOST_3411 = 100
410 | CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2012_256 = 101
411 | CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2012_512 = 102
412 | XML_SIGNATURE_TYPE_ENVELOPED = 0
413 | XML_SIGNATURE_TYPE_ENVELOPING = 1
414 | XML_SIGNATURE_TYPE_TEMPLATE = 2
415 | ```
416 |
417 | ### Через исходные коды
418 |
419 | В скачаном с официального сайта архиве `cades_linux_amd64.tar.gz` есть RPM пакет `cprocsp-pki-2.0.0-amd64-phpcades.rpm`, в котором находятся исходные тексты расширения, в том числе `test_extension.php` (скопирован в `devel/test_extension.php`).
420 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # КриптоПро 4.0 в докер контейнере
2 |
3 | Содержимое контейнера:
4 |
5 | * PHP7 с установленным расширением `libphpcades` (`CPStore`, `CPSigner`, `CPSignedData`)
6 | * инструменты КриптоПро: `certmgr`, `cpverify`, `cryptcp`, `csptest`, `csptestf`, `der2xer`, `inittst`, `wipefile`, `cpconfig`
7 | * вспомогательные скрипты командой строки
8 | * HTTP REST-сервер
9 |
10 | Есть 3 варианта использования контейнера:
11 |
12 | * [через интерфейс командной строки](#cli) (и ssh-клиент для удаленных машин)
13 | * [через HTTP REST-сервер](#http)
14 | * добавить свои обработчики внутрь контейнера
15 |
16 | # Структура проекта
17 |
18 | ```
19 | ├── assets - материалы для README.md
20 | ├── devel - devel скрипты
21 | ├── certificates - тестовые сертификаты
22 | ├── dist - пакеты КриптоПро (необходимо скачать с официального сайта)
23 | ├── Dockerfile - файл сборки образа
24 | ├── README.md - этот файл
25 | └── scripts - вспомогательные скрипты командой строки
26 | └── www - HTTP REST-сервер
27 | ````
28 |
29 | # Создание образа из исходного кода
30 |
31 | Скачать с официального сайта в `dist/` (необходимо быть залогиненым в системе):
32 |
33 | * [КриптоПро CSP 4.0 для Linux (x64, deb)](https://www.cryptopro.ru/products/csp/downloads) => `dist/linux-amd64_deb.tgz`
34 | * Browser plug-in [версия 2.0 для пользователей](https://www.cryptopro.ru/products/cades/plugin) => `dist/cades_linux_amd64.tar.gz` - Linux версию
35 | * [Патч для PHP7](https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=79589#post79589) => `dist/php7_support.patch.zip`
36 |
37 | Запустить:
38 |
39 | ```
40 | docker build --tag required/cryptopro .
41 | ```
42 |
43 | ## Возможные проблемы
44 |
45 | В `Dockerfile` содержатся названия пакетов, например `lsb-cprocsp-devel-4.0.9921-5.noarch.rpm`, которые могут заменить новой версией. Следует поправить названия пакетов в `Dockerfile`.
46 |
47 | # Запуск контейнера
48 |
49 | Запустим контейнер под именем `cryptopro`, к которому будем обращаться в примерах:
50 |
51 | ```
52 | docker run -it --rm -p 8095:80 --name cryptopro required/cryptopro
53 | ```
54 |
55 | # Работа с контейнером через интерфейс командной строки
56 |
57 | ## Лицензия
58 |
59 | Установка серийного номера:
60 |
61 | ```
62 | docker exec -i cryptopro cpconfig -license -set <серийный_номер>
63 | ```
64 |
65 | Просмотр:
66 |
67 | ```
68 | docker exec -i cryptopro cpconfig -license -view
69 | ```
70 |
71 | 
72 |
73 |
74 | ## Установка корневых сертификатов
75 |
76 | Для установки корневых сертификатов нужно на `stdin` скрипта `/scripts/root` передать файл с сертификатами. Если в файле несколько сертификатов, все они будут установлены.
77 |
78 | ### Через скачивание на диск
79 |
80 | Скачаем сертификат на диск с помощью `curl` и передадим полученный файл на `stdin` с запуском команды его установки:
81 |
82 | ```
83 | curl -sS http://cpca.cryptopro.ru/cacer.p7b > certificates/cacer.p7b
84 | cat certificates/cacer.p7b | docker exec -i cryptopro /scripts/root
85 | ```
86 |
87 | ### Без скачивания на диск
88 |
89 | ```
90 | # сертификаты УЦ
91 | curl -sS http://cpca.cryptopro.ru/cacer.p7b | docker exec -i cryptopro /scripts/root
92 | # сертификаты тестового УЦ
93 | curl -sS http://testca2012.cryptopro.ru/cert/rootca.cer | docker exec -i cryptopro /scripts/root
94 | curl -sS http://testca2012.cryptopro.ru/cert/subca.cer | docker exec -i cryptopro /scripts/root
95 | ```
96 |
97 | 
98 |
99 | Примечание: по какой-то причине иногда "заедает", но при повторном запуске - срабатывает.
100 |
101 | ## Установка сертификатов пользователя для проверки и подписания
102 |
103 | Необходимо специальным образом сформировать zip-архив `bundle.zip` и отправить его на `stdin` скрипта `/scripts/my`. Пример такого zip-файла:
104 |
105 | ```
106 | ├── certificate.cer - файл сертификата (не обязательно)
107 | └── le-09650.000 - каталог с файлами закрытого ключа (не обязательно)
108 | ├── header.key
109 | ├── masks2.key
110 | ├── masks.key
111 | ├── name.key
112 | ├── primary2.key
113 | └── primary.key
114 | ```
115 |
116 | [Как получить сертификат КриптоПро](http://pushorigin.ru/cryptopro/real-cert-crypto-pro-linux).
117 |
118 | Первый найденный файл в корне архива будет воспринят как сертификат, а первый найденный каталог - как связка файлов закрытого ключа. Пароль от контейнера, если есть, передается первым параметром командной строки.
119 |
120 | В каталоге `certificates/` содержатся различные комбинации тестового сертификата и закрытого ключа, с PIN кодом и без:
121 |
122 | ```
123 | ├── bundle-cert-only.zip - только сертификат
124 | ├── bundle-cosign.zip - сертификат + закрытый ключ БЕЗ пин-кода (для добавления второй подписи)
125 | ├── bundle-cyrillic.zip - сертификат + закрытый ключ, название контейнера "тестовое название контейнера" (кириллица)
126 | ├── bundle-no-pin.zip - сертификат + закрытый ключ БЕЗ пин-кода
127 | ├── bundle-pin.zip - сертификат + закрытый ключ с пин-кодом 12345678
128 | └── bundle-private-key-only.zip - только закрытый ключ
129 | ```
130 |
131 | Примеры:
132 |
133 | ```
134 | # сертификат + закрытый ключ с пин-кодом
135 | cat certificates/bundle-pin.zip | docker exec -i cryptopro /scripts/my 12345678
136 |
137 | # сертификат + закрытый ключ БЕЗ пин-кода
138 | cat certificates/bundle-no-pin.zip | docker exec -i cryptopro /scripts/my
139 |
140 | # только сертификат
141 | cat certificates/bundle-cert-only.zip | docker exec -i cryptopro /scripts/my
142 |
143 | # только закрытый ключ
144 | cat certificates/bundle-private-key-only.zip | docker exec -i cryptopro /scripts/my
145 |
146 | # сертификат + закрытый ключ, название контейнера "тестовое название контейнера" (кириллица)
147 | cat certificates/bundle-cyrillic.zip | docker exec -i cryptopro /scripts/my
148 | ```
149 |
150 | 
151 |
152 | ## Просмотр установленных сертификатов
153 |
154 | Сертификаты пользователя:
155 |
156 | ```
157 | docker exec -i cryptopro certmgr -list
158 | ```
159 |
160 | 
161 |
162 | Корневые сертификаты:
163 |
164 | ```
165 | docker exec -i cryptopro certmgr -list -store root
166 | ```
167 |
168 | ## Подписание документа
169 |
170 | Для примера установим этот тестовый сертификат:
171 |
172 | ```
173 | # сертификат + закрытый ключ с пин-кодом
174 | cat certificates/bundle-pin.zip | docker exec -i cryptopro /scripts/my 12345678
175 | ```
176 |
177 | Его SHA1 Hash равен `dd45247ab9db600dca42cc36c1141262fa60e3fe` (узнать: `certmgr -list`), который будем использовать как указатель нужного сертификата.
178 |
179 | Теперь передадим на `stdin` файл, в качестве команды - последовательность действий, и на `stdout` получим подписанный файл:
180 |
181 | ```
182 | cat README.md | docker exec -i cryptopro sh -c 'tmp=`mktemp`; cat - > "$tmp"; cryptcp -sign -thumbprint dd45247ab9db600dca42cc36c1141262fa60e3fe -nochain -pin 12345678 "$tmp" "$tmp.sig" > /dev/null 2>&1; cat "$tmp.sig"; rm -f "$tmp" "$tmp.sig"'
183 | ```
184 |
185 | Получилось довольно неудобно. Скрипт `scripts/sign` делает то же самое, теперь команда подписания будет выглядеть так:
186 |
187 | ```
188 | cat README.md | docker exec -i cryptopro /scripts/sign dd45247ab9db600dca42cc36c1141262fa60e3fe 12345678
189 | ```
190 |
191 | 
192 |
193 | Об ошибке можно узнать через стандартный `$?`.
194 |
195 | ## Проверка подписи
196 |
197 | Подпишем файл из примера выше и сохраним его на диск:
198 |
199 | ```
200 | cat README.md | docker exec -i cryptopro /scripts/sign dd45247ab9db600dca42cc36c1141262fa60e3fe 12345678 > certificates/README.md.sig
201 | ```
202 |
203 | Тогда проверка подписанного файла будет выглядеть так:
204 |
205 | ```
206 | cat certificates/README.md.sig | docker exec -i cryptopro sh -c 'tmp=`mktemp`; cat - > "$tmp"; cryptcp -verify -norev -f "$tmp" "$tmp"; rm -f "$tmp"'
207 | ```
208 |
209 | То же самое, но с использованием скрипта:
210 |
211 | ```
212 | cat certificates/README.md.sig | docker exec -i cryptopro scripts/verify
213 | ```
214 |
215 | 
216 |
217 | ## Получение исходного файла из sig-файла
218 |
219 | Возьмем файл из примера выше:
220 |
221 | ```
222 | cat certificates/README.md.sig | docker exec -i cryptopro sh -c 'tmp=`mktemp`; cat - > "$tmp"; cryptcp -verify -nochain "$tmp" "$tmp.origin" > /dev/null 2>&1; cat "$tmp.origin"; rm -f "$tmp" "$tmp.origin"'
223 | ```
224 |
225 | То же самое, но с использованием скрипта:
226 |
227 | ```
228 | cat certificates/README.md.sig | docker exec -i cryptopro scripts/unsign
229 | ```
230 |
231 | 
232 |
233 | ## Использование контейнера на удаленной машине
234 |
235 | В примерах выше команды выглядят так: `cat ... | docker ...` или `curl ... | docker ...`, то есть контейнер запущен на локальной машине. Если же докер контейнер запущен на удаленной машине, то команды нужно отправлять через ssh клиент. Например, команда подписания:
236 |
237 | ```
238 | cat README.md | ssh -q user@host 'docker exec -i cryptopro /scripts/sign dd45247ab9db600dca42cc36c1141262fa60e3fe 12345678'
239 | ```
240 |
241 | Опция `-q` отключает приветствие из файла `/etc/banner` (хотя оно все равно пишется в `stderr`). А `/etc/motd` при выполнении команды по ssh не выводится.
242 |
243 | В качестве эксперимента можно отправить по ssh на свою же машину так:
244 |
245 | ```
246 | # копируем публичный ключ на "удаленную машину" (на самом деле - localhost)
247 | ssh-copy-id $(whoami)@localhost
248 | # пробуем подписать
249 | cat README.md | ssh -q $(whoami)@localhost 'docker exec -i cryptopro /scripts/sign dd45247ab9db600dca42cc36c1141262fa60e3fe 12345678'
250 | ```
251 |
252 | # Работа с контейнером через HTTP REST-сервер
253 |
254 | Установка сертификатов осуществляется через командую строку. Все остальные действия доступны по HTTP.
255 |
256 | * `/healthcheck` - проверка работоспособности (`GET`)
257 | * `/certificates` - все установленные сертификаты пользователя (`GET`)
258 | * `/sign` - подписание документов (`POST`)
259 | * `/cosign` - добавление еще одной подписи к документу (`POST`)
260 | * `/verify` - проверка подписанного документа (`POST`)
261 | * `/unsign` - получение исходного файла без подписей (`POST`)
262 |
263 | 
264 |
265 | ## Формат данных
266 |
267 | Для `POST` данные должны поступать в теле запроса в формате `x-www-form-urlencoded`.
268 |
269 | Возвращаются данные в формате `JSON`.
270 |
271 | ## Обработка ошибок
272 |
273 | Успешные действия возвращают код `200` и `"status": "ok"`.
274 |
275 | Действия с ошибками возвращают `4xx` и `5xx` коды и `"status": "fail"`, в полях `errMsg` содержится описание ошибки, в `errCode` - ее код.
276 |
277 | Например, обращение с неправильным методом
278 |
279 | ```sh
280 | curl -sS -X POST --data-binary "bindata" http://localhost:8095/healthchecks
281 | ```
282 |
283 | выведет такую ошибку:
284 |
285 | ```JSON
286 | {"status":"fail","errMsg":"Method must be one of: GET","errCode":405}
287 | ```
288 |
289 | ## `/healthcheck` - проверка работоспособности
290 |
291 | Используется, чтобы убедиться в работоспособности сервиса. Например, так: `docker ps -f name=cryptopro` или `curl http://localhost:8095/healthcheck`.
292 |
293 | ## `/certificates` - все установленные сертификаты пользователя
294 |
295 | ```
296 | curl -sS http://localhost:8095/certificates
297 | ```
298 |
299 | Если сертификатов нет:
300 |
301 | ```JSON
302 | {"status":"fail","errMsg":"No certificates in store 'My'","errCode":404}
303 | ```
304 |
305 | Если сертификаты есть:
306 |
307 | ```JSON
308 | {
309 | "certificates": [
310 | {
311 | "privateKey": {
312 | "providerName": "Crypto-Pro GOST R 34.10-2012 KC1 CSP",
313 | "uniqueContainerName": "HDIMAGE\\\\eb5f6857.000\\D160",
314 | "containerName": "eb5f6857-a08a-4510-8a96-df2f75b6d65a"
315 | },
316 | "algorithm": {
317 | "name": "ГОСТ Р 34.10-2012",
318 | "val": "1.2.643.7.1.1.1.1"
319 | },
320 | "valid": {
321 | "to": "24.05.2019 08:13:16",
322 | "from": "24.02.2019 08:03:16"
323 | },
324 | "issuer": {
325 | "E": "support@cryptopro.ru",
326 | "C": "RU",
327 | "L": "Moscow",
328 | "O": "CRYPTO-PRO LLC",
329 | "CN": "CRYPTO-PRO Test Center 2",
330 | "raw": "CN=CRYPTO-PRO Test Center 2, O=CRYPTO-PRO LLC, L=Moscow, C=RU, E=support@cryptopro.ru"
331 | },
332 | "subject": {
333 | "C": "RU",
334 | "L": "Test",
335 | "O": "Test",
336 | "OU": "Test",
337 | "CN": "Test",
338 | "E": "test@test.ru",
339 | "raw": "E=test@test.ru, CN=Test, OU=Test, O=Test, L=Test, S=Test, C=RU"
340 | },
341 | "thumbprint": "982AA9E713A2F99B10DAA07DCDC94A4BC32A1027",
342 | "serialNumber": "120032C3567443029CC358FCDF00000032C356",
343 | "hasPrivateKey": true
344 | }
345 | ],
346 | "status": "ok"
347 | }
348 | ```
349 |
350 | ## `/sign` - подписание документов
351 |
352 | Для выбора сертификата для подписания нужно указать один критерии поиска `find_type`:
353 |
354 | * `sha1` - по SHA1 сертификата
355 | * `subject` - по `subject` подписанта
356 |
357 | В `query` - параметры поиска, в `pin` - пин-код (если он установлен):
358 |
359 | ```sh
360 | CERT_QUERY="find_type=sha1&query=82028260efc03eedc88dcb61c0f6a02e788e26e2&pin=12345678"
361 | curl -sS -X POST --data-binary @- "http://localhost:8095/sign?$CERT_QUERY" < README.md
362 | ```
363 |
364 | Вернется `JSON` - документ, в `signedContent` будет содержаться подписанный файл.
365 |
366 | ## `/cosign` - добавление еще одной подписи к документу
367 |
368 | Не реализовано, столкнулся с проблемой: не получается заставить работать функцию `CPSignedData::CoSignCades()`.
369 |
370 | ## `/verify` - проверка подписанного документа
371 |
372 | Подпишем файл и проверим его:
373 |
374 | ```sh
375 | # подпишем файл
376 | CERT_QUERY="find_type=sha1&query=82028260efc03eedc88dcb61c0f6a02e788e26e2&pin=12345678"
377 | curl -sS -X POST --data-binary @- "http://localhost:8095/sign?$CERT_QUERY" < README.md > /tmp/file.json
378 | # извлечем подписанный файл из "signedContent"
379 | jq ".signedContent" --raw-output /tmp/file.json > /tmp/file.sig
380 | # проверим подписанный файл
381 | curl -sS -X POST --data-binary @- "http://localhost:8095/verify" < /tmp/file.sig
382 | ```
383 |
384 | Если файл прошел проверку, вернется список подписантов `signers`.
385 |
386 |
387 | ## `/unsign` - получение исходного файла без подписей
388 |
389 | Исходный файл вернется в поле `content`.
390 |
391 | ```sh
392 | # получим из подписанного файла /tmp/file.sig оригинальный файл, он будет в "content" файла /tmp/unsig.json
393 | curl -sS -X POST --data-binary @- "http://localhost:8095/unsign" < /tmp/file.sig > /tmp/unsig.json
394 | # выведем на экран первые несколько строк
395 | jq ".content" --raw-output /tmp/unsig.json | base64 -d | head
396 | ```
397 |
398 |
399 | ## Проблемы
400 |
401 | Если pin-код не подходит, то в терминал выводится:
402 |
403 | ```
404 | Wrong pin, 2 tries left.
405 |
406 | CryptoPro CSP: Type password for container "eb5f6857-a08a-4510-8a96-df2f75b6d65a"
407 | Password:
408 | ```
409 |
410 | И подписание останавливается.
411 |
412 |
413 | # Ссылки
414 |
415 | * [Страница расширения для PHP](http://cpdn.cryptopro.ru/default.asp?url=content/cades/phpcades.html)
416 | * [Тестовый УЦ](http://testca2012.cryptopro.ru/ui/), его сертификаты: [корневой](http://testca2012.cryptopro.ru/cert/rootca.cer), [промежуточный](http://testca2012.cryptopro.ru/cert/subca.cer)
417 |
418 |
419 | # Аналоги
420 |
421 | Существует аналогичный пакет [CryptoProCSP](https://github.com/taigasys/CryptoProCSP), он классный, но:
422 |
423 | * давно не обновлялся, используется версия `PHP5.6`
424 | * для запуска пришлось подредактировать `Dockerfile`
425 |
--------------------------------------------------------------------------------
/assets/cacer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/cacer.gif
--------------------------------------------------------------------------------
/assets/license.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/license.gif
--------------------------------------------------------------------------------
/assets/my-cert.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/my-cert.gif
--------------------------------------------------------------------------------
/assets/rest.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/rest.gif
--------------------------------------------------------------------------------
/assets/show-certs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/show-certs.gif
--------------------------------------------------------------------------------
/assets/sign.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/sign.gif
--------------------------------------------------------------------------------
/assets/unsign.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/unsign.gif
--------------------------------------------------------------------------------
/assets/verify.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/assets/verify.gif
--------------------------------------------------------------------------------
/certificates/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/certificates/.gitkeep
--------------------------------------------------------------------------------
/certificates/bundle-cert-only.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/certificates/bundle-cert-only.zip
--------------------------------------------------------------------------------
/certificates/bundle-cosign.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/certificates/bundle-cosign.zip
--------------------------------------------------------------------------------
/certificates/bundle-cyrillic.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/certificates/bundle-cyrillic.zip
--------------------------------------------------------------------------------
/certificates/bundle-no-pin.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/certificates/bundle-no-pin.zip
--------------------------------------------------------------------------------
/certificates/bundle-pin.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/certificates/bundle-pin.zip
--------------------------------------------------------------------------------
/certificates/bundle-private-key-only.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbfun/cryptopro/769a880d9757da563e46858e2dd765463db71e0f/certificates/bundle-private-key-only.zip
--------------------------------------------------------------------------------
/demo-cli.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Демонстрация основных возможностей командной строки
5 | #
6 |
7 | cd "$(dirname "$0")"
8 | source scripts/lib/colors.sh
9 | source scripts/lib/functions.sh
10 |
11 | warning 'Установка корневого сертификата'
12 | info 'curl -sS http://testca2012.cryptopro.ru/cert/rootca.cer | docker exec -i cryptopro /scripts/root'
13 | sleep 5
14 | echo
15 | curl -sS http://testca2012.cryptopro.ru/cert/rootca.cer | docker exec -i cryptopro /scripts/root
16 |
17 | echo
18 | sleep 2
19 |
20 | warning 'Установка сертификата + закрытый ключ'
21 | info 'cat certificates/bundle-pin.zip | docker exec -i cryptopro /scripts/my 12345678'
22 | sleep 5
23 | echo
24 | cat certificates/bundle-pin.zip | docker exec -i cryptopro /scripts/my 12345678
25 |
26 | echo
27 | sleep 2
28 |
29 | warning 'Подписание документа'
30 | info 'cat README.md | docker exec -i cryptopro /scripts/sign dd45247ab9db600dca42cc36c1141262fa60e3fe 12345678'
31 | sleep 5
32 | echo
33 | cat README.md | docker exec -i cryptopro /scripts/sign dd45247ab9db600dca42cc36c1141262fa60e3fe 12345678
34 |
35 | echo
36 | sleep 2
37 |
38 | warning 'Проверка подписи документа'
39 | info 'cat /tmp/README.md.sig | docker exec -i cryptopro scripts/verify'
40 | cat README.md | docker exec -i cryptopro /scripts/sign dd45247ab9db600dca42cc36c1141262fa60e3fe 12345678 > /tmp/README.md.sig
41 | sleep 5
42 | echo
43 | cat /tmp/README.md.sig | docker exec -i cryptopro scripts/verify
44 |
--------------------------------------------------------------------------------
/demo-php.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Демонстрация работы PHP
5 | #
6 |
7 | cd "$(dirname "$0")"
8 | source scripts/lib/colors.sh
9 | source scripts/lib/functions.sh
10 |
11 | warning 'Установка корневого сертификата'
12 | info 'curl -sS http://testca.cryptopro.ru/CertEnroll/test-ca-2014_CRYPTO-PRO%20Test%20Center%202.crt | docker exec -i cryptopro /scripts/root'
13 | sleep 5
14 | echo
15 | curl -sS http://testca.cryptopro.ru/CertEnroll/test-ca-2014_CRYPTO-PRO%20Test%20Center%202.crt | docker exec -i cryptopro /scripts/root
16 |
17 | echo
18 | sleep 2
19 |
20 | warning 'Установка сертификата + закрытый ключ'
21 | info 'cat certificates/bundle-Test.zip | docker exec -i cryptopro /scripts/my'
22 | sleep 5
23 | echo
24 | cat certificates/bundle-Test.zip | docker exec -i cryptopro /scripts/my
25 |
26 | echo
27 | sleep 2
28 |
29 | warning 'Проверка cryptopro в PHP'
30 | info 'docker exec -i cryptopro php /www/test_extension.php'
31 | sleep 5
32 | echo
33 | docker exec -i cryptopro php /www/test_extension.php
34 |
--------------------------------------------------------------------------------
/demo-rest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Демонстрация работы REST сервера
5 | #
6 |
7 | cd "$(dirname "$0")"
8 | source scripts/lib/colors.sh
9 | source scripts/lib/functions.sh
10 |
11 | REST_URI="http://localhost:8095"
12 | FILE_TO_SIGN="README.md"
13 | CERT_QUERY="find_type=sha1&query=82028260efc03eedc88dcb61c0f6a02e788e26e2&pin=12345678"
14 |
15 | # warning 'Установка корневого сертификата'
16 | curl -sS http://testca.cryptopro.ru/CertEnroll/test-ca-2014_CRYPTO-PRO%20Test%20Center%202.crt | docker exec -i cryptopro /scripts/root > /dev/null
17 |
18 | # warning 'Установка сертификатов пользователя'
19 | cat certificates/bundle-Test.zip | docker exec -i cryptopro /scripts/my > /dev/null
20 | cat certificates/bundle-cosign.zip | docker exec -i cryptopro /scripts/my 12345678 > /dev/null
21 |
22 | warning "Подписание файла $FILE_TO_SIGN"
23 | info "curl -sS -X POST --data-binary @- "$REST_URI/sign?$CERT_QUERY" < "$FILE_TO_SIGN" > /tmp/file.json"
24 | curl -sS -X POST --data-binary @- "$REST_URI/sign?$CERT_QUERY" < "$FILE_TO_SIGN" > /tmp/file.json
25 |
26 | jq .status "/tmp/file.json"
27 |
28 | echo
29 | sleep 3
30 |
31 | warning "Проверка подписи"
32 | jq ".signedContent" --raw-output /tmp/file.json > /tmp/file.sig
33 | info "curl -sS -X POST --data-binary @- "$REST_URI/verify" < /tmp/file.sig | jq .status"
34 | curl -sS -X POST --data-binary @- "$REST_URI/verify" < /tmp/file.sig | jq .status
35 |
36 | echo
37 | sleep 3
38 |
39 | warning "Получение исходного файла"
40 | info "curl -sS -X POST --data-binary @- "$REST_URI/unsign" < /tmp/file.sig > /tmp/unsig.json"
41 | curl -sS -X POST --data-binary @- "$REST_URI/unsign" < /tmp/file.sig > /tmp/unsig.json
42 | jq .status "/tmp/unsig.json"
43 |
44 | echo
45 | sleep 3
46 |
47 | warning "Первые несколько строк исходного файла"
48 | jq ".content" --raw-output /tmp/unsig.json | base64 -d | head -n5
49 |
--------------------------------------------------------------------------------
/devel/attach.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # подключение к запущенному контейнеру
5 | #
6 |
7 | docker exec -it cryptopro sh -c "/bin/bash"
8 |
--------------------------------------------------------------------------------
/devel/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # сборка образа
5 | #
6 |
7 | cd "$(dirname "$0")"
8 |
9 | docker build --tag required/cryptopro ./../
10 |
--------------------------------------------------------------------------------
/devel/install-certs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Установка сертификатов для разработки
5 | #
6 |
7 | cd "$(dirname "$0")"
8 |
9 | echo 'Установка корневого сертификата'
10 | # curl -sS http://testca2012.cryptopro.ru/cert/rootca.cer | docker exec -i cryptopro /scripts/root
11 | curl -sS http://testca.cryptopro.ru/CertEnroll/test-ca-2014_CRYPTO-PRO%20Test%20Center%202.crt | docker exec -i cryptopro /scripts/root
12 |
13 | echo 'Установка сертификатов'
14 | cat ../certificates/bundle-cosign.zip | docker exec -i cryptopro /scripts/my 12345678
15 | cat ../certificates/bundle-Test.zip | docker exec -i cryptopro /scripts/my
16 |
--------------------------------------------------------------------------------
/devel/reflection.php:
--------------------------------------------------------------------------------
1 | showClasses();
9 | echo '# Constants' . PHP_EOL . PHP_EOL;
10 | $this->showConstants();
11 | }
12 |
13 | private function showClasses()
14 | {
15 | $classes = get_declared_classes();
16 |
17 | $classes = array_filter($classes, function($name){
18 | return preg_match('~^CP~i', $name);
19 | });
20 |
21 | foreach($classes as $class)
22 | {
23 | echo $class . PHP_EOL;
24 |
25 | $reflectionClass = new \ReflectionClass($class);
26 | $methodsList = $reflectionClass->getMethods();
27 | array_walk($methodsList, function($m){
28 | if($m->name == '__construct') return;
29 | echo " " . $m->name . '()' . PHP_EOL;
30 | });
31 |
32 | echo PHP_EOL;
33 | }
34 | }
35 |
36 | private function showConstants() {
37 | $constants = get_defined_constants(true);
38 |
39 | foreach ($constants['php_CPCSP'] as $k => $v) {
40 | echo $k . ' = ' . $v . PHP_EOL;
41 | }
42 | }
43 |
44 |
45 |
46 | }
47 |
48 | $e = new Explorer;
49 | $e->run();
50 |
--------------------------------------------------------------------------------
/devel/rest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # REST
5 | #
6 |
7 | cd "$(dirname "$0")"
8 | source ../scripts/lib/colors.sh
9 | source ../scripts/lib/functions.sh
10 |
11 | REST_URI="http://localhost:8095"
12 | FILE_TO_SIGN="../README.md"
13 |
14 | CERT_QUERY="find_type=sha1&query=82028260efc03eedc88dcb61c0f6a02e788e26e2&pin=12345678"
15 |
16 | # Неверный метод
17 | # curl -sS -X POST --data-binary "bindata" "$REST_URI/healthcheck"
18 |
19 | # подписание документа
20 | curl -sS -X POST --data-binary @- "$REST_URI/sign?$CERT_QUERY" < "$FILE_TO_SIGN" > /tmp/file.json
21 |
22 | # проверка подписи
23 | jq ".signedContent" --raw-output /tmp/file.json > /tmp/file.sig
24 |
25 | # Не подходящий формат
26 | # curl -sS -X POST --data-binary @- "$REST_URI/verify" < /tmp/file.json
27 |
28 | # корректная проверка
29 | curl -sS -X POST --data-binary @- "$REST_URI/verify" < /tmp/file.sig
30 |
31 | # исходный файл
32 | curl -sS -X POST --data-binary @- "$REST_URI/unsign" < /tmp/file.sig > /tmp/unsig.json
33 | jq ".content" --raw-output /tmp/unsig.json | base64 -d | head
34 |
35 | # добавление еще одной подписи
36 | # CERT_QUERY="find_type=subject&query=Test"
37 | # curl -sS -X POST --data-binary @- "$REST_URI/cosign?$CERT_QUERY" < /tmp/file.sig
38 |
--------------------------------------------------------------------------------
/scripts/lib/colors.sh:
--------------------------------------------------------------------------------
1 | # Библиотека цветов
2 | # Сброс
3 | Color_Off='\e[0m' # Text Reset
4 | Red='\e[1;31m' # Red
5 | Green='\e[1;32m' # Green
6 | Yellow='\e[1;33m' # Yellow
7 | Blue='\e[1;34m' # Blue
8 | Purple='\e[1;35m' # Purple
9 | Cyan='\e[1;36m' # Cyan
10 | White='\e[1;37m' # White
11 | UCyan='\e[4;36m' # Cyan
12 |
--------------------------------------------------------------------------------
/scripts/lib/functions.sh:
--------------------------------------------------------------------------------
1 | function assert
2 | {
3 | SUBSTR=`echo "$1" | grep -q "$2"`
4 | if [ $? != 0 ]; then
5 | error "$3; Expected: $2"
6 | exit 1
7 | fi
8 | }
9 |
10 | function info
11 | {
12 | echo -e $Blue"$1"$Color_Off
13 | }
14 |
15 | function ok
16 | {
17 | echo -e $Green"$1"$Color_Off
18 | }
19 |
20 | function warning
21 | {
22 | echo -e $Yellow"$1"$Color_Off
23 | }
24 |
25 | function error
26 | {
27 | echo -e $Red"$1"$Color_Off
28 | }
29 |
--------------------------------------------------------------------------------
/scripts/lib/root.exp:
--------------------------------------------------------------------------------
1 | #!/usr/bin/expect
2 |
3 | set file [lindex $argv 0]
4 |
5 | spawn certmgr -inst -all -store uroot -file $file
6 |
7 | # Иногда "заедает" на '(o)OK, (c)Cancel', пауза должна решить проблему
8 | sleep 1
9 |
10 | while { 1 } {
11 |
12 | expect {
13 | "(o)OK, (c)Cancel" {
14 | send -- "o\r"
15 | sleep 1
16 | }
17 | eof { exit 0 }
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/scripts/my:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Установка сертификатов пользователя для проверки и подписания
5 | #
6 |
7 | cd "$(dirname "$0")"
8 | source lib/colors.sh
9 | source lib/functions.sh
10 |
11 | dir=`mktemp -d`
12 | cd "$dir"
13 | cat - > "bundle.zip"
14 | unzip -q bundle.zip
15 | rm bundle.zip
16 |
17 | # info "Temp dir: $dir"
18 |
19 | # проверка всех необходимых файлов в закрытом ключе
20 | function testprivk {
21 | [ ! -f "$contShortName/header.key" ] && error "File header.key not found in $contShortName" && exit 1
22 | [ ! -f "$contShortName/masks.key" ] && error "File masks.key not found in $contShortName" && exit 1
23 | [ ! -f "$contShortName/masks2.key" ] && error "File masks2.key not found in $contShortName" && exit 1
24 | [ ! -f "$contShortName/name.key" ] && error "File name.key not found in $contShortName" && exit 1
25 | [ ! -f "$contShortName/primary.key" ] && error "File primary.key not found in $contShortName" && exit 1
26 | [ ! -f "$contShortName/primary2.key" ] && error "File primary2.key not found in $contShortName" && exit 1
27 | }
28 |
29 | # для связки закрытого ключа с сертификатом необходимо указать полное наименование контейнера, которое находится в name.key
30 | # таким способо также можно выяснить название, но с cp1251 работает не устойчиво
31 | # function findContFullName {
32 | # contFullName=`csptest -keyset -enum_cont -verifycontext -unique | grep --fixed-strings "$contShortName" | cut -d '|' -f1`
33 | # if [ ! -n "$contFullName" ]; then
34 | # error "Proper container not found by short name: $contShortName"
35 | # exit 1
36 | # fi
37 | # }
38 |
39 | # xargs удаляет `./` из названия файла
40 | certFileName=`find -maxdepth 1 -type f \! -name . | head -n1 | xargs -I{} basename {}`
41 | contShortName=`find -maxdepth 1 -type d \! -name . | head -n1 | xargs -I{} basename {}`
42 | contFullName=`tail -c+5 "$contShortName/name.key"`
43 |
44 | # Есть контейнер, устанавливаем
45 | if [ -n "$contShortName" ]; then
46 | info "Key container short name: $contShortName"
47 | testprivk
48 | cp -R "$contShortName" /var/opt/cprocsp/keys/root/
49 | if [ "$?" -eq "0" ]; then
50 | ok "Key container installed"
51 | fi
52 | fi
53 |
54 | # Есть сертификат
55 | if [ -n "$certFileName" ]; then
56 |
57 | if [ ! -n "$contShortName" ]; then
58 | # устанавливается только сертификат
59 | certmgr -inst -file "$certFileName"
60 |
61 | if [ "$?" -eq "0" ]; then
62 | ok "Certificate installed"
63 | warning "No PrivateKey Link"
64 | fi
65 |
66 | else
67 |
68 | # устанавливается сертификат + контейнер, нужно их связать ('PrivateKey Link')
69 |
70 | info "Key container full name: $contFullName" | iconv -fcp1251 -tutf-8
71 |
72 | if [ -z "$1" ]; then
73 | # нет PIN
74 | certmgr -inst -file "$certFileName" -cont '\\.\HDIMAGE\'"$contFullName"
75 | else
76 | # есть PIN
77 | certmgr -inst -file "$certFileName" -pin "$1" -cont '\\.\HDIMAGE\'"$contFullName"
78 | fi
79 |
80 | if [ "$?" -eq "0" ]; then
81 | ok "Certificate installed with PrivateKey Link"
82 | fi
83 |
84 | fi
85 |
86 |
87 | fi
88 |
89 | rm -rf "$dir"
90 |
91 | # certmgr -list
92 |
--------------------------------------------------------------------------------
/scripts/root:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Установка корневых сертификатов
5 | #
6 |
7 | cd "$(dirname "$0")"
8 |
9 | file=`mktemp`
10 | cat - > "$file"
11 |
12 | ./lib/root.exp "$file"
13 | rm -f "$file"
14 |
--------------------------------------------------------------------------------
/scripts/sign:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Подписание документа
5 | #
6 |
7 | tmp=`mktemp`
8 | cat - > "$tmp"
9 | cryptcp -sign -thumbprint "$1" -nochain -pin "$2" "$tmp" "$tmp.sig" > /dev/null 2>&1
10 | signResult=$?
11 | if [ "$signResult" != "0" ]; then
12 | rm -f "$tmp" "$tmp.sig"
13 | exit $signResult
14 | fi
15 | cat "$tmp.sig"
16 | rm -f "$tmp" "$tmp.sig"
17 |
--------------------------------------------------------------------------------
/scripts/unsign:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Получение исходного файла из sig-файла
5 | #
6 |
7 | tmp=`mktemp`
8 | cat - > "$tmp"
9 | cryptcp -verify -nochain "$tmp" "$tmp.origin" > /dev/null 2>&1
10 | signResult=$?
11 | if [ "$signResult" != "0" ]; then
12 | rm -f "$tmp" "$tmp.origin"
13 | exit $signResult
14 | fi
15 | cat "$tmp.origin"
16 | rm -f "$tmp" "$tmp.origin"
17 |
--------------------------------------------------------------------------------
/scripts/verify:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Проверка подписи
5 | #
6 |
7 | tmp=`mktemp`
8 | cat - > "$tmp"
9 | cryptcp -verify -norev -f "$tmp" "$tmp"
10 | signResult=$?
11 | rm -f "$tmp"
12 | if [ "$signResult" != "0" ]; then
13 | exit $signResult
14 | fi
15 |
--------------------------------------------------------------------------------
/www/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | /logs/*
3 | !/logs/README.md
4 |
--------------------------------------------------------------------------------
/www/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | ## Pull Requests
4 |
5 | 1. Fork the Slim Skeleton repository
6 | 2. Create a new branch for each feature or improvement
7 | 3. Send a pull request from each feature branch to the **3.x** branch
8 |
9 | It is very important to separate new features or improvements into separate feature branches, and to send a
10 | pull request for each branch. This allows us to review and pull in new features or improvements individually.
11 |
12 | ## Style Guide
13 |
14 | All pull requests must adhere to the [PSR-2 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md).
15 |
--------------------------------------------------------------------------------
/www/README.md:
--------------------------------------------------------------------------------
1 | # Slim Framework 3 Skeleton Application
2 |
3 | Use this skeleton application to quickly setup and start working on a new Slim Framework 3 application. This application uses the latest Slim 3 with the PHP-View template renderer. It also uses the Monolog logger.
4 |
5 | This skeleton application was built for Composer. This makes setting up a new Slim Framework application quick and easy.
6 |
7 | ## Install the Application
8 |
9 | Run this command from the directory in which you want to install your new Slim Framework application.
10 |
11 | php composer.phar create-project slim/slim-skeleton [my-app-name]
12 |
13 | Replace `[my-app-name]` with the desired directory name for your new application. You'll want to:
14 |
15 | * Point your virtual host document root to your new application's `public/` directory.
16 | * Ensure `logs/` is web writeable.
17 |
18 | To run the application in development, you can run these commands
19 |
20 | cd [my-app-name]
21 | php composer.phar start
22 |
23 | Run this command in the application directory to run the test suite
24 |
25 | php composer.phar test
26 |
27 | That's it! Now go build something cool.
28 |
--------------------------------------------------------------------------------
/www/app/Certificate/Finder.php:
--------------------------------------------------------------------------------
1 | CERTIFICATE_FIND_SHA1_HASH,
10 | 'subject' => CERTIFICATE_FIND_SUBJECT_NAME
11 | ];
12 |
13 | public function findType($find_type)
14 | {
15 | $this->findType =& self::$findTypeMap[$find_type];
16 | if(!isset($this->findType))
17 | {
18 | throw new \App\Exception("No such find_type", 404);
19 | }
20 | return $this;
21 | }
22 |
23 | public function query($query)
24 | {
25 | $this->query = $query;
26 | return $this;
27 | }
28 |
29 | public function fetch()
30 | {
31 | $store = new \CPStore();
32 | $store->Open(CURRENT_USER_STORE, 'My', STORE_OPEN_READ_ONLY);
33 | $this->certs = $store->get_Certificates();
34 | if($this->certs->Count() === 0)
35 | {
36 | throw new \App\Exception("No certificates in store 'My'", 404);
37 | }
38 |
39 | if(isset($this->findType))
40 | {
41 | // 3 парамет - $valid_only
42 | $this->certs = $this->certs->Find($this->findType, $this->query, false);
43 | }
44 |
45 | return $this;
46 | }
47 |
48 | public function count() {
49 | return $this->certs->Count();
50 | }
51 |
52 | public function get()
53 | {
54 | return $this->certs;
55 | }
56 |
57 | public function first()
58 | {
59 | return $this->certs->Item(1);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/www/app/Certificate/Info.php:
--------------------------------------------------------------------------------
1 | CAPICOM_CERT_INFO_*_EMAIL_NAME и CAPICOM_CERT_INFO_*_UPN и CAPICOM_CERT_INFO_*_DNS_NAME не поддерживаются криптопровайдером на Unix платформах.
10 | > Если email в RDN то можно получить всю строку с subject и достать email оттуда.
11 |
12 | @see https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=72528#post72528
13 |
14 | */
15 |
16 | class Info {
17 |
18 | public function __construct(\CPCertificate $cert)
19 | {
20 | $this->cert = $cert;
21 | }
22 |
23 | public function get()
24 | {
25 | $ret = [
26 | 'hasPrivateKey' => $this->cert->HasPrivateKey(),
27 | 'serialNumber' => $this->cert->get_SerialNumber(),
28 | 'thumbprint' => $this->cert->get_Thumbprint(),
29 | 'subject' => $this->parseMeta($this->cert->get_SubjectName()),
30 | 'issuer' => $this->parseMeta($this->cert->get_IssuerName()),
31 | 'valid' => [
32 | 'from' => $this->cert->get_ValidFromDate(),
33 | 'to' => $this->cert->get_ValidToDate(),
34 | ]
35 | ];
36 |
37 | try {
38 | $algo = $this->cert->PublicKey()->get_Algorithm();
39 | $ret['algorithm'] = [
40 | 'val' => $algo->get_Value(),
41 | 'name' => $algo->get_FriendlyName()
42 | ];
43 | } catch (\Exception $e) { }
44 |
45 | try {
46 | $pk = $this->cert->PrivateKey();
47 | $ret['privateKey'] = [
48 | 'containerName' => $pk->get_ContainerName(),
49 | 'uniqueContainerName' => $pk->get_UniqueContainerName(),
50 | 'providerName' => $pk->get_ProviderName()
51 | ];
52 | } catch (\Exception $e) { }
53 |
54 |
55 | return $ret;
56 |
57 | }
58 |
59 | private function parseMeta($str) {
60 | $ret = [
61 | 'raw' => $str
62 | ];
63 | if(preg_match_all('~(emailAddress|E|C|L|O|CN|OU|T|SN|G)=([^,]*)~', $str . ',', $m)) {
64 | foreach($m[1] as $idx => $key) {
65 | $ret[$key] = stripslashes($m[2][$idx]);
66 | }
67 | }
68 | return $ret;
69 | }
70 |
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/www/app/Controller.php:
--------------------------------------------------------------------------------
1 | withJson(['status' => 'ok', 'php_sapi_name' => php_sapi_name()]);
14 | }
15 |
16 | public function certificates(Request $request, Response $response, array $args)
17 | {
18 | $CertFinder = new Certificate\Finder;
19 | $certificates = $CertFinder->
20 | fetch()->
21 | get();
22 | $data = [
23 | 'status' => 'ok',
24 | 'certificates' => $this->getCertsInfo($certificates)
25 | ];
26 |
27 | return $response->withJson($data);
28 | }
29 |
30 | public function unsign(Request $request, Response $response, array $args)
31 | {
32 | $this->getFile($request);
33 | $this->checkEmptyFile();
34 |
35 | $sd = new \CPSignedData;
36 | $sd->set_ContentEncoding(ENCODE_BINARY);
37 | $sd->set_Content($this->content);
38 | // одновременно "расшифровывает"
39 | $sd->VerifyCades($this->content, CADES_BES, false);
40 |
41 | $data = [
42 | 'status' => 'ok',
43 | 'content' => $sd->get_Content()
44 | ];
45 |
46 | return $response->withJson($data);
47 | }
48 |
49 | public function sign(Request $request, Response $response, array $args)
50 | {
51 | $this->getFile($request);
52 | $this->checkEmptyFile();
53 | $cert = $this->getCertByQuery($request);
54 |
55 | $signer = new \CPSigner();
56 | // $signer->set_TSAAddress($address); // Опционально?
57 | $signer->set_Certificate($cert);
58 | $pin = $request->getQueryParams()['pin'];
59 | if(strlen($pin))
60 | {
61 | $signer->set_KeyPin($pin);
62 | }
63 |
64 | $sd = new \CPSignedData;
65 | $sd->set_ContentEncoding(ENCODE_BINARY);
66 | $sd->set_Content(base64_encode($this->content));
67 |
68 | // Второй параметр - тип подписи(1 = CADES_BES): http://cpdn.cryptopro.ru/default.asp?url=content/cades/namespace_c_ad_e_s_c_o_m_fe49883d8ff77f7edbeeaf0be3d44c0b_1fe49883d8ff77f7edbeeaf0be3d44c0b.html
69 | // Третий параметр detached - отделенная(true) или совмещенная (false)
70 | $this->signedContent = $sd->SignCades($signer, CADES_BES, false, 0);
71 |
72 | $data = [
73 | 'status' => 'ok',
74 | 'signedContent' => $this->signedContent
75 | ];
76 |
77 | try {
78 | $CertInfo = new Certificate\Info($cert);
79 | $data['cert'] = $CertInfo->get();
80 | } catch (\Exception $e) { }
81 |
82 | return $response->withJson($data);
83 | }
84 |
85 | public function verify(Request $request, Response $response, array $args)
86 | {
87 | $this->getFile($request);
88 | $this->checkEmptyFile();
89 |
90 | $sd = new \CPSignedData;
91 | $sd->set_ContentEncoding(BASE64_TO_BINARY);
92 | $sd->set_Content($this->content);
93 | // Бросает исключение
94 | $sd->VerifyCades($this->content, CADES_BES, false);
95 |
96 | $data = [
97 | 'status' => 'ok'
98 | ];
99 |
100 | $signers = $sd->get_Signers();
101 | $data['signers'] = $this->getSignersInfo($signers);
102 |
103 | // Возможно получить все сертификаты, в том числе просто приложенные
104 | // $certificates = $sd->get_Certificates();
105 | // $data['certificates'] = $this->getCertsInfo($certificates);
106 |
107 | return $response->withJson($data);
108 | }
109 |
110 | ///////////////////////////////////////// PRIVATE
111 |
112 | private function getFile($request)
113 | {
114 | $this->content = $request->getBody()->getContents();
115 | }
116 |
117 | private function checkEmptyFile()
118 | {
119 | if(strlen($this->content) === 0)
120 | {
121 | throw new \App\Exception("Empty file", 449);
122 | }
123 | }
124 |
125 | private function getCertByQuery(Request $request)
126 | {
127 | $CertFinder = new Certificate\Finder;
128 | $cert = $CertFinder->
129 | findType($request->getQueryParams()['find_type'])->
130 | query($request->getQueryParams()['query'])->
131 | fetch()->
132 | first();
133 | return $cert;
134 | }
135 |
136 | private function getCertsInfo(\CPCertificates $certificates)
137 | {
138 | $ret = [];
139 | for($i = 1; $i <= $certificates->Count(); $i++)
140 | {
141 | $cert = $certificates->Item($i);
142 | $CertInfo = new Certificate\Info($cert);
143 | $ret[] = $CertInfo->get();
144 | }
145 | return $ret;
146 | }
147 |
148 | private function getSignersInfo(\CPSigners $signers)
149 | {
150 | $ret = [];
151 | for($i = 1; $i <= $signers->get_Count(); $i++)
152 | {
153 | $cert = $signers->get_Item($i)->get_Certificate();
154 | $CertInfo = new Certificate\Info($cert);
155 | $ret[] = $CertInfo->get();
156 | }
157 | return $ret;
158 | }
159 |
160 |
161 |
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/www/app/Exception.php:
--------------------------------------------------------------------------------
1 | =5.5.0",
16 | "slim/slim": "^3.1",
17 | "slim/php-view": "^2.0",
18 | "monolog/monolog": "^1.17"
19 | },
20 | "require-dev": {
21 | "phpunit/phpunit": ">=4.8 < 6.0"
22 | },
23 | "autoload-dev": {
24 | "psr-4": {
25 | "Tests\\": "tests/",
26 | "App\\": "app/"
27 | }
28 | },
29 | "config": {
30 | "process-timeout" : 0
31 | },
32 | "scripts": {
33 | "start": "php -S localhost:8080 -t public",
34 | "test": "phpunit"
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/www/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "5e16cb7781829836a704bd8767830833",
8 | "packages": [
9 | {
10 | "name": "container-interop/container-interop",
11 | "version": "1.2.0",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/container-interop/container-interop.git",
15 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
20 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "psr/container": "^1.0"
25 | },
26 | "type": "library",
27 | "autoload": {
28 | "psr-4": {
29 | "Interop\\Container\\": "src/Interop/Container/"
30 | }
31 | },
32 | "notification-url": "https://packagist.org/downloads/",
33 | "license": [
34 | "MIT"
35 | ],
36 | "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
37 | "homepage": "https://github.com/container-interop/container-interop",
38 | "time": "2017-02-14T19:40:03+00:00"
39 | },
40 | {
41 | "name": "monolog/monolog",
42 | "version": "1.24.0",
43 | "source": {
44 | "type": "git",
45 | "url": "https://github.com/Seldaek/monolog.git",
46 | "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266"
47 | },
48 | "dist": {
49 | "type": "zip",
50 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
51 | "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
52 | "shasum": ""
53 | },
54 | "require": {
55 | "php": ">=5.3.0",
56 | "psr/log": "~1.0"
57 | },
58 | "provide": {
59 | "psr/log-implementation": "1.0.0"
60 | },
61 | "require-dev": {
62 | "aws/aws-sdk-php": "^2.4.9 || ^3.0",
63 | "doctrine/couchdb": "~1.0@dev",
64 | "graylog2/gelf-php": "~1.0",
65 | "jakub-onderka/php-parallel-lint": "0.9",
66 | "php-amqplib/php-amqplib": "~2.4",
67 | "php-console/php-console": "^3.1.3",
68 | "phpunit/phpunit": "~4.5",
69 | "phpunit/phpunit-mock-objects": "2.3.0",
70 | "ruflin/elastica": ">=0.90 <3.0",
71 | "sentry/sentry": "^0.13",
72 | "swiftmailer/swiftmailer": "^5.3|^6.0"
73 | },
74 | "suggest": {
75 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
76 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
77 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
78 | "ext-mongo": "Allow sending log messages to a MongoDB server",
79 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
80 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
81 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
82 | "php-console/php-console": "Allow sending log messages to Google Chrome",
83 | "rollbar/rollbar": "Allow sending log messages to Rollbar",
84 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
85 | "sentry/sentry": "Allow sending log messages to a Sentry server"
86 | },
87 | "type": "library",
88 | "extra": {
89 | "branch-alias": {
90 | "dev-master": "2.0.x-dev"
91 | }
92 | },
93 | "autoload": {
94 | "psr-4": {
95 | "Monolog\\": "src/Monolog"
96 | }
97 | },
98 | "notification-url": "https://packagist.org/downloads/",
99 | "license": [
100 | "MIT"
101 | ],
102 | "authors": [
103 | {
104 | "name": "Jordi Boggiano",
105 | "email": "j.boggiano@seld.be",
106 | "homepage": "http://seld.be"
107 | }
108 | ],
109 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
110 | "homepage": "http://github.com/Seldaek/monolog",
111 | "keywords": [
112 | "log",
113 | "logging",
114 | "psr-3"
115 | ],
116 | "time": "2018-11-05T09:00:11+00:00"
117 | },
118 | {
119 | "name": "nikic/fast-route",
120 | "version": "v1.3.0",
121 | "source": {
122 | "type": "git",
123 | "url": "https://github.com/nikic/FastRoute.git",
124 | "reference": "181d480e08d9476e61381e04a71b34dc0432e812"
125 | },
126 | "dist": {
127 | "type": "zip",
128 | "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812",
129 | "reference": "181d480e08d9476e61381e04a71b34dc0432e812",
130 | "shasum": ""
131 | },
132 | "require": {
133 | "php": ">=5.4.0"
134 | },
135 | "require-dev": {
136 | "phpunit/phpunit": "^4.8.35|~5.7"
137 | },
138 | "type": "library",
139 | "autoload": {
140 | "psr-4": {
141 | "FastRoute\\": "src/"
142 | },
143 | "files": [
144 | "src/functions.php"
145 | ]
146 | },
147 | "notification-url": "https://packagist.org/downloads/",
148 | "license": [
149 | "BSD-3-Clause"
150 | ],
151 | "authors": [
152 | {
153 | "name": "Nikita Popov",
154 | "email": "nikic@php.net"
155 | }
156 | ],
157 | "description": "Fast request router for PHP",
158 | "keywords": [
159 | "router",
160 | "routing"
161 | ],
162 | "time": "2018-02-13T20:26:39+00:00"
163 | },
164 | {
165 | "name": "pimple/pimple",
166 | "version": "v3.2.3",
167 | "source": {
168 | "type": "git",
169 | "url": "https://github.com/silexphp/Pimple.git",
170 | "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32"
171 | },
172 | "dist": {
173 | "type": "zip",
174 | "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32",
175 | "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32",
176 | "shasum": ""
177 | },
178 | "require": {
179 | "php": ">=5.3.0",
180 | "psr/container": "^1.0"
181 | },
182 | "require-dev": {
183 | "symfony/phpunit-bridge": "^3.2"
184 | },
185 | "type": "library",
186 | "extra": {
187 | "branch-alias": {
188 | "dev-master": "3.2.x-dev"
189 | }
190 | },
191 | "autoload": {
192 | "psr-0": {
193 | "Pimple": "src/"
194 | }
195 | },
196 | "notification-url": "https://packagist.org/downloads/",
197 | "license": [
198 | "MIT"
199 | ],
200 | "authors": [
201 | {
202 | "name": "Fabien Potencier",
203 | "email": "fabien@symfony.com"
204 | }
205 | ],
206 | "description": "Pimple, a simple Dependency Injection Container",
207 | "homepage": "http://pimple.sensiolabs.org",
208 | "keywords": [
209 | "container",
210 | "dependency injection"
211 | ],
212 | "time": "2018-01-21T07:42:36+00:00"
213 | },
214 | {
215 | "name": "psr/container",
216 | "version": "1.0.0",
217 | "source": {
218 | "type": "git",
219 | "url": "https://github.com/php-fig/container.git",
220 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
221 | },
222 | "dist": {
223 | "type": "zip",
224 | "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
225 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
226 | "shasum": ""
227 | },
228 | "require": {
229 | "php": ">=5.3.0"
230 | },
231 | "type": "library",
232 | "extra": {
233 | "branch-alias": {
234 | "dev-master": "1.0.x-dev"
235 | }
236 | },
237 | "autoload": {
238 | "psr-4": {
239 | "Psr\\Container\\": "src/"
240 | }
241 | },
242 | "notification-url": "https://packagist.org/downloads/",
243 | "license": [
244 | "MIT"
245 | ],
246 | "authors": [
247 | {
248 | "name": "PHP-FIG",
249 | "homepage": "http://www.php-fig.org/"
250 | }
251 | ],
252 | "description": "Common Container Interface (PHP FIG PSR-11)",
253 | "homepage": "https://github.com/php-fig/container",
254 | "keywords": [
255 | "PSR-11",
256 | "container",
257 | "container-interface",
258 | "container-interop",
259 | "psr"
260 | ],
261 | "time": "2017-02-14T16:28:37+00:00"
262 | },
263 | {
264 | "name": "psr/http-message",
265 | "version": "1.0.1",
266 | "source": {
267 | "type": "git",
268 | "url": "https://github.com/php-fig/http-message.git",
269 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
270 | },
271 | "dist": {
272 | "type": "zip",
273 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
274 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
275 | "shasum": ""
276 | },
277 | "require": {
278 | "php": ">=5.3.0"
279 | },
280 | "type": "library",
281 | "extra": {
282 | "branch-alias": {
283 | "dev-master": "1.0.x-dev"
284 | }
285 | },
286 | "autoload": {
287 | "psr-4": {
288 | "Psr\\Http\\Message\\": "src/"
289 | }
290 | },
291 | "notification-url": "https://packagist.org/downloads/",
292 | "license": [
293 | "MIT"
294 | ],
295 | "authors": [
296 | {
297 | "name": "PHP-FIG",
298 | "homepage": "http://www.php-fig.org/"
299 | }
300 | ],
301 | "description": "Common interface for HTTP messages",
302 | "homepage": "https://github.com/php-fig/http-message",
303 | "keywords": [
304 | "http",
305 | "http-message",
306 | "psr",
307 | "psr-7",
308 | "request",
309 | "response"
310 | ],
311 | "time": "2016-08-06T14:39:51+00:00"
312 | },
313 | {
314 | "name": "psr/log",
315 | "version": "1.1.0",
316 | "source": {
317 | "type": "git",
318 | "url": "https://github.com/php-fig/log.git",
319 | "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
320 | },
321 | "dist": {
322 | "type": "zip",
323 | "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
324 | "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
325 | "shasum": ""
326 | },
327 | "require": {
328 | "php": ">=5.3.0"
329 | },
330 | "type": "library",
331 | "extra": {
332 | "branch-alias": {
333 | "dev-master": "1.0.x-dev"
334 | }
335 | },
336 | "autoload": {
337 | "psr-4": {
338 | "Psr\\Log\\": "Psr/Log/"
339 | }
340 | },
341 | "notification-url": "https://packagist.org/downloads/",
342 | "license": [
343 | "MIT"
344 | ],
345 | "authors": [
346 | {
347 | "name": "PHP-FIG",
348 | "homepage": "http://www.php-fig.org/"
349 | }
350 | ],
351 | "description": "Common interface for logging libraries",
352 | "homepage": "https://github.com/php-fig/log",
353 | "keywords": [
354 | "log",
355 | "psr",
356 | "psr-3"
357 | ],
358 | "time": "2018-11-20T15:27:04+00:00"
359 | },
360 | {
361 | "name": "slim/php-view",
362 | "version": "2.2.0",
363 | "source": {
364 | "type": "git",
365 | "url": "https://github.com/slimphp/PHP-View.git",
366 | "reference": "122ed121a8d9cf91a94020814d2a3ee6c836754f"
367 | },
368 | "dist": {
369 | "type": "zip",
370 | "url": "https://api.github.com/repos/slimphp/PHP-View/zipball/122ed121a8d9cf91a94020814d2a3ee6c836754f",
371 | "reference": "122ed121a8d9cf91a94020814d2a3ee6c836754f",
372 | "shasum": ""
373 | },
374 | "require": {
375 | "psr/http-message": "^1.0"
376 | },
377 | "require-dev": {
378 | "phpunit/phpunit": "^4.8",
379 | "slim/slim": "^3.0"
380 | },
381 | "type": "library",
382 | "autoload": {
383 | "psr-4": {
384 | "Slim\\Views\\": "src"
385 | }
386 | },
387 | "notification-url": "https://packagist.org/downloads/",
388 | "license": [
389 | "MIT"
390 | ],
391 | "authors": [
392 | {
393 | "name": "Glenn Eggleton",
394 | "email": "geggleto@gmail.com"
395 | }
396 | ],
397 | "description": "Render PHP view scripts into a PSR-7 Response object.",
398 | "keywords": [
399 | "framework",
400 | "php",
401 | "phtml",
402 | "renderer",
403 | "slim",
404 | "template",
405 | "view"
406 | ],
407 | "time": "2016-10-11T07:43:08+00:00"
408 | },
409 | {
410 | "name": "slim/slim",
411 | "version": "3.12.0",
412 | "source": {
413 | "type": "git",
414 | "url": "https://github.com/slimphp/Slim.git",
415 | "reference": "f4947cc900b6e51cbfda58b9f1247bca2f76f9f0"
416 | },
417 | "dist": {
418 | "type": "zip",
419 | "url": "https://api.github.com/repos/slimphp/Slim/zipball/f4947cc900b6e51cbfda58b9f1247bca2f76f9f0",
420 | "reference": "f4947cc900b6e51cbfda58b9f1247bca2f76f9f0",
421 | "shasum": ""
422 | },
423 | "require": {
424 | "container-interop/container-interop": "^1.2",
425 | "nikic/fast-route": "^1.0",
426 | "php": ">=5.5.0",
427 | "pimple/pimple": "^3.0",
428 | "psr/container": "^1.0",
429 | "psr/http-message": "^1.0"
430 | },
431 | "provide": {
432 | "psr/http-message-implementation": "1.0"
433 | },
434 | "require-dev": {
435 | "phpunit/phpunit": "^4.0",
436 | "squizlabs/php_codesniffer": "^2.5"
437 | },
438 | "type": "library",
439 | "autoload": {
440 | "psr-4": {
441 | "Slim\\": "Slim"
442 | }
443 | },
444 | "notification-url": "https://packagist.org/downloads/",
445 | "license": [
446 | "MIT"
447 | ],
448 | "authors": [
449 | {
450 | "name": "Rob Allen",
451 | "email": "rob@akrabat.com",
452 | "homepage": "http://akrabat.com"
453 | },
454 | {
455 | "name": "Josh Lockhart",
456 | "email": "hello@joshlockhart.com",
457 | "homepage": "https://joshlockhart.com"
458 | },
459 | {
460 | "name": "Gabriel Manricks",
461 | "email": "gmanricks@me.com",
462 | "homepage": "http://gabrielmanricks.com"
463 | },
464 | {
465 | "name": "Andrew Smith",
466 | "email": "a.smith@silentworks.co.uk",
467 | "homepage": "http://silentworks.co.uk"
468 | }
469 | ],
470 | "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
471 | "homepage": "https://slimframework.com",
472 | "keywords": [
473 | "api",
474 | "framework",
475 | "micro",
476 | "router"
477 | ],
478 | "time": "2019-01-15T13:21:25+00:00"
479 | }
480 | ],
481 | "packages-dev": [
482 | {
483 | "name": "doctrine/instantiator",
484 | "version": "1.1.0",
485 | "source": {
486 | "type": "git",
487 | "url": "https://github.com/doctrine/instantiator.git",
488 | "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda"
489 | },
490 | "dist": {
491 | "type": "zip",
492 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
493 | "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
494 | "shasum": ""
495 | },
496 | "require": {
497 | "php": "^7.1"
498 | },
499 | "require-dev": {
500 | "athletic/athletic": "~0.1.8",
501 | "ext-pdo": "*",
502 | "ext-phar": "*",
503 | "phpunit/phpunit": "^6.2.3",
504 | "squizlabs/php_codesniffer": "^3.0.2"
505 | },
506 | "type": "library",
507 | "extra": {
508 | "branch-alias": {
509 | "dev-master": "1.2.x-dev"
510 | }
511 | },
512 | "autoload": {
513 | "psr-4": {
514 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
515 | }
516 | },
517 | "notification-url": "https://packagist.org/downloads/",
518 | "license": [
519 | "MIT"
520 | ],
521 | "authors": [
522 | {
523 | "name": "Marco Pivetta",
524 | "email": "ocramius@gmail.com",
525 | "homepage": "http://ocramius.github.com/"
526 | }
527 | ],
528 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
529 | "homepage": "https://github.com/doctrine/instantiator",
530 | "keywords": [
531 | "constructor",
532 | "instantiate"
533 | ],
534 | "time": "2017-07-22T11:58:36+00:00"
535 | },
536 | {
537 | "name": "myclabs/deep-copy",
538 | "version": "1.8.1",
539 | "source": {
540 | "type": "git",
541 | "url": "https://github.com/myclabs/DeepCopy.git",
542 | "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8"
543 | },
544 | "dist": {
545 | "type": "zip",
546 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
547 | "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
548 | "shasum": ""
549 | },
550 | "require": {
551 | "php": "^7.1"
552 | },
553 | "replace": {
554 | "myclabs/deep-copy": "self.version"
555 | },
556 | "require-dev": {
557 | "doctrine/collections": "^1.0",
558 | "doctrine/common": "^2.6",
559 | "phpunit/phpunit": "^7.1"
560 | },
561 | "type": "library",
562 | "autoload": {
563 | "psr-4": {
564 | "DeepCopy\\": "src/DeepCopy/"
565 | },
566 | "files": [
567 | "src/DeepCopy/deep_copy.php"
568 | ]
569 | },
570 | "notification-url": "https://packagist.org/downloads/",
571 | "license": [
572 | "MIT"
573 | ],
574 | "description": "Create deep copies (clones) of your objects",
575 | "keywords": [
576 | "clone",
577 | "copy",
578 | "duplicate",
579 | "object",
580 | "object graph"
581 | ],
582 | "time": "2018-06-11T23:09:50+00:00"
583 | },
584 | {
585 | "name": "phpdocumentor/reflection-common",
586 | "version": "1.0.1",
587 | "source": {
588 | "type": "git",
589 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
590 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
591 | },
592 | "dist": {
593 | "type": "zip",
594 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
595 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
596 | "shasum": ""
597 | },
598 | "require": {
599 | "php": ">=5.5"
600 | },
601 | "require-dev": {
602 | "phpunit/phpunit": "^4.6"
603 | },
604 | "type": "library",
605 | "extra": {
606 | "branch-alias": {
607 | "dev-master": "1.0.x-dev"
608 | }
609 | },
610 | "autoload": {
611 | "psr-4": {
612 | "phpDocumentor\\Reflection\\": [
613 | "src"
614 | ]
615 | }
616 | },
617 | "notification-url": "https://packagist.org/downloads/",
618 | "license": [
619 | "MIT"
620 | ],
621 | "authors": [
622 | {
623 | "name": "Jaap van Otterdijk",
624 | "email": "opensource@ijaap.nl"
625 | }
626 | ],
627 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
628 | "homepage": "http://www.phpdoc.org",
629 | "keywords": [
630 | "FQSEN",
631 | "phpDocumentor",
632 | "phpdoc",
633 | "reflection",
634 | "static analysis"
635 | ],
636 | "time": "2017-09-11T18:02:19+00:00"
637 | },
638 | {
639 | "name": "phpdocumentor/reflection-docblock",
640 | "version": "4.3.0",
641 | "source": {
642 | "type": "git",
643 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
644 | "reference": "94fd0001232e47129dd3504189fa1c7225010d08"
645 | },
646 | "dist": {
647 | "type": "zip",
648 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08",
649 | "reference": "94fd0001232e47129dd3504189fa1c7225010d08",
650 | "shasum": ""
651 | },
652 | "require": {
653 | "php": "^7.0",
654 | "phpdocumentor/reflection-common": "^1.0.0",
655 | "phpdocumentor/type-resolver": "^0.4.0",
656 | "webmozart/assert": "^1.0"
657 | },
658 | "require-dev": {
659 | "doctrine/instantiator": "~1.0.5",
660 | "mockery/mockery": "^1.0",
661 | "phpunit/phpunit": "^6.4"
662 | },
663 | "type": "library",
664 | "extra": {
665 | "branch-alias": {
666 | "dev-master": "4.x-dev"
667 | }
668 | },
669 | "autoload": {
670 | "psr-4": {
671 | "phpDocumentor\\Reflection\\": [
672 | "src/"
673 | ]
674 | }
675 | },
676 | "notification-url": "https://packagist.org/downloads/",
677 | "license": [
678 | "MIT"
679 | ],
680 | "authors": [
681 | {
682 | "name": "Mike van Riel",
683 | "email": "me@mikevanriel.com"
684 | }
685 | ],
686 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
687 | "time": "2017-11-30T07:14:17+00:00"
688 | },
689 | {
690 | "name": "phpdocumentor/type-resolver",
691 | "version": "0.4.0",
692 | "source": {
693 | "type": "git",
694 | "url": "https://github.com/phpDocumentor/TypeResolver.git",
695 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
696 | },
697 | "dist": {
698 | "type": "zip",
699 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
700 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
701 | "shasum": ""
702 | },
703 | "require": {
704 | "php": "^5.5 || ^7.0",
705 | "phpdocumentor/reflection-common": "^1.0"
706 | },
707 | "require-dev": {
708 | "mockery/mockery": "^0.9.4",
709 | "phpunit/phpunit": "^5.2||^4.8.24"
710 | },
711 | "type": "library",
712 | "extra": {
713 | "branch-alias": {
714 | "dev-master": "1.0.x-dev"
715 | }
716 | },
717 | "autoload": {
718 | "psr-4": {
719 | "phpDocumentor\\Reflection\\": [
720 | "src/"
721 | ]
722 | }
723 | },
724 | "notification-url": "https://packagist.org/downloads/",
725 | "license": [
726 | "MIT"
727 | ],
728 | "authors": [
729 | {
730 | "name": "Mike van Riel",
731 | "email": "me@mikevanriel.com"
732 | }
733 | ],
734 | "time": "2017-07-14T14:27:02+00:00"
735 | },
736 | {
737 | "name": "phpspec/prophecy",
738 | "version": "1.8.0",
739 | "source": {
740 | "type": "git",
741 | "url": "https://github.com/phpspec/prophecy.git",
742 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06"
743 | },
744 | "dist": {
745 | "type": "zip",
746 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
747 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
748 | "shasum": ""
749 | },
750 | "require": {
751 | "doctrine/instantiator": "^1.0.2",
752 | "php": "^5.3|^7.0",
753 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
754 | "sebastian/comparator": "^1.1|^2.0|^3.0",
755 | "sebastian/recursion-context": "^1.0|^2.0|^3.0"
756 | },
757 | "require-dev": {
758 | "phpspec/phpspec": "^2.5|^3.2",
759 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
760 | },
761 | "type": "library",
762 | "extra": {
763 | "branch-alias": {
764 | "dev-master": "1.8.x-dev"
765 | }
766 | },
767 | "autoload": {
768 | "psr-0": {
769 | "Prophecy\\": "src/"
770 | }
771 | },
772 | "notification-url": "https://packagist.org/downloads/",
773 | "license": [
774 | "MIT"
775 | ],
776 | "authors": [
777 | {
778 | "name": "Konstantin Kudryashov",
779 | "email": "ever.zet@gmail.com",
780 | "homepage": "http://everzet.com"
781 | },
782 | {
783 | "name": "Marcello Duarte",
784 | "email": "marcello.duarte@gmail.com"
785 | }
786 | ],
787 | "description": "Highly opinionated mocking framework for PHP 5.3+",
788 | "homepage": "https://github.com/phpspec/prophecy",
789 | "keywords": [
790 | "Double",
791 | "Dummy",
792 | "fake",
793 | "mock",
794 | "spy",
795 | "stub"
796 | ],
797 | "time": "2018-08-05T17:53:17+00:00"
798 | },
799 | {
800 | "name": "phpunit/php-code-coverage",
801 | "version": "4.0.8",
802 | "source": {
803 | "type": "git",
804 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
805 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d"
806 | },
807 | "dist": {
808 | "type": "zip",
809 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
810 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
811 | "shasum": ""
812 | },
813 | "require": {
814 | "ext-dom": "*",
815 | "ext-xmlwriter": "*",
816 | "php": "^5.6 || ^7.0",
817 | "phpunit/php-file-iterator": "^1.3",
818 | "phpunit/php-text-template": "^1.2",
819 | "phpunit/php-token-stream": "^1.4.2 || ^2.0",
820 | "sebastian/code-unit-reverse-lookup": "^1.0",
821 | "sebastian/environment": "^1.3.2 || ^2.0",
822 | "sebastian/version": "^1.0 || ^2.0"
823 | },
824 | "require-dev": {
825 | "ext-xdebug": "^2.1.4",
826 | "phpunit/phpunit": "^5.7"
827 | },
828 | "suggest": {
829 | "ext-xdebug": "^2.5.1"
830 | },
831 | "type": "library",
832 | "extra": {
833 | "branch-alias": {
834 | "dev-master": "4.0.x-dev"
835 | }
836 | },
837 | "autoload": {
838 | "classmap": [
839 | "src/"
840 | ]
841 | },
842 | "notification-url": "https://packagist.org/downloads/",
843 | "license": [
844 | "BSD-3-Clause"
845 | ],
846 | "authors": [
847 | {
848 | "name": "Sebastian Bergmann",
849 | "email": "sb@sebastian-bergmann.de",
850 | "role": "lead"
851 | }
852 | ],
853 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
854 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
855 | "keywords": [
856 | "coverage",
857 | "testing",
858 | "xunit"
859 | ],
860 | "time": "2017-04-02T07:44:40+00:00"
861 | },
862 | {
863 | "name": "phpunit/php-file-iterator",
864 | "version": "1.4.5",
865 | "source": {
866 | "type": "git",
867 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
868 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
869 | },
870 | "dist": {
871 | "type": "zip",
872 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
873 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
874 | "shasum": ""
875 | },
876 | "require": {
877 | "php": ">=5.3.3"
878 | },
879 | "type": "library",
880 | "extra": {
881 | "branch-alias": {
882 | "dev-master": "1.4.x-dev"
883 | }
884 | },
885 | "autoload": {
886 | "classmap": [
887 | "src/"
888 | ]
889 | },
890 | "notification-url": "https://packagist.org/downloads/",
891 | "license": [
892 | "BSD-3-Clause"
893 | ],
894 | "authors": [
895 | {
896 | "name": "Sebastian Bergmann",
897 | "email": "sb@sebastian-bergmann.de",
898 | "role": "lead"
899 | }
900 | ],
901 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
902 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
903 | "keywords": [
904 | "filesystem",
905 | "iterator"
906 | ],
907 | "time": "2017-11-27T13:52:08+00:00"
908 | },
909 | {
910 | "name": "phpunit/php-text-template",
911 | "version": "1.2.1",
912 | "source": {
913 | "type": "git",
914 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
915 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
916 | },
917 | "dist": {
918 | "type": "zip",
919 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
920 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
921 | "shasum": ""
922 | },
923 | "require": {
924 | "php": ">=5.3.3"
925 | },
926 | "type": "library",
927 | "autoload": {
928 | "classmap": [
929 | "src/"
930 | ]
931 | },
932 | "notification-url": "https://packagist.org/downloads/",
933 | "license": [
934 | "BSD-3-Clause"
935 | ],
936 | "authors": [
937 | {
938 | "name": "Sebastian Bergmann",
939 | "email": "sebastian@phpunit.de",
940 | "role": "lead"
941 | }
942 | ],
943 | "description": "Simple template engine.",
944 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
945 | "keywords": [
946 | "template"
947 | ],
948 | "time": "2015-06-21T13:50:34+00:00"
949 | },
950 | {
951 | "name": "phpunit/php-timer",
952 | "version": "1.0.9",
953 | "source": {
954 | "type": "git",
955 | "url": "https://github.com/sebastianbergmann/php-timer.git",
956 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
957 | },
958 | "dist": {
959 | "type": "zip",
960 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
961 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
962 | "shasum": ""
963 | },
964 | "require": {
965 | "php": "^5.3.3 || ^7.0"
966 | },
967 | "require-dev": {
968 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
969 | },
970 | "type": "library",
971 | "extra": {
972 | "branch-alias": {
973 | "dev-master": "1.0-dev"
974 | }
975 | },
976 | "autoload": {
977 | "classmap": [
978 | "src/"
979 | ]
980 | },
981 | "notification-url": "https://packagist.org/downloads/",
982 | "license": [
983 | "BSD-3-Clause"
984 | ],
985 | "authors": [
986 | {
987 | "name": "Sebastian Bergmann",
988 | "email": "sb@sebastian-bergmann.de",
989 | "role": "lead"
990 | }
991 | ],
992 | "description": "Utility class for timing",
993 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
994 | "keywords": [
995 | "timer"
996 | ],
997 | "time": "2017-02-26T11:10:40+00:00"
998 | },
999 | {
1000 | "name": "phpunit/php-token-stream",
1001 | "version": "2.0.2",
1002 | "source": {
1003 | "type": "git",
1004 | "url": "https://github.com/sebastianbergmann/php-token-stream.git",
1005 | "reference": "791198a2c6254db10131eecfe8c06670700904db"
1006 | },
1007 | "dist": {
1008 | "type": "zip",
1009 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db",
1010 | "reference": "791198a2c6254db10131eecfe8c06670700904db",
1011 | "shasum": ""
1012 | },
1013 | "require": {
1014 | "ext-tokenizer": "*",
1015 | "php": "^7.0"
1016 | },
1017 | "require-dev": {
1018 | "phpunit/phpunit": "^6.2.4"
1019 | },
1020 | "type": "library",
1021 | "extra": {
1022 | "branch-alias": {
1023 | "dev-master": "2.0-dev"
1024 | }
1025 | },
1026 | "autoload": {
1027 | "classmap": [
1028 | "src/"
1029 | ]
1030 | },
1031 | "notification-url": "https://packagist.org/downloads/",
1032 | "license": [
1033 | "BSD-3-Clause"
1034 | ],
1035 | "authors": [
1036 | {
1037 | "name": "Sebastian Bergmann",
1038 | "email": "sebastian@phpunit.de"
1039 | }
1040 | ],
1041 | "description": "Wrapper around PHP's tokenizer extension.",
1042 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
1043 | "keywords": [
1044 | "tokenizer"
1045 | ],
1046 | "time": "2017-11-27T05:48:46+00:00"
1047 | },
1048 | {
1049 | "name": "phpunit/phpunit",
1050 | "version": "5.7.27",
1051 | "source": {
1052 | "type": "git",
1053 | "url": "https://github.com/sebastianbergmann/phpunit.git",
1054 | "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c"
1055 | },
1056 | "dist": {
1057 | "type": "zip",
1058 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c",
1059 | "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c",
1060 | "shasum": ""
1061 | },
1062 | "require": {
1063 | "ext-dom": "*",
1064 | "ext-json": "*",
1065 | "ext-libxml": "*",
1066 | "ext-mbstring": "*",
1067 | "ext-xml": "*",
1068 | "myclabs/deep-copy": "~1.3",
1069 | "php": "^5.6 || ^7.0",
1070 | "phpspec/prophecy": "^1.6.2",
1071 | "phpunit/php-code-coverage": "^4.0.4",
1072 | "phpunit/php-file-iterator": "~1.4",
1073 | "phpunit/php-text-template": "~1.2",
1074 | "phpunit/php-timer": "^1.0.6",
1075 | "phpunit/phpunit-mock-objects": "^3.2",
1076 | "sebastian/comparator": "^1.2.4",
1077 | "sebastian/diff": "^1.4.3",
1078 | "sebastian/environment": "^1.3.4 || ^2.0",
1079 | "sebastian/exporter": "~2.0",
1080 | "sebastian/global-state": "^1.1",
1081 | "sebastian/object-enumerator": "~2.0",
1082 | "sebastian/resource-operations": "~1.0",
1083 | "sebastian/version": "^1.0.6|^2.0.1",
1084 | "symfony/yaml": "~2.1|~3.0|~4.0"
1085 | },
1086 | "conflict": {
1087 | "phpdocumentor/reflection-docblock": "3.0.2"
1088 | },
1089 | "require-dev": {
1090 | "ext-pdo": "*"
1091 | },
1092 | "suggest": {
1093 | "ext-xdebug": "*",
1094 | "phpunit/php-invoker": "~1.1"
1095 | },
1096 | "bin": [
1097 | "phpunit"
1098 | ],
1099 | "type": "library",
1100 | "extra": {
1101 | "branch-alias": {
1102 | "dev-master": "5.7.x-dev"
1103 | }
1104 | },
1105 | "autoload": {
1106 | "classmap": [
1107 | "src/"
1108 | ]
1109 | },
1110 | "notification-url": "https://packagist.org/downloads/",
1111 | "license": [
1112 | "BSD-3-Clause"
1113 | ],
1114 | "authors": [
1115 | {
1116 | "name": "Sebastian Bergmann",
1117 | "email": "sebastian@phpunit.de",
1118 | "role": "lead"
1119 | }
1120 | ],
1121 | "description": "The PHP Unit Testing framework.",
1122 | "homepage": "https://phpunit.de/",
1123 | "keywords": [
1124 | "phpunit",
1125 | "testing",
1126 | "xunit"
1127 | ],
1128 | "time": "2018-02-01T05:50:59+00:00"
1129 | },
1130 | {
1131 | "name": "phpunit/phpunit-mock-objects",
1132 | "version": "3.4.4",
1133 | "source": {
1134 | "type": "git",
1135 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
1136 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118"
1137 | },
1138 | "dist": {
1139 | "type": "zip",
1140 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118",
1141 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118",
1142 | "shasum": ""
1143 | },
1144 | "require": {
1145 | "doctrine/instantiator": "^1.0.2",
1146 | "php": "^5.6 || ^7.0",
1147 | "phpunit/php-text-template": "^1.2",
1148 | "sebastian/exporter": "^1.2 || ^2.0"
1149 | },
1150 | "conflict": {
1151 | "phpunit/phpunit": "<5.4.0"
1152 | },
1153 | "require-dev": {
1154 | "phpunit/phpunit": "^5.4"
1155 | },
1156 | "suggest": {
1157 | "ext-soap": "*"
1158 | },
1159 | "type": "library",
1160 | "extra": {
1161 | "branch-alias": {
1162 | "dev-master": "3.2.x-dev"
1163 | }
1164 | },
1165 | "autoload": {
1166 | "classmap": [
1167 | "src/"
1168 | ]
1169 | },
1170 | "notification-url": "https://packagist.org/downloads/",
1171 | "license": [
1172 | "BSD-3-Clause"
1173 | ],
1174 | "authors": [
1175 | {
1176 | "name": "Sebastian Bergmann",
1177 | "email": "sb@sebastian-bergmann.de",
1178 | "role": "lead"
1179 | }
1180 | ],
1181 | "description": "Mock Object library for PHPUnit",
1182 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
1183 | "keywords": [
1184 | "mock",
1185 | "xunit"
1186 | ],
1187 | "abandoned": true,
1188 | "time": "2017-06-30T09:13:00+00:00"
1189 | },
1190 | {
1191 | "name": "sebastian/code-unit-reverse-lookup",
1192 | "version": "1.0.1",
1193 | "source": {
1194 | "type": "git",
1195 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
1196 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
1197 | },
1198 | "dist": {
1199 | "type": "zip",
1200 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
1201 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
1202 | "shasum": ""
1203 | },
1204 | "require": {
1205 | "php": "^5.6 || ^7.0"
1206 | },
1207 | "require-dev": {
1208 | "phpunit/phpunit": "^5.7 || ^6.0"
1209 | },
1210 | "type": "library",
1211 | "extra": {
1212 | "branch-alias": {
1213 | "dev-master": "1.0.x-dev"
1214 | }
1215 | },
1216 | "autoload": {
1217 | "classmap": [
1218 | "src/"
1219 | ]
1220 | },
1221 | "notification-url": "https://packagist.org/downloads/",
1222 | "license": [
1223 | "BSD-3-Clause"
1224 | ],
1225 | "authors": [
1226 | {
1227 | "name": "Sebastian Bergmann",
1228 | "email": "sebastian@phpunit.de"
1229 | }
1230 | ],
1231 | "description": "Looks up which function or method a line of code belongs to",
1232 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
1233 | "time": "2017-03-04T06:30:41+00:00"
1234 | },
1235 | {
1236 | "name": "sebastian/comparator",
1237 | "version": "1.2.4",
1238 | "source": {
1239 | "type": "git",
1240 | "url": "https://github.com/sebastianbergmann/comparator.git",
1241 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
1242 | },
1243 | "dist": {
1244 | "type": "zip",
1245 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
1246 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
1247 | "shasum": ""
1248 | },
1249 | "require": {
1250 | "php": ">=5.3.3",
1251 | "sebastian/diff": "~1.2",
1252 | "sebastian/exporter": "~1.2 || ~2.0"
1253 | },
1254 | "require-dev": {
1255 | "phpunit/phpunit": "~4.4"
1256 | },
1257 | "type": "library",
1258 | "extra": {
1259 | "branch-alias": {
1260 | "dev-master": "1.2.x-dev"
1261 | }
1262 | },
1263 | "autoload": {
1264 | "classmap": [
1265 | "src/"
1266 | ]
1267 | },
1268 | "notification-url": "https://packagist.org/downloads/",
1269 | "license": [
1270 | "BSD-3-Clause"
1271 | ],
1272 | "authors": [
1273 | {
1274 | "name": "Jeff Welch",
1275 | "email": "whatthejeff@gmail.com"
1276 | },
1277 | {
1278 | "name": "Volker Dusch",
1279 | "email": "github@wallbash.com"
1280 | },
1281 | {
1282 | "name": "Bernhard Schussek",
1283 | "email": "bschussek@2bepublished.at"
1284 | },
1285 | {
1286 | "name": "Sebastian Bergmann",
1287 | "email": "sebastian@phpunit.de"
1288 | }
1289 | ],
1290 | "description": "Provides the functionality to compare PHP values for equality",
1291 | "homepage": "http://www.github.com/sebastianbergmann/comparator",
1292 | "keywords": [
1293 | "comparator",
1294 | "compare",
1295 | "equality"
1296 | ],
1297 | "time": "2017-01-29T09:50:25+00:00"
1298 | },
1299 | {
1300 | "name": "sebastian/diff",
1301 | "version": "1.4.3",
1302 | "source": {
1303 | "type": "git",
1304 | "url": "https://github.com/sebastianbergmann/diff.git",
1305 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
1306 | },
1307 | "dist": {
1308 | "type": "zip",
1309 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
1310 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
1311 | "shasum": ""
1312 | },
1313 | "require": {
1314 | "php": "^5.3.3 || ^7.0"
1315 | },
1316 | "require-dev": {
1317 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
1318 | },
1319 | "type": "library",
1320 | "extra": {
1321 | "branch-alias": {
1322 | "dev-master": "1.4-dev"
1323 | }
1324 | },
1325 | "autoload": {
1326 | "classmap": [
1327 | "src/"
1328 | ]
1329 | },
1330 | "notification-url": "https://packagist.org/downloads/",
1331 | "license": [
1332 | "BSD-3-Clause"
1333 | ],
1334 | "authors": [
1335 | {
1336 | "name": "Kore Nordmann",
1337 | "email": "mail@kore-nordmann.de"
1338 | },
1339 | {
1340 | "name": "Sebastian Bergmann",
1341 | "email": "sebastian@phpunit.de"
1342 | }
1343 | ],
1344 | "description": "Diff implementation",
1345 | "homepage": "https://github.com/sebastianbergmann/diff",
1346 | "keywords": [
1347 | "diff"
1348 | ],
1349 | "time": "2017-05-22T07:24:03+00:00"
1350 | },
1351 | {
1352 | "name": "sebastian/environment",
1353 | "version": "2.0.0",
1354 | "source": {
1355 | "type": "git",
1356 | "url": "https://github.com/sebastianbergmann/environment.git",
1357 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac"
1358 | },
1359 | "dist": {
1360 | "type": "zip",
1361 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
1362 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
1363 | "shasum": ""
1364 | },
1365 | "require": {
1366 | "php": "^5.6 || ^7.0"
1367 | },
1368 | "require-dev": {
1369 | "phpunit/phpunit": "^5.0"
1370 | },
1371 | "type": "library",
1372 | "extra": {
1373 | "branch-alias": {
1374 | "dev-master": "2.0.x-dev"
1375 | }
1376 | },
1377 | "autoload": {
1378 | "classmap": [
1379 | "src/"
1380 | ]
1381 | },
1382 | "notification-url": "https://packagist.org/downloads/",
1383 | "license": [
1384 | "BSD-3-Clause"
1385 | ],
1386 | "authors": [
1387 | {
1388 | "name": "Sebastian Bergmann",
1389 | "email": "sebastian@phpunit.de"
1390 | }
1391 | ],
1392 | "description": "Provides functionality to handle HHVM/PHP environments",
1393 | "homepage": "http://www.github.com/sebastianbergmann/environment",
1394 | "keywords": [
1395 | "Xdebug",
1396 | "environment",
1397 | "hhvm"
1398 | ],
1399 | "time": "2016-11-26T07:53:53+00:00"
1400 | },
1401 | {
1402 | "name": "sebastian/exporter",
1403 | "version": "2.0.0",
1404 | "source": {
1405 | "type": "git",
1406 | "url": "https://github.com/sebastianbergmann/exporter.git",
1407 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4"
1408 | },
1409 | "dist": {
1410 | "type": "zip",
1411 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
1412 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
1413 | "shasum": ""
1414 | },
1415 | "require": {
1416 | "php": ">=5.3.3",
1417 | "sebastian/recursion-context": "~2.0"
1418 | },
1419 | "require-dev": {
1420 | "ext-mbstring": "*",
1421 | "phpunit/phpunit": "~4.4"
1422 | },
1423 | "type": "library",
1424 | "extra": {
1425 | "branch-alias": {
1426 | "dev-master": "2.0.x-dev"
1427 | }
1428 | },
1429 | "autoload": {
1430 | "classmap": [
1431 | "src/"
1432 | ]
1433 | },
1434 | "notification-url": "https://packagist.org/downloads/",
1435 | "license": [
1436 | "BSD-3-Clause"
1437 | ],
1438 | "authors": [
1439 | {
1440 | "name": "Jeff Welch",
1441 | "email": "whatthejeff@gmail.com"
1442 | },
1443 | {
1444 | "name": "Volker Dusch",
1445 | "email": "github@wallbash.com"
1446 | },
1447 | {
1448 | "name": "Bernhard Schussek",
1449 | "email": "bschussek@2bepublished.at"
1450 | },
1451 | {
1452 | "name": "Sebastian Bergmann",
1453 | "email": "sebastian@phpunit.de"
1454 | },
1455 | {
1456 | "name": "Adam Harvey",
1457 | "email": "aharvey@php.net"
1458 | }
1459 | ],
1460 | "description": "Provides the functionality to export PHP variables for visualization",
1461 | "homepage": "http://www.github.com/sebastianbergmann/exporter",
1462 | "keywords": [
1463 | "export",
1464 | "exporter"
1465 | ],
1466 | "time": "2016-11-19T08:54:04+00:00"
1467 | },
1468 | {
1469 | "name": "sebastian/global-state",
1470 | "version": "1.1.1",
1471 | "source": {
1472 | "type": "git",
1473 | "url": "https://github.com/sebastianbergmann/global-state.git",
1474 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
1475 | },
1476 | "dist": {
1477 | "type": "zip",
1478 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
1479 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
1480 | "shasum": ""
1481 | },
1482 | "require": {
1483 | "php": ">=5.3.3"
1484 | },
1485 | "require-dev": {
1486 | "phpunit/phpunit": "~4.2"
1487 | },
1488 | "suggest": {
1489 | "ext-uopz": "*"
1490 | },
1491 | "type": "library",
1492 | "extra": {
1493 | "branch-alias": {
1494 | "dev-master": "1.0-dev"
1495 | }
1496 | },
1497 | "autoload": {
1498 | "classmap": [
1499 | "src/"
1500 | ]
1501 | },
1502 | "notification-url": "https://packagist.org/downloads/",
1503 | "license": [
1504 | "BSD-3-Clause"
1505 | ],
1506 | "authors": [
1507 | {
1508 | "name": "Sebastian Bergmann",
1509 | "email": "sebastian@phpunit.de"
1510 | }
1511 | ],
1512 | "description": "Snapshotting of global state",
1513 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
1514 | "keywords": [
1515 | "global state"
1516 | ],
1517 | "time": "2015-10-12T03:26:01+00:00"
1518 | },
1519 | {
1520 | "name": "sebastian/object-enumerator",
1521 | "version": "2.0.1",
1522 | "source": {
1523 | "type": "git",
1524 | "url": "https://github.com/sebastianbergmann/object-enumerator.git",
1525 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7"
1526 | },
1527 | "dist": {
1528 | "type": "zip",
1529 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7",
1530 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7",
1531 | "shasum": ""
1532 | },
1533 | "require": {
1534 | "php": ">=5.6",
1535 | "sebastian/recursion-context": "~2.0"
1536 | },
1537 | "require-dev": {
1538 | "phpunit/phpunit": "~5"
1539 | },
1540 | "type": "library",
1541 | "extra": {
1542 | "branch-alias": {
1543 | "dev-master": "2.0.x-dev"
1544 | }
1545 | },
1546 | "autoload": {
1547 | "classmap": [
1548 | "src/"
1549 | ]
1550 | },
1551 | "notification-url": "https://packagist.org/downloads/",
1552 | "license": [
1553 | "BSD-3-Clause"
1554 | ],
1555 | "authors": [
1556 | {
1557 | "name": "Sebastian Bergmann",
1558 | "email": "sebastian@phpunit.de"
1559 | }
1560 | ],
1561 | "description": "Traverses array structures and object graphs to enumerate all referenced objects",
1562 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
1563 | "time": "2017-02-18T15:18:39+00:00"
1564 | },
1565 | {
1566 | "name": "sebastian/recursion-context",
1567 | "version": "2.0.0",
1568 | "source": {
1569 | "type": "git",
1570 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
1571 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a"
1572 | },
1573 | "dist": {
1574 | "type": "zip",
1575 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a",
1576 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a",
1577 | "shasum": ""
1578 | },
1579 | "require": {
1580 | "php": ">=5.3.3"
1581 | },
1582 | "require-dev": {
1583 | "phpunit/phpunit": "~4.4"
1584 | },
1585 | "type": "library",
1586 | "extra": {
1587 | "branch-alias": {
1588 | "dev-master": "2.0.x-dev"
1589 | }
1590 | },
1591 | "autoload": {
1592 | "classmap": [
1593 | "src/"
1594 | ]
1595 | },
1596 | "notification-url": "https://packagist.org/downloads/",
1597 | "license": [
1598 | "BSD-3-Clause"
1599 | ],
1600 | "authors": [
1601 | {
1602 | "name": "Jeff Welch",
1603 | "email": "whatthejeff@gmail.com"
1604 | },
1605 | {
1606 | "name": "Sebastian Bergmann",
1607 | "email": "sebastian@phpunit.de"
1608 | },
1609 | {
1610 | "name": "Adam Harvey",
1611 | "email": "aharvey@php.net"
1612 | }
1613 | ],
1614 | "description": "Provides functionality to recursively process PHP variables",
1615 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1616 | "time": "2016-11-19T07:33:16+00:00"
1617 | },
1618 | {
1619 | "name": "sebastian/resource-operations",
1620 | "version": "1.0.0",
1621 | "source": {
1622 | "type": "git",
1623 | "url": "https://github.com/sebastianbergmann/resource-operations.git",
1624 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
1625 | },
1626 | "dist": {
1627 | "type": "zip",
1628 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
1629 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
1630 | "shasum": ""
1631 | },
1632 | "require": {
1633 | "php": ">=5.6.0"
1634 | },
1635 | "type": "library",
1636 | "extra": {
1637 | "branch-alias": {
1638 | "dev-master": "1.0.x-dev"
1639 | }
1640 | },
1641 | "autoload": {
1642 | "classmap": [
1643 | "src/"
1644 | ]
1645 | },
1646 | "notification-url": "https://packagist.org/downloads/",
1647 | "license": [
1648 | "BSD-3-Clause"
1649 | ],
1650 | "authors": [
1651 | {
1652 | "name": "Sebastian Bergmann",
1653 | "email": "sebastian@phpunit.de"
1654 | }
1655 | ],
1656 | "description": "Provides a list of PHP built-in functions that operate on resources",
1657 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
1658 | "time": "2015-07-28T20:34:47+00:00"
1659 | },
1660 | {
1661 | "name": "sebastian/version",
1662 | "version": "2.0.1",
1663 | "source": {
1664 | "type": "git",
1665 | "url": "https://github.com/sebastianbergmann/version.git",
1666 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
1667 | },
1668 | "dist": {
1669 | "type": "zip",
1670 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
1671 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
1672 | "shasum": ""
1673 | },
1674 | "require": {
1675 | "php": ">=5.6"
1676 | },
1677 | "type": "library",
1678 | "extra": {
1679 | "branch-alias": {
1680 | "dev-master": "2.0.x-dev"
1681 | }
1682 | },
1683 | "autoload": {
1684 | "classmap": [
1685 | "src/"
1686 | ]
1687 | },
1688 | "notification-url": "https://packagist.org/downloads/",
1689 | "license": [
1690 | "BSD-3-Clause"
1691 | ],
1692 | "authors": [
1693 | {
1694 | "name": "Sebastian Bergmann",
1695 | "email": "sebastian@phpunit.de",
1696 | "role": "lead"
1697 | }
1698 | ],
1699 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1700 | "homepage": "https://github.com/sebastianbergmann/version",
1701 | "time": "2016-10-03T07:35:21+00:00"
1702 | },
1703 | {
1704 | "name": "symfony/polyfill-ctype",
1705 | "version": "v1.10.0",
1706 | "source": {
1707 | "type": "git",
1708 | "url": "https://github.com/symfony/polyfill-ctype.git",
1709 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
1710 | },
1711 | "dist": {
1712 | "type": "zip",
1713 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
1714 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
1715 | "shasum": ""
1716 | },
1717 | "require": {
1718 | "php": ">=5.3.3"
1719 | },
1720 | "suggest": {
1721 | "ext-ctype": "For best performance"
1722 | },
1723 | "type": "library",
1724 | "extra": {
1725 | "branch-alias": {
1726 | "dev-master": "1.9-dev"
1727 | }
1728 | },
1729 | "autoload": {
1730 | "psr-4": {
1731 | "Symfony\\Polyfill\\Ctype\\": ""
1732 | },
1733 | "files": [
1734 | "bootstrap.php"
1735 | ]
1736 | },
1737 | "notification-url": "https://packagist.org/downloads/",
1738 | "license": [
1739 | "MIT"
1740 | ],
1741 | "authors": [
1742 | {
1743 | "name": "Symfony Community",
1744 | "homepage": "https://symfony.com/contributors"
1745 | },
1746 | {
1747 | "name": "Gert de Pagter",
1748 | "email": "BackEndTea@gmail.com"
1749 | }
1750 | ],
1751 | "description": "Symfony polyfill for ctype functions",
1752 | "homepage": "https://symfony.com",
1753 | "keywords": [
1754 | "compatibility",
1755 | "ctype",
1756 | "polyfill",
1757 | "portable"
1758 | ],
1759 | "time": "2018-08-06T14:22:27+00:00"
1760 | },
1761 | {
1762 | "name": "symfony/yaml",
1763 | "version": "v4.2.3",
1764 | "source": {
1765 | "type": "git",
1766 | "url": "https://github.com/symfony/yaml.git",
1767 | "reference": "d461670ee145092b7e2a56c1da7118f19cadadb0"
1768 | },
1769 | "dist": {
1770 | "type": "zip",
1771 | "url": "https://api.github.com/repos/symfony/yaml/zipball/d461670ee145092b7e2a56c1da7118f19cadadb0",
1772 | "reference": "d461670ee145092b7e2a56c1da7118f19cadadb0",
1773 | "shasum": ""
1774 | },
1775 | "require": {
1776 | "php": "^7.1.3",
1777 | "symfony/polyfill-ctype": "~1.8"
1778 | },
1779 | "conflict": {
1780 | "symfony/console": "<3.4"
1781 | },
1782 | "require-dev": {
1783 | "symfony/console": "~3.4|~4.0"
1784 | },
1785 | "suggest": {
1786 | "symfony/console": "For validating YAML files using the lint command"
1787 | },
1788 | "type": "library",
1789 | "extra": {
1790 | "branch-alias": {
1791 | "dev-master": "4.2-dev"
1792 | }
1793 | },
1794 | "autoload": {
1795 | "psr-4": {
1796 | "Symfony\\Component\\Yaml\\": ""
1797 | },
1798 | "exclude-from-classmap": [
1799 | "/Tests/"
1800 | ]
1801 | },
1802 | "notification-url": "https://packagist.org/downloads/",
1803 | "license": [
1804 | "MIT"
1805 | ],
1806 | "authors": [
1807 | {
1808 | "name": "Fabien Potencier",
1809 | "email": "fabien@symfony.com"
1810 | },
1811 | {
1812 | "name": "Symfony Community",
1813 | "homepage": "https://symfony.com/contributors"
1814 | }
1815 | ],
1816 | "description": "Symfony Yaml Component",
1817 | "homepage": "https://symfony.com",
1818 | "time": "2019-01-16T20:35:37+00:00"
1819 | },
1820 | {
1821 | "name": "webmozart/assert",
1822 | "version": "1.4.0",
1823 | "source": {
1824 | "type": "git",
1825 | "url": "https://github.com/webmozart/assert.git",
1826 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
1827 | },
1828 | "dist": {
1829 | "type": "zip",
1830 | "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
1831 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
1832 | "shasum": ""
1833 | },
1834 | "require": {
1835 | "php": "^5.3.3 || ^7.0",
1836 | "symfony/polyfill-ctype": "^1.8"
1837 | },
1838 | "require-dev": {
1839 | "phpunit/phpunit": "^4.6",
1840 | "sebastian/version": "^1.0.1"
1841 | },
1842 | "type": "library",
1843 | "extra": {
1844 | "branch-alias": {
1845 | "dev-master": "1.3-dev"
1846 | }
1847 | },
1848 | "autoload": {
1849 | "psr-4": {
1850 | "Webmozart\\Assert\\": "src/"
1851 | }
1852 | },
1853 | "notification-url": "https://packagist.org/downloads/",
1854 | "license": [
1855 | "MIT"
1856 | ],
1857 | "authors": [
1858 | {
1859 | "name": "Bernhard Schussek",
1860 | "email": "bschussek@gmail.com"
1861 | }
1862 | ],
1863 | "description": "Assertions to validate method input/output with nice error messages.",
1864 | "keywords": [
1865 | "assert",
1866 | "check",
1867 | "validate"
1868 | ],
1869 | "time": "2018-12-25T11:19:39+00:00"
1870 | }
1871 | ],
1872 | "aliases": [],
1873 | "minimum-stability": "stable",
1874 | "stability-flags": [],
1875 | "prefer-stable": false,
1876 | "prefer-lowest": false,
1877 | "platform": {
1878 | "php": ">=5.5.0"
1879 | },
1880 | "platform-dev": []
1881 | }
1882 |
--------------------------------------------------------------------------------
/www/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 |
3 | volumes:
4 | logs:
5 | driver: local
6 |
7 | services:
8 | slim:
9 | image: php:7-alpine
10 | working_dir: /var/www
11 | command: php -S 0.0.0.0:8080 -t public
12 | environment:
13 | docker: "true"
14 | ports:
15 | - 8080:8080
16 | volumes:
17 | - .:/var/www
18 | - logs:/var/www/logs
19 |
--------------------------------------------------------------------------------
/www/logs/README.md:
--------------------------------------------------------------------------------
1 | Your Slim Framework application's log files will be written to this directory.
2 |
--------------------------------------------------------------------------------
/www/phpunit.xml:
--------------------------------------------------------------------------------
1 |
Try SlimFramework
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /www/test_extension.php: -------------------------------------------------------------------------------- 1 | Open($location, $name, $mode); 7 | return $store; 8 | } 9 | 10 | function SetupCertificates($location, $name, $mode) 11 | { 12 | $store = SetupStore($location, $name, $mode); 13 | $certs = $store->get_Certificates(); 14 | return $certs; 15 | 16 | } 17 | 18 | function SetupCertificate($location, $name, $mode, 19 | $find_type, $query, $valid_only, 20 | $number) 21 | { 22 | $certs = SetupCertificates($location, $name, $mode); 23 | if($find_type != NULL) 24 | { 25 | $certs = $certs->Find($find_type, $query, $valid_only); 26 | return $certs->Item($number); 27 | } 28 | else 29 | { 30 | $cert = $certs->Item($number); 31 | return $cert; 32 | } 33 | } 34 | 35 | function test_CPSignedData_Sign_Verify() 36 | { 37 | try{ 38 | $content = "test content"; 39 | $address = "http://testca.cryptopro.ru/tsp/tsp.srf"; 40 | $cert = SetupCertificate(CURRENT_USER_STORE, "My", STORE_OPEN_READ_ONLY, 41 | CERTIFICATE_FIND_SUBJECT_NAME, "Test", 0, 42 | 1); 43 | 44 | if(!$cert) 45 | return "Certificate not found"; 46 | $signer = new CPSigner(); 47 | $signer->set_TSAAddress($address); 48 | $signer->set_Certificate($cert); 49 | 50 | $sd = new CPSignedData(); 51 | $sd->set_ContentEncoding(1); 52 | $sd->set_Content(base64_encode($content)); 53 | 54 | // Второй параметр - тип подписи(1 = CADES_BES): http://cpdn.cryptopro.ru/default.asp?url=content/cades/namespace_c_ad_e_s_c_o_m_fe49883d8ff77f7edbeeaf0be3d44c0b_1fe49883d8ff77f7edbeeaf0be3d44c0b.html 55 | 56 | //Третий параметр detached - отделенная(true) или совмещенная (false) 57 | $sm = $sd->SignCades($signer, 1, false, 0); 58 | 59 | printf("Signature is:\n"); 60 | printf($sm); 61 | printf("\n"); 62 | 63 | $sd->VerifyCades($sm, 1, false); 64 | return 1; 65 | }catch(Exception $e) 66 | { 67 | printf($e->getMessage()); 68 | } 69 | } 70 | 71 | if(test_CPSignedData_Sign_Verify() == 1) 72 | { 73 | printf("TEST OK\n"); 74 | }else 75 | { 76 | printf("TEST FAIL\n"); 77 | } 78 | 79 | ?> 80 | -------------------------------------------------------------------------------- /www/tests/Functional/BaseTestCase.php: -------------------------------------------------------------------------------- 1 | $requestMethod, 39 | 'REQUEST_URI' => $requestUri 40 | ] 41 | ); 42 | 43 | // Set up a request object based on the environment 44 | $request = Request::createFromEnvironment($environment); 45 | 46 | // Add request data, if it exists 47 | if (isset($requestData)) { 48 | $request = $request->withParsedBody($requestData); 49 | } 50 | 51 | // Set up a response object 52 | $response = new Response(); 53 | 54 | // Use the application settings 55 | $settings = require __DIR__ . '/../../src/settings.php'; 56 | 57 | // Instantiate the application 58 | $app = new App($settings); 59 | 60 | // Set up dependencies 61 | require __DIR__ . '/../../src/dependencies.php'; 62 | 63 | // Register middleware 64 | if ($this->withMiddleware) { 65 | require __DIR__ . '/../../src/middleware.php'; 66 | } 67 | 68 | // Register routes 69 | require __DIR__ . '/../../src/routes.php'; 70 | 71 | // Process the application 72 | $response = $app->process($request, $response); 73 | 74 | // Return the response 75 | return $response; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /www/tests/Functional/HomepageTest.php: -------------------------------------------------------------------------------- 1 | runApp('GET', '/'); 13 | 14 | $this->assertEquals(200, $response->getStatusCode()); 15 | $this->assertContains('SlimFramework', (string)$response->getBody()); 16 | $this->assertNotContains('Hello', (string)$response->getBody()); 17 | } 18 | 19 | /** 20 | * Test that the index route with optional name argument returns a rendered greeting 21 | */ 22 | public function testGetHomepageWithGreeting() 23 | { 24 | $response = $this->runApp('GET', '/name'); 25 | 26 | $this->assertEquals(200, $response->getStatusCode()); 27 | $this->assertContains('Hello name!', (string)$response->getBody()); 28 | } 29 | 30 | /** 31 | * Test that the index route won't accept a post request 32 | */ 33 | public function testPostHomepageNotAllowed() 34 | { 35 | $response = $this->runApp('POST', '/', ['test']); 36 | 37 | $this->assertEquals(405, $response->getStatusCode()); 38 | $this->assertContains('Method not allowed', (string)$response->getBody()); 39 | } 40 | } --------------------------------------------------------------------------------