├── .deepsource.toml
├── .env.exp
├── .github
└── workflows
│ ├── docker-ci.yml
│ ├── ruff.yml
│ └── update-deps.yml
├── .gitignore
├── .pdm-python
├── .pre-commit-config.yaml
├── Dockerfile
├── LICENSE
├── README.md
├── app
├── __init__.py
├── controller.py
├── event.py
└── utils.py
├── app_conf.py
├── conf_dir
└── settings.toml
├── main.py
├── pdm.lock
├── pm2.json
├── pyproject.toml
├── res
├── json
│ └── status.json
└── pem
│ ├── aosp_ec.pem
│ ├── aosp_rsa.pem
│ ├── google.pem
│ └── knox.pem
├── screenshot.png
└── setting
├── __init__.py
└── telegrambot.py
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | [[analyzers]]
4 | name = "python"
5 |
6 | [analyzers.meta]
7 | runtime_version = "3.x.x"
--------------------------------------------------------------------------------
/.env.exp:
--------------------------------------------------------------------------------
1 | TELEGRAM_BOT_TOKEN=xxx
2 | # TELEGRAM_BOT_PROXY_ADDRESS=socks5://127.0.0.1:7890
3 |
--------------------------------------------------------------------------------
/.github/workflows/docker-ci.yml:
--------------------------------------------------------------------------------
1 | name: Docker Image CI
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | paths-ignore:
7 | - '**.md'
8 | - '**.toml'
9 | - 'LICENSE'
10 | - '!.github/workflows/**'
11 |
12 | env:
13 | REGISTRY: ghcr.io
14 | IMAGE_NAME: ${{ github.repository }}
15 |
16 | jobs:
17 | build-and-push-image:
18 | runs-on: ubuntu-latest
19 |
20 | permissions:
21 | contents: read
22 | packages: write
23 |
24 | steps:
25 | - name: Checkout repository
26 | uses: actions/checkout@v3
27 |
28 | - name: Log in to ghcr.io
29 | uses: docker/login-action@v2
30 | with:
31 | registry: ${{ env.REGISTRY }}
32 | username: ${{ github.actor }}
33 | password: ${{ secrets.GITHUB_TOKEN }}
34 |
35 | - name: Extract metadata (tags, labels) for Docker
36 | id: meta
37 | uses: docker/metadata-action@v4
38 | with:
39 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
40 |
41 | - name: Set up QEMU
42 | uses: docker/setup-qemu-action@v2
43 |
44 | - name: Set up Docker Buildx
45 | uses: docker/setup-buildx-action@v2
46 |
47 | - name: Build and push Docker image
48 | uses: docker/build-push-action@master
49 | with:
50 | context: .
51 | push: true
52 | platforms: linux/arm64, linux/amd64
53 | tags: ${{ steps.meta.outputs.tags }}
54 | labels: ${{ steps.meta.outputs.labels }}
55 |
--------------------------------------------------------------------------------
/.github/workflows/ruff.yml:
--------------------------------------------------------------------------------
1 | name: Ruff
2 | on: [ push, pull_request ]
3 | jobs:
4 | ruff:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v3
8 | - uses: chartboost/ruff-action@v1
9 |
--------------------------------------------------------------------------------
/.github/workflows/update-deps.yml:
--------------------------------------------------------------------------------
1 | name: Update dependencies
2 |
3 | on:
4 | schedule:
5 | - cron: "0 0 * * *"
6 | workflow_dispatch:
7 |
8 | permissions:
9 | contents: write
10 | pull-requests: write
11 |
12 | jobs:
13 | update-dependencies:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 |
18 | - name: Update dependencies
19 | uses: pdm-project/update-deps-action@main
20 | with:
21 | sign-off-commit: true
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Config/app.toml
2 |
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *$py.class
6 |
7 | # C extensions
8 | *.so
9 |
10 |
11 | # Distribution / packaging
12 | .Python
13 | build/
14 | develop-eggs/
15 | dist/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | pip-wheel-metadata/
26 | share/python-wheels/
27 | *.egg-info/
28 | .installed.cfg
29 | *.egg
30 | MANIFEST
31 |
32 | # PyInstaller
33 | # Usually these files are written by a python script from a template
34 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
35 | *.manifest
36 | *.spec
37 |
38 | # Installer logs
39 | pip-log.txt
40 | pip-delete-this-directory.txt
41 |
42 | # Unit test / coverage reports
43 | htmlcov/
44 | .tox/
45 | .nox/
46 | .coverage
47 | .coverage.*
48 | .cache
49 | nosetests.xml
50 | coverage.xml
51 | *.cover
52 | *.py,cover
53 | .hypothesis/
54 | .pytest_cache/
55 |
56 | # Translations
57 | *.mo
58 | *.pot
59 |
60 | # Django stuff:
61 | *.log
62 | local_settings.py
63 | db.sqlite3
64 | db.sqlite3-journal
65 |
66 | # Flask stuff:
67 | instance/
68 | .webassets-cache
69 |
70 | # Scrapy stuff:
71 | .scrapy
72 |
73 | # Sphinx documentation
74 | docs/_build/
75 |
76 | # PyBuilder
77 | target/
78 |
79 | # Jupyter Notebook
80 | .ipynb_checkpoints
81 |
82 | # IPython
83 | profile_default/
84 | ipython_config.py
85 |
86 | # pyenv
87 | .python-version
88 |
89 | # pipenv
90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
93 | # install all needed dependencies.
94 | #Pipfile.lock
95 |
96 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
97 | __pypackages__/
98 |
99 | # Celery stuff
100 | celerybeat-schedule
101 | celerybeat.pid
102 |
103 | # SageMath parsed files
104 | *.sage.py
105 |
106 | # Environments
107 | .env
108 | .venv
109 | env/
110 | venv/
111 | ENV/
112 | env.bak/
113 | venv.bak/
114 |
115 | # Spyder project settings
116 | .spyderproject
117 | .spyproject
118 |
119 | # Rope project settings
120 | .ropeproject
121 |
122 | # mkdocs documentation
123 | /site
124 |
125 | # mypy
126 | .mypy_cache/
127 | .dmypy.json
128 | dmypy.json
129 |
130 | # Pyre type checker
131 | .pyre/
--------------------------------------------------------------------------------
/.pdm-python:
--------------------------------------------------------------------------------
1 | /home/runner/work/KeyboxChecker/KeyboxChecker/.venv/bin/python
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v3.2.0
4 | hooks:
5 | - id: trailing-whitespace
6 | - id: end-of-file-fixer
7 | - id: check-yaml
8 | - id: check-added-large-files
9 |
10 | - repo: https://github.com/astral-sh/ruff-pre-commit
11 | # Ruff version.
12 | rev: v0.1.7
13 | hooks:
14 | # Run the linter.
15 | - id: ruff
16 | args: [ --fix ]
17 | # Run the formatter.
18 | - id: ruff-format
19 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.11-slim
2 | WORKDIR /app
3 | COPY . /app
4 | RUN pip install pdm && pdm install --prod
5 | CMD ["pdm", "run", "python", "main.py"]
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU Affero General Public License is a free, copyleft license for
11 | software and other kinds of works, specifically designed to ensure
12 | cooperation with the community in the case of network server software.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | our General Public Licenses are intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users.
19 |
20 | When we speak of free software, we are referring to freedom, not
21 | price. Our General Public Licenses are designed to make sure that you
22 | have the freedom to distribute copies of free software (and charge for
23 | them if you wish), that you receive source code or can get it if you
24 | want it, that you can change the software or use pieces of it in new
25 | free programs, and that you know you can do these things.
26 |
27 | Developers that use our General Public Licenses protect your rights
28 | with two steps: (1) assert copyright on the software, and (2) offer
29 | you this License which gives you legal permission to copy, distribute
30 | and/or modify the software.
31 |
32 | A secondary benefit of defending all users' freedom is that
33 | improvements made in alternate versions of the program, if they
34 | receive widespread use, become available for other developers to
35 | incorporate. Many developers of free software are heartened and
36 | encouraged by the resulting cooperation. However, in the case of
37 | software used on network servers, this result may fail to come about.
38 | The GNU General Public License permits making a modified version and
39 | letting the public access it on a server without ever releasing its
40 | source code to the public.
41 |
42 | The GNU Affero General Public License is designed specifically to
43 | ensure that, in such cases, the modified source code becomes available
44 | to the community. It requires the operator of a network server to
45 | provide the source code of the modified version running there to the
46 | users of that server. Therefore, public use of a modified version, on
47 | a publicly accessible server, gives the public access to the source
48 | code of the modified version.
49 |
50 | An older license, called the Affero General Public License and
51 | published by Affero, was designed to accomplish similar goals. This is
52 | a different license, not a version of the Affero GPL, but Affero has
53 | released a new version of the Affero GPL which permits relicensing under
54 | this license.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | TERMS AND CONDITIONS
60 |
61 | 0. Definitions.
62 |
63 | "This License" refers to version 3 of the GNU Affero General Public License.
64 |
65 | "Copyright" also means copyright-like laws that apply to other kinds of
66 | works, such as semiconductor masks.
67 |
68 | "The Program" refers to any copyrightable work licensed under this
69 | License. Each licensee is addressed as "you". "Licensees" and
70 | "recipients" may be individuals or organizations.
71 |
72 | To "modify" a work means to copy from or adapt all or part of the work
73 | in a fashion requiring copyright permission, other than the making of an
74 | exact copy. The resulting work is called a "modified version" of the
75 | earlier work or a work "based on" the earlier work.
76 |
77 | A "covered work" means either the unmodified Program or a work based
78 | on the Program.
79 |
80 | To "propagate" a work means to do anything with it that, without
81 | permission, would make you directly or secondarily liable for
82 | infringement under applicable copyright law, except executing it on a
83 | computer or modifying a private copy. Propagation includes copying,
84 | distribution (with or without modification), making available to the
85 | public, and in some countries other activities as well.
86 |
87 | To "convey" a work means any kind of propagation that enables other
88 | parties to make or receive copies. Mere interaction with a user through
89 | a computer network, with no transfer of a copy, is not conveying.
90 |
91 | An interactive user interface displays "Appropriate Legal Notices"
92 | to the extent that it includes a convenient and prominently visible
93 | feature that (1) displays an appropriate copyright notice, and (2)
94 | tells the user that there is no warranty for the work (except to the
95 | extent that warranties are provided), that licensees may convey the
96 | work under this License, and how to view a copy of this License. If
97 | the interface presents a list of user commands or options, such as a
98 | menu, a prominent item in the list meets this criterion.
99 |
100 | 1. Source Code.
101 |
102 | The "source code" for a work means the preferred form of the work
103 | for making modifications to it. "Object code" means any non-source
104 | form of a work.
105 |
106 | A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 |
111 | The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form. A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 |
122 | The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities. However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work. For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 |
135 | The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 |
139 | The Corresponding Source for a work in source code form is that
140 | same work.
141 |
142 | 2. Basic Permissions.
143 |
144 | All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met. This License explicitly affirms your unlimited
147 | permission to run the unmodified Program. The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work. This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 |
152 | You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force. You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright. Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 |
163 | Conveying under any other circumstances is permitted solely under
164 | the conditions stated below. Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 |
167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 |
169 | No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 |
175 | When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 |
183 | 4. Conveying Verbatim Copies.
184 |
185 | You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 |
193 | You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 |
196 | 5. Conveying Modified Source Versions.
197 |
198 | You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 |
202 | a) The work must carry prominent notices stating that you modified
203 | it, and giving a relevant date.
204 |
205 | b) The work must carry prominent notices stating that it is
206 | released under this License and any conditions added under section
207 | 7. This requirement modifies the requirement in section 4 to
208 | "keep intact all notices".
209 |
210 | c) You must license the entire work, as a whole, under this
211 | License to anyone who comes into possession of a copy. This
212 | License will therefore apply, along with any applicable section 7
213 | additional terms, to the whole of the work, and all its parts,
214 | regardless of how they are packaged. This License gives no
215 | permission to license the work in any other way, but it does not
216 | invalidate such permission if you have separately received it.
217 |
218 | d) If the work has interactive user interfaces, each must display
219 | Appropriate Legal Notices; however, if the Program has interactive
220 | interfaces that do not display Appropriate Legal Notices, your
221 | work need not make them do so.
222 |
223 | A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit. Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 |
233 | 6. Conveying Non-Source Forms.
234 |
235 | You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 |
240 | a) Convey the object code in, or embodied in, a physical product
241 | (including a physical distribution medium), accompanied by the
242 | Corresponding Source fixed on a durable physical medium
243 | customarily used for software interchange.
244 |
245 | b) Convey the object code in, or embodied in, a physical product
246 | (including a physical distribution medium), accompanied by a
247 | written offer, valid for at least three years and valid for as
248 | long as you offer spare parts or customer support for that product
249 | model, to give anyone who possesses the object code either (1) a
250 | copy of the Corresponding Source for all the software in the
251 | product that is covered by this License, on a durable physical
252 | medium customarily used for software interchange, for a price no
253 | more than your reasonable cost of physically performing this
254 | conveying of source, or (2) access to copy the
255 | Corresponding Source from a network server at no charge.
256 |
257 | c) Convey individual copies of the object code with a copy of the
258 | written offer to provide the Corresponding Source. This
259 | alternative is allowed only occasionally and noncommercially, and
260 | only if you received the object code with such an offer, in accord
261 | with subsection 6b.
262 |
263 | d) Convey the object code by offering access from a designated
264 | place (gratis or for a charge), and offer equivalent access to the
265 | Corresponding Source in the same way through the same place at no
266 | further charge. You need not require recipients to copy the
267 | Corresponding Source along with the object code. If the place to
268 | copy the object code is a network server, the Corresponding Source
269 | may be on a different server (operated by you or a third party)
270 | that supports equivalent copying facilities, provided you maintain
271 | clear directions next to the object code saying where to find the
272 | Corresponding Source. Regardless of what server hosts the
273 | Corresponding Source, you remain obligated to ensure that it is
274 | available for as long as needed to satisfy these requirements.
275 |
276 | e) Convey the object code using peer-to-peer transmission, provided
277 | you inform other peers where the object code and Corresponding
278 | Source of the work are being offered to the general public at no
279 | charge under subsection 6d.
280 |
281 | A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 |
285 | A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling. In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage. For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product. A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 |
298 | "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source. The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 |
306 | If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information. But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 |
317 | The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed. Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 |
325 | Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 |
331 | 7. Additional Terms.
332 |
333 | "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law. If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 |
342 | When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it. (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.) You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 |
349 | Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 |
353 | a) Disclaiming warranty or limiting liability differently from the
354 | terms of sections 15 and 16 of this License; or
355 |
356 | b) Requiring preservation of specified reasonable legal notices or
357 | author attributions in that material or in the Appropriate Legal
358 | Notices displayed by works containing it; or
359 |
360 | c) Prohibiting misrepresentation of the origin of that material, or
361 | requiring that modified versions of such material be marked in
362 | reasonable ways as different from the original version; or
363 |
364 | d) Limiting the use for publicity purposes of names of licensors or
365 | authors of the material; or
366 |
367 | e) Declining to grant rights under trademark law for use of some
368 | trade names, trademarks, or service marks; or
369 |
370 | f) Requiring indemnification of licensors and authors of that
371 | material by anyone who conveys the material (or modified versions of
372 | it) with contractual assumptions of liability to the recipient, for
373 | any liability that these contractual assumptions directly impose on
374 | those licensors and authors.
375 |
376 | All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10. If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term. If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 |
386 | If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 |
391 | Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 |
395 | 8. Termination.
396 |
397 | You may not propagate or modify a covered work except as expressly
398 | provided under this License. Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 |
403 | However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 |
410 | Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 |
417 | Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License. If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 |
423 | 9. Acceptance Not Required for Having Copies.
424 |
425 | You are not required to accept this License in order to receive or
426 | run a copy of the Program. Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance. However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work. These actions infringe copyright if you do
431 | not accept this License. Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 |
434 | 10. Automatic Licensing of Downstream Recipients.
435 |
436 | Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License. You are not responsible
439 | for enforcing compliance by third parties with this License.
440 |
441 | An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations. If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 |
451 | You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License. For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 |
459 | 11. Patents.
460 |
461 | A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based. The
463 | work thus licensed is called the contributor's "contributor version".
464 |
465 | A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version. For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 |
475 | Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 |
480 | In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement). To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 |
487 | If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients. "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 |
501 | If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 |
509 | A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License. You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 |
524 | Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 |
528 | 12. No Surrender of Others' Freedom.
529 |
530 | If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License. If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all. For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 |
540 | 13. Remote Network Interaction; Use with the GNU General Public License.
541 |
542 | Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software. This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 |
553 | Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work. The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 |
561 | 14. Revised Versions of this License.
562 |
563 | The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time. Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 |
568 | Each version is given a distinguishing version number. If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation. If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 |
577 | If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 |
582 | Later license versions may give you additional or different
583 | permissions. However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 |
587 | 15. Disclaimer of Warranty.
588 |
589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 |
598 | 16. Limitation of Liability.
599 |
600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 |
610 | 17. Interpretation of Sections 15 and 16.
611 |
612 | If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 |
619 | END OF TERMS AND CONDITIONS
620 |
621 | How to Apply These Terms to Your New Programs
622 |
623 | If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 |
627 | To do so, attach the following notices to the program. It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 |
632 |
633 | Copyright (C)
634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published
637 | by the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Keybox Checker
2 | [](https://github.com/KimmyXYC/KeyboxChecker/actions/workflows/ruff.yaml)
3 | [](https://github.com/KimmyXYC/KeyboxChecker/actions/workflows/docker-ci.yaml)
4 | ## 部署 / Deployment
5 |
6 | - 下载源码。 Download the code.
7 | ```shell
8 | git clone https://github.com/KimmyXYC/KeyboxChecker.git
9 | cd KeyboxChecker
10 | ```
11 |
12 | - 复制配置文件。 Copy configuration file.
13 | ```shell
14 | cp .env.exp .env
15 | ```
16 |
17 | - 填写配置文件。 Fill out the configuration file.
18 | ```
19 | TELEGRAM_BOT_TOKEN=xxx
20 | # TELEGRAM_BOT_PROXY_ADDRESS=socks5://127.0.0.1:7890
21 | ```
22 |
23 | ### 本地部署 / Local Deployment
24 | - 安装依赖并运行。 Install dependencies and run.
25 | ```shell
26 | pip3 install pdm
27 | pdm install
28 | pdm run python main.py
29 | ```
30 | - 使用 PM2 守护进程。 Use PM2 to daemonize the process.
31 | ```shell
32 | pm2 start pm2.json
33 | pm2 monit
34 | pm2 restart pm2.json
35 | pm2 stop pm2.json
36 | ```
37 |
38 | ### Docker 部署 / Docker Deployment
39 | - 使用预构建镜像。 Use pre-built image.
40 | ```shell
41 | docker run -d --name keyboxchecker --env-file .env ghcr.io/kimmyxyc/keyboxchecker:main
42 | ```
43 |
44 | ## 使用 / Usage
45 | 私聊发送 keybox.xml 文件 或 对 keybox.xml 文件回复 /check
46 | Send the keybox.xml file in the private chat or reply with /check to keybox.xml file.
47 |
48 | 
49 |
--------------------------------------------------------------------------------
/app/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2023/11/18 上午12:47
3 | # @Author : sudoskys
4 | # @File : __init__.py
5 | # @Software: PyCharm
6 |
--------------------------------------------------------------------------------
/app/controller.py:
--------------------------------------------------------------------------------
1 | from asgiref.sync import sync_to_async
2 | from loguru import logger
3 | from telebot import types
4 | from telebot import util
5 | from telebot.async_telebot import AsyncTeleBot
6 | from telebot.asyncio_helper import ApiTelegramException
7 | from telebot.asyncio_storage import StateMemoryStorage
8 |
9 | from setting.telegrambot import BotSetting
10 | from app import event
11 |
12 | StepCache = StateMemoryStorage()
13 |
14 |
15 | @sync_to_async
16 | def sync_to_async_func():
17 | pass
18 |
19 |
20 | class BotRunner(object):
21 | def __init__(self):
22 | self.bot = AsyncTeleBot(BotSetting.token, state_storage=StepCache)
23 |
24 | async def run(self):
25 | logger.info("Bot Start")
26 | bot = self.bot
27 | if BotSetting.proxy_address:
28 | from telebot import asyncio_helper
29 |
30 | asyncio_helper.proxy = BotSetting.proxy_address
31 | logger.info("Proxy tunnels are being used!")
32 | await self.bot.set_my_commands([types.BotCommand("check", "Check the validity of the Keybox")])
33 |
34 | @bot.message_handler(commands=['start', 'help'], chat_types=['private'])
35 | async def handle_start(message):
36 | await bot.reply_to(
37 | message,
38 | "Please send me a keybox.xml, and I will check if it is valid.\n\n"
39 | "Github: https://github.com/KimmyXYC/KeyboxChecker.git",
40 | disable_web_page_preview=True
41 | )
42 |
43 | @bot.message_handler(content_types=['document'], chat_types=['private'])
44 | async def handle_keybox(message: types.Message):
45 | if message.document.mime_type != 'application/xml' and message.document.mime_type != 'text/xml':
46 | await bot.reply_to(message, "File format error")
47 | return
48 | if message.document.file_size > 20 * 1024:
49 | await bot.reply_to(message, "File size is too large")
50 | return
51 | await event.keybox_check(bot, message, message.document)
52 |
53 | @bot.message_handler(commands=['check'])
54 | async def handle_keybox_check(message: types.Message):
55 | if message.reply_to_message and message.reply_to_message.document:
56 | document = message.reply_to_message.document
57 | if document.mime_type != 'application/xml' and document.mime_type != 'text/xml':
58 | await bot.reply_to(message, "File format error")
59 | return
60 | if document.file_size > 20 * 1024:
61 | await bot.reply_to(message, "File size is too large")
62 | return
63 | await event.keybox_check(bot, message, document)
64 | else:
65 | await bot.reply_to(message, "Please reply to a keybox.xml file")
66 |
67 | try:
68 | await bot.polling(
69 | non_stop=True, allowed_updates=util.update_types, skip_pending=True
70 | )
71 | except ApiTelegramException as e:
72 | logger.opt(exception=e).exception("ApiTelegramException")
73 | except Exception as e:
74 | logger.exception(e)
75 |
--------------------------------------------------------------------------------
/app/event.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time: 2024/7/28 19:55
3 | # @FileName: event.py
4 | # @Software: PyCharm
5 | # @GitHub: KimmyXYC
6 | import aiohttp
7 | import json
8 | import tempfile
9 | import time
10 | import os
11 | import re
12 | import xml.etree.ElementTree as ET
13 | from loguru import logger
14 | from datetime import datetime, timezone
15 | from cryptography import x509
16 | from cryptography.hazmat.backends import default_backend
17 | from cryptography.hazmat.primitives import hashes, serialization
18 | from cryptography.hazmat.primitives.asymmetric import padding, ec
19 |
20 |
21 | async def load_from_url():
22 | url = "https://android.googleapis.com/attestation/status"
23 |
24 | headers = {
25 | "Cache-Control": "max-age=0, no-cache, no-store, must-revalidate",
26 | "Pragma": "no-cache",
27 | "Expires": "0"
28 | }
29 |
30 | params = {
31 | "ts": int(time.time())
32 | }
33 |
34 | async with aiohttp.ClientSession() as session:
35 | async with session.get(url, headers=headers, params=params) as response:
36 | if response.status != 200:
37 | raise Exception(f"Error fetching data: {response.status}")
38 | return await response.json()
39 |
40 |
41 | def get_device_ids_and_algorithms(xml_file):
42 | tree = ET.parse(xml_file)
43 | root = tree.getroot()
44 |
45 | results = []
46 | for keybox in root.findall('Keybox'):
47 | device_id = keybox.get('DeviceID')
48 |
49 | for key in keybox.findall('Key'):
50 | algorithm = key.get('algorithm')
51 | device_info = {
52 | 'DeviceID': device_id if device_id else 'Unknown',
53 | 'Algorithm': algorithm if algorithm else 'Unknown'
54 | }
55 | results.append(device_info)
56 | return results
57 |
58 |
59 | def parse_number_of_certificates(xml_file):
60 | tree = ET.parse(xml_file)
61 | root = tree.getroot()
62 |
63 | number_of_certificates = root.find('.//NumberOfCertificates')
64 |
65 | if number_of_certificates is not None:
66 | count = int(number_of_certificates.text.strip())
67 | return count
68 | else:
69 | raise Exception('No NumberOfCertificates found.')
70 |
71 |
72 | def parse_certificates(xml_file, pem_number):
73 | tree = ET.parse(xml_file)
74 | root = tree.getroot()
75 |
76 | pem_certificates = root.findall('.//Certificate[@format="pem"]')
77 |
78 | if pem_certificates is not None:
79 | pem_contents = [cert.text.strip() for cert in pem_certificates[:pem_number]]
80 | return pem_contents
81 | else:
82 | raise Exception("No Certificate found.")
83 |
84 |
85 | def parse_private_key(xml_file):
86 | tree = ET.parse(xml_file)
87 | root = tree.getroot()
88 | private_key = root.find('.//PrivateKey')
89 | if private_key is not None:
90 | return private_key.text.strip()
91 | else:
92 | raise Exception("No PrivateKey found.")
93 |
94 |
95 | def load_public_key_from_file(file_path):
96 | with open(file_path, 'rb') as key_file:
97 | public_key = serialization.load_pem_public_key(
98 | key_file.read(),
99 | backend=default_backend()
100 | )
101 | return public_key
102 |
103 |
104 | def compare_keys(public_key1, public_key2):
105 | return public_key1.public_bytes(
106 | encoding=serialization.Encoding.PEM,
107 | format=serialization.PublicFormat.SubjectPublicKeyInfo
108 | ) == public_key2.public_bytes(
109 | encoding=serialization.Encoding.PEM,
110 | format=serialization.PublicFormat.SubjectPublicKeyInfo
111 | )
112 |
113 |
114 | async def keybox_check(bot, message, document):
115 | file_info = await bot.get_file(document.file_id)
116 | downloaded_file = await bot.download_file(file_info.file_path)
117 | with tempfile.NamedTemporaryFile(delete=False) as temp_file:
118 | temp_file.write(downloaded_file)
119 | temp_file.flush()
120 | temp_file.close()
121 | try:
122 | pem_number = parse_number_of_certificates(temp_file.name)
123 | pem_certificates = parse_certificates(temp_file.name, pem_number)
124 | private_key = parse_private_key(temp_file.name)
125 | keybox_info = get_device_ids_and_algorithms(temp_file.name)
126 | os.remove(temp_file.name)
127 | except Exception as e:
128 | logger.error(f"[Keybox Check][message.chat.id]: {e}")
129 | await bot.reply_to(message, e)
130 | os.remove(temp_file.name)
131 | return
132 | try:
133 | certificate = x509.load_pem_x509_certificate(
134 | pem_certificates[0].encode(),
135 | default_backend()
136 | )
137 | try:
138 | private_key = re.sub(re.compile(r'^\s+', re.MULTILINE), '', private_key)
139 | private_key = serialization.load_pem_private_key(
140 | private_key.encode(),
141 | password=None,
142 | backend=default_backend()
143 | )
144 | check_private_key = True
145 | except Exception:
146 | check_private_key = False
147 | except Exception as e:
148 | logger.error(f"[Keybox Check][message.chat.id]: {e}")
149 | await bot.reply_to(message, e)
150 | return
151 |
152 | # Keybox Information
153 | reply = f"📱 *Device ID:* `{keybox_info[0]['DeviceID']}`"
154 | reply += f"\n🔑 *Algorithm:* `{keybox_info[0]['Algorithm']}`"
155 | reply += "\n----------------------------------------"
156 |
157 | # Certificate Validity Verification
158 | serial_number = certificate.serial_number
159 | serial_number_string = hex(serial_number)[2:].lower()
160 | reply += f"\n🔐 *Serial number:* `{serial_number_string}`"
161 | subject = certificate.subject
162 | reply += "\nℹ️ *Subject:* `"
163 | for rdn in subject:
164 | reply += f"{rdn.oid._name}={rdn.value}, "
165 | reply = reply[:-2]
166 | reply += "`"
167 | not_valid_before = certificate.not_valid_before_utc
168 | not_valid_after = certificate.not_valid_after_utc
169 | current_time = datetime.now(timezone.utc)
170 | is_valid = not_valid_before <= current_time <= not_valid_after
171 | if is_valid:
172 | reply += "\n✅ Certificate within validity period"
173 | elif current_time > not_valid_after:
174 | reply += "\n❌ Expired certificate"
175 | else:
176 | reply += "\n❌ Invalid certificate"
177 |
178 | # Private Key Verification
179 | if check_private_key:
180 | private_key_public_key = private_key.public_key()
181 | certificate_public_key = certificate.public_key()
182 | if compare_keys(private_key_public_key, certificate_public_key):
183 | reply += "\n✅ Matching private key and certificate public key"
184 | else:
185 | reply += "\n❌ Mismatched private key and certificate public key"
186 | else:
187 | reply += "\n❌ Invalid private key"
188 |
189 | # Keychain Authentication
190 | flag = True
191 | for i in range(pem_number - 1):
192 | son_certificate = x509.load_pem_x509_certificate(pem_certificates[i].encode(), default_backend())
193 | father_certificate = x509.load_pem_x509_certificate(pem_certificates[i + 1].encode(), default_backend())
194 |
195 | if son_certificate.issuer != father_certificate.subject:
196 | flag = False
197 | break
198 | signature = son_certificate.signature
199 | signature_algorithm = son_certificate.signature_algorithm_oid._name
200 | tbs_certificate = son_certificate.tbs_certificate_bytes
201 | public_key = father_certificate.public_key()
202 | try:
203 | if signature_algorithm in ['sha256WithRSAEncryption', 'sha1WithRSAEncryption', 'sha384WithRSAEncryption',
204 | 'sha512WithRSAEncryption']:
205 | hash_algorithm = {
206 | 'sha256WithRSAEncryption': hashes.SHA256(),
207 | 'sha1WithRSAEncryption': hashes.SHA1(),
208 | 'sha384WithRSAEncryption': hashes.SHA384(),
209 | 'sha512WithRSAEncryption': hashes.SHA512()
210 | }[signature_algorithm]
211 | padding_algorithm = padding.PKCS1v15()
212 | public_key.verify(signature, tbs_certificate, padding_algorithm, hash_algorithm)
213 | elif signature_algorithm in ['ecdsa-with-SHA256', 'ecdsa-with-SHA1', 'ecdsa-with-SHA384',
214 | 'ecdsa-with-SHA512']:
215 | hash_algorithm = {
216 | 'ecdsa-with-SHA256': hashes.SHA256(),
217 | 'ecdsa-with-SHA1': hashes.SHA1(),
218 | 'ecdsa-with-SHA384': hashes.SHA384(),
219 | 'ecdsa-with-SHA512': hashes.SHA512()
220 | }[signature_algorithm]
221 | padding_algorithm = ec.ECDSA(hash_algorithm)
222 | public_key.verify(signature, tbs_certificate, padding_algorithm)
223 | else:
224 | raise ValueError("Unsupported signature algorithms")
225 | except Exception:
226 | flag = False
227 | break
228 | if flag:
229 | reply += "\n✅ Valid keychain"
230 | else:
231 | reply += "\n❌ Invalid keychain"
232 |
233 | # Root Certificate Validation
234 | root_certificate = x509.load_pem_x509_certificate(pem_certificates[-1].encode(), default_backend())
235 | root_public_key = root_certificate.public_key()
236 | google_public_key = load_public_key_from_file("res/pem/google.pem")
237 | aosp_ec_public_key = load_public_key_from_file("res/pem/aosp_ec.pem")
238 | aosp_rsa_public_key = load_public_key_from_file("res/pem/aosp_rsa.pem")
239 | knox_public_key = load_public_key_from_file("res/pem/knox.pem")
240 | if compare_keys(root_public_key, google_public_key):
241 | reply += "\n✅ Google hardware attestation root certificate"
242 | elif compare_keys(root_public_key, aosp_ec_public_key):
243 | reply += "\n🟡 AOSP software attestation root certificate (EC)"
244 | elif compare_keys(root_public_key, aosp_rsa_public_key):
245 | reply += "\n🟡 AOSP software attestation root certificate (RSA)"
246 | elif compare_keys(root_public_key, knox_public_key):
247 | reply += "\n✅ Samsung Knox attestation root certificate"
248 | else:
249 | reply += "\n❌ Unknown root certificate"
250 |
251 | # Number of Certificates in Keychain
252 | if pem_number >= 4:
253 | reply += "\n🟡 More than 3 certificates in the keychain"
254 |
255 | # Validation of certificate revocation
256 | try:
257 | status_json = await load_from_url()
258 | except Exception:
259 | logger.error("Failed to fetch Google's revoked keybox list")
260 | with open("res/json/status.json", 'r', encoding='utf-8') as file:
261 | status_json = json.load(file)
262 | reply += "\n⚠️ Using local revoked keybox list"
263 |
264 | status = None
265 | for i in range(pem_number):
266 | certificate = x509.load_pem_x509_certificate(pem_certificates[i].encode(), default_backend())
267 | serial_number = certificate.serial_number
268 | serial_number_string = hex(serial_number)[2:].lower()
269 | if status_json['entries'].get(serial_number_string, None):
270 | status = status_json['entries'][serial_number_string]
271 | break
272 | if not status:
273 | reply += "\n✅ Serial number not found in Google's revoked keybox list"
274 | else:
275 | reply += f"\n❌ Serial number found in Google's revoked keybox list\n🔍 *Reason:* `{status['reason']}`"
276 | reply += f"\n⏱ *Check Time (UTC):* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
277 | await bot.reply_to(message, reply, parse_mode='Markdown')
278 |
--------------------------------------------------------------------------------
/app/utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2023/11/18 上午12:51
3 | # @Author : sudoskys
4 | # @File : utils.py
5 | # @Software: PyCharm
6 | def parse_command(command):
7 | if not command:
8 | return None, None
9 | parts = command.split(" ", 1)
10 | if len(parts) > 1:
11 | return parts[0], parts[1]
12 | elif len(parts) == 1:
13 | return parts[0], None
14 | else:
15 | return None, None
16 |
17 |
18 | def generate_uuid():
19 | import shortuuid
20 |
21 | return str(shortuuid.uuid())
22 |
--------------------------------------------------------------------------------
/app_conf.py:
--------------------------------------------------------------------------------
1 | import dynaconf
2 | from dynaconf import Dynaconf, Validator
3 | from loguru import logger
4 |
5 | settings = Dynaconf(
6 | envvar_prefix="DYNACONF",
7 | settings_files=["conf_dir/settings.toml", "conf_dir/.secrets.toml"],
8 | validators=[
9 | # Ensure some parameter meets a condition
10 | # Validator('AGE', lte=30, gte=10),
11 | # validate a value is eq in specific env
12 | # Validator('PROJECT', eq='hello_world', env='production'),
13 | ],
14 | )
15 | settings.validators.register(
16 | Validator("app.debug", condition=lambda v: isinstance(v, bool), env="DEBUG"),
17 | )
18 | # raises after all possible errors are evaluated
19 | try:
20 | settings.validators.validate_all()
21 | except dynaconf.ValidationError as e:
22 | accumulative_errors = e.details
23 | logger.error(f"Setting Validation Error {accumulative_errors}")
24 | raise e
25 |
26 | # :) Look https://www.dynaconf.com/validation/ for more validations
27 |
28 |
29 | # `envvar_prefix` = export envvars with `export DYNACONF_FOO=bar`.
30 | # `settings_files` = Load these files in the order.
31 |
--------------------------------------------------------------------------------
/conf_dir/settings.toml:
--------------------------------------------------------------------------------
1 | [app]
2 | debug = false
3 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import sys
3 |
4 | from dotenv import load_dotenv
5 | from loguru import logger
6 |
7 | from app.controller import BotRunner
8 | from app_conf import settings
9 |
10 | load_dotenv()
11 | # 移除默认的日志处理器
12 | logger.remove()
13 | # 添加标准输出
14 | print("从配置文件中读取到的DEBUG为", settings.app.debug)
15 | handler_id = logger.add(sys.stderr, level="INFO" if not settings.app.debug else "DEBUG")
16 | # 添加文件写出
17 | logger.add(
18 | sink="run.log",
19 | format="{time} - {level} - {message}",
20 | level="INFO",
21 | rotation="100 MB",
22 | enqueue=True,
23 | )
24 |
25 | logger.info("Log Is Secret, Please Don't Share It To Others")
26 |
27 |
28 | async def main():
29 | await asyncio.gather(BotRunner().run())
30 |
31 |
32 | loop = asyncio.get_event_loop()
33 | loop.run_until_complete(main())
34 |
--------------------------------------------------------------------------------
/pm2.json:
--------------------------------------------------------------------------------
1 | {
2 | "apps": [
3 | {
4 | "name": "KeyboxChecker",
5 | "script": "pdm run python3 main.py",
6 | "instances": 1,
7 | "max_restarts": 3,
8 | "restart_delay": 10000,
9 | "exp_backoff_restart_delay": 100,
10 | "error_file": "app.log",
11 | "out_file": "app.log",
12 | "log_date_format": "YYYY-MM-DD HH-mm-ss"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = ""
3 | version = ""
4 | description = ""
5 | authors = [
6 | { name = "KimmyXYC", email = "kimmyxyc@gmail.com" },
7 | ]
8 | dependencies = [
9 | "pydantic<3.0.0,>=2.0.0",
10 | "pydantic-settings<3.0.0,>=2.1.0",
11 | "python-dotenv<2.0.0,>=1.0.0",
12 | "pytelegrambotapi<5.0.0,>=4.14.0",
13 | "loguru<1.0.0,>=0.7.0",
14 | "elara<1.0.0,>=0.5.5",
15 | "httpx<1.0.0,>=0.25.1",
16 | "shortuuid<2.0.0,>=1.0.11",
17 | "asgiref<4.0.0,>=3.7.2",
18 | "aiohttp>=3.9.0",
19 | "dynaconf>=3.2.4",
20 | "pre-commit>=3.5.0",
21 | "cryptography>=43.0.0",
22 | ]
23 |
24 |
25 |
26 | requires-python = ">=3.8"
27 | readme = "README.md"
28 | license = { text = "AGPL-3.0" }
29 |
30 |
31 | [tool.ruff]
32 | # Exclude a variety of commonly ignored directories.
33 | exclude = [
34 | ".idea",
35 | ".bzr",
36 | ".direnv",
37 | ".eggs",
38 | ".git",
39 | ".git-rewrite",
40 | ".hg",
41 | ".mypy_cache",
42 | ".nox",
43 | ".pants.d",
44 | ".pytype",
45 | ".ruff_cache",
46 | ".svn",
47 | ".tox",
48 | ".venv",
49 | "__pypackages__",
50 | "_build",
51 | "buck-out",
52 | "build",
53 | "dist",
54 | "node_modules",
55 | "venv",
56 | ]
57 |
58 | # Same as Black.
59 | line-length = 88
60 | indent-width = 4
61 |
62 | # Assume Python 3.8
63 | target-version = "py38"
64 |
65 | [tool.ruff.lint]
66 | # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
67 | select = ["E4", "E7", "E9", "F"]
68 | ignore = []
69 |
70 | # Allow fix for all enabled rules (when `--fix`) is provided.
71 | fixable = ["ALL"]
72 | unfixable = []
73 |
74 | # Allow unused variables when underscore-prefixed.
75 | dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
76 |
77 | [tool.ruff.format]
78 | # Like Black, use double quotes for strings.
79 | quote-style = "double"
80 |
81 | # Like Black, indent with spaces, rather than tabs.
82 | indent-style = "space"
83 |
84 | # Like Black, respect magic trailing commas.
85 | skip-magic-trailing-comma = false
86 |
87 | # Like Black, automatically detect the appropriate line ending.
88 | line-ending = "auto"
89 |
90 | [tool.pdm]
91 |
--------------------------------------------------------------------------------
/res/json/status.json:
--------------------------------------------------------------------------------
1 | {
2 | "entries": {
3 | "6681152659205225093": {
4 | "status": "REVOKED",
5 | "reason": "KEY_COMPROMISE"
6 | },
7 | "8350192447815228107": {
8 | "status": "REVOKED",
9 | "reason": "KEY_COMPROMISE"
10 | },
11 | "9408173275444922801": {
12 | "status": "REVOKED",
13 | "reason": "KEY_COMPROMISE"
14 | },
15 | "11244410301401252959": {
16 | "status": "REVOKED",
17 | "reason": "KEY_COMPROMISE"
18 | },
19 | "15346629759498347257": {
20 | "status": "REVOKED",
21 | "reason": "KEY_COMPROMISE"
22 | },
23 | "1228286566665971148": {
24 | "status": "REVOKED",
25 | "reason": "KEY_COMPROMISE"
26 | },
27 | "17471682139930361099": {
28 | "status": "REVOKED",
29 | "reason": "SOFTWARE_FLAW"
30 | },
31 | "1545991490585406285": {
32 | "status": "REVOKED",
33 | "reason": "KEY_COMPROMISE"
34 | },
35 | "16799496319142405818": {
36 | "status": "REVOKED",
37 | "reason": "KEY_COMPROMISE"
38 | },
39 | "2621004353020741590": {
40 | "status": "REVOKED",
41 | "reason": "KEY_COMPROMISE"
42 | },
43 | "1051246719628187981": {
44 | "status": "REVOKED",
45 | "reason": "KEY_COMPROMISE"
46 | },
47 | "c35747a084470c3135aeefe2b8d40cd6": {
48 | "status": "REVOKED",
49 | "reason": "KEY_COMPROMISE"
50 | },
51 | "ee3ac673107ddf0831027a84c532bee4": {
52 | "status": "REVOKED",
53 | "reason": "KEY_COMPROMISE"
54 | },
55 | "1f4363f4acefdf83ae59202b934cead9": {
56 | "status": "REVOKED",
57 | "reason": "KEY_COMPROMISE"
58 | },
59 | "633d72164968d2b7ec1a927a14c8efbe": {
60 | "status": "REVOKED",
61 | "reason": "KEY_COMPROMISE"
62 | },
63 | "f3a6cc97099ae7311ca7d1c55625a9e2": {
64 | "status": "REVOKED",
65 | "reason": "KEY_COMPROMISE"
66 | },
67 | "c360da616de6583ae816cdefdda66221": {
68 | "status": "REVOKED",
69 | "reason": "KEY_COMPROMISE"
70 | },
71 | "1476c32be5b4788386062ca1d6a3ec01": {
72 | "status": "REVOKED",
73 | "reason": "KEY_COMPROMISE"
74 | },
75 | "c9b95f08cb46c66e778a996bb04eb063": {
76 | "status": "REVOKED",
77 | "reason": "KEY_COMPROMISE"
78 | },
79 | "2775678662643671941": {
80 | "status": "REVOKED",
81 | "reason": "KEY_COMPROMISE"
82 | },
83 | "10478051501886118140": {
84 | "status": "REVOKED",
85 | "reason": "KEY_COMPROMISE"
86 | },
87 | "15304424745846567057": {
88 | "status": "REVOKED",
89 | "reason": "KEY_COMPROMISE"
90 | },
91 | "2540354691047989632": {
92 | "status": "REVOKED",
93 | "reason": "KEY_COMPROMISE"
94 | },
95 | "9605027729693255932": {
96 | "status": "REVOKED",
97 | "reason": "KEY_COMPROMISE"
98 | },
99 | "7266970422002561562": {
100 | "status": "REVOKED",
101 | "reason": "KEY_COMPROMISE"
102 | },
103 | "2121480040206509646": {
104 | "status": "REVOKED",
105 | "reason": "KEY_COMPROMISE"
106 | },
107 | "4722071905782261079": {
108 | "status": "REVOKED",
109 | "reason": "KEY_COMPROMISE"
110 | },
111 | "13791718860221210775": {
112 | "status": "REVOKED",
113 | "reason": "KEY_COMPROMISE"
114 | },
115 | "5318853256439367328": {
116 | "status": "REVOKED",
117 | "reason": "KEY_COMPROMISE"
118 | },
119 | "16619986970074733637": {
120 | "status": "REVOKED",
121 | "reason": "KEY_COMPROMISE"
122 | },
123 | "8090691296252605665": {
124 | "status": "REVOKED",
125 | "reason": "KEY_COMPROMISE"
126 | },
127 | "9422579570321443809": {
128 | "status": "REVOKED",
129 | "reason": "KEY_COMPROMISE"
130 | },
131 | "14441488828221950432": {
132 | "status": "REVOKED",
133 | "reason": "KEY_COMPROMISE"
134 | },
135 | "cfd09f492467a8d78f3c87f8ae82b0ed": {
136 | "status": "REVOKED",
137 | "reason": "KEY_COMPROMISE"
138 | },
139 | "843184b4161e8dfbb711061d3483ad81": {
140 | "status": "REVOKED",
141 | "reason": "KEY_COMPROMISE"
142 | },
143 | "f2e14b3039c35d54fb9661b60b17ec94": {
144 | "status": "REVOKED",
145 | "reason": "KEY_COMPROMISE"
146 | },
147 | "836d1498921ff86a22fe3768042849a2": {
148 | "status": "REVOKED",
149 | "reason": "KEY_COMPROMISE"
150 | },
151 | "c95180267ba53a50b636e36d32976065": {
152 | "status": "REVOKED",
153 | "reason": "KEY_COMPROMISE"
154 | },
155 | "9414602a0ce3f77d9ac05af532785ef": {
156 | "status": "REVOKED",
157 | "reason": "KEY_COMPROMISE"
158 | },
159 | "c21b00ddf8c5a26106a03e8c11b37998": {
160 | "status": "REVOKED",
161 | "reason": "KEY_COMPROMISE"
162 | },
163 | "d9e9fa3c6021bcca273b524f551feab9": {
164 | "status": "REVOKED",
165 | "reason": "KEY_COMPROMISE"
166 | },
167 | "6a0c9ef31f814ebb8d8301eb443f7940": {
168 | "status": "REVOKED",
169 | "reason": "KEY_COMPROMISE"
170 | },
171 | "78d6b0810af9e6897b62ef2e26a853d2": {
172 | "status": "REVOKED",
173 | "reason": "KEY_COMPROMISE"
174 | },
175 | "e8063fd19d678b46998c5d25bf6bcd2": {
176 | "status": "REVOKED",
177 | "reason": "KEY_COMPROMISE"
178 | },
179 | "a23891b8cf1e06bea42599aecd9bc9cf": {
180 | "status": "REVOKED",
181 | "reason": "KEY_COMPROMISE"
182 | },
183 | "fc609574570c3e0a1d347e02a2ad6d4d": {
184 | "status": "REVOKED",
185 | "reason": "SOFTWARE_FLAW"
186 | },
187 | "7355273169128314967": {
188 | "status": "REVOKED",
189 | "reason": "KEY_COMPROMISE"
190 | },
191 | "5344612975616013951": {
192 | "status": "REVOKED",
193 | "reason": "KEY_COMPROMISE"
194 | },
195 | "16166206677093325219": {
196 | "status": "REVOKED",
197 | "reason": "KEY_COMPROMISE"
198 | },
199 | "15489222854939603791": {
200 | "status": "REVOKED",
201 | "reason": "KEY_COMPROMISE"
202 | },
203 | "18154252358500841010": {
204 | "status": "REVOKED",
205 | "reason": "KEY_COMPROMISE"
206 | },
207 | "12098947777634431853": {
208 | "status": "REVOKED",
209 | "reason": "KEY_COMPROMISE"
210 | },
211 | "10997554208317698753": {
212 | "status": "REVOKED",
213 | "reason": "KEY_COMPROMISE"
214 | },
215 | "12365028775357944392": {
216 | "status": "REVOKED",
217 | "reason": "KEY_COMPROMISE"
218 | },
219 | "3bbbbd83aa163125a86e900730bc9f53": {
220 | "status": "REVOKED",
221 | "reason": "KEY_COMPROMISE"
222 | },
223 | "fb3b56606adc45049dd5ebc0846e0daf": {
224 | "status": "REVOKED",
225 | "reason": "KEY_COMPROMISE"
226 | },
227 | "90fdc81863091e2bc62519d620143d1": {
228 | "status": "REVOKED",
229 | "reason": "KEY_COMPROMISE"
230 | },
231 | "1ae2ba1ba985e8a55a3b617172e61537": {
232 | "status": "REVOKED",
233 | "reason": "KEY_COMPROMISE"
234 | },
235 | "7f69b2f66b0679f7fffc721fc3978128": {
236 | "status": "REVOKED",
237 | "reason": "KEY_COMPROMISE"
238 | },
239 | "4b7f33db15d04ce1736768dbad021261": {
240 | "status": "REVOKED",
241 | "reason": "KEY_COMPROMISE"
242 | },
243 | "43cf4aa6e5d9744dd436d9d5ef1391cd": {
244 | "status": "REVOKED",
245 | "reason": "KEY_COMPROMISE"
246 | },
247 | "ad3b740cccc9369f89240dbc5284cb10": {
248 | "status": "REVOKED",
249 | "reason": "KEY_COMPROMISE"
250 | },
251 | "9ed21fe7bfa899183bcb0833de8c5178": {
252 | "status": "REVOKED",
253 | "reason": "KEY_COMPROMISE"
254 | },
255 | "87a5a6991dfa390d3e4c61bbe3d291b3": {
256 | "status": "REVOKED",
257 | "reason": "KEY_COMPROMISE"
258 | },
259 | "fb5adea0f8212f845bea3f996bcee726": {
260 | "status": "REVOKED",
261 | "reason": "KEY_COMPROMISE"
262 | },
263 | "7f90e587a2cb6ef5dee0b83b58893d74": {
264 | "status": "REVOKED",
265 | "reason": "KEY_COMPROMISE"
266 | },
267 | "6b870bcad63bdfe92d02ba4698b16264": {
268 | "status": "REVOKED",
269 | "reason": "KEY_COMPROMISE"
270 | },
271 | "1af3b8c5427453b6937ae0bcb6fe447f": {
272 | "status": "REVOKED",
273 | "reason": "KEY_COMPROMISE"
274 | },
275 | "2975e3f59a67e034d4bd451b927f1d27": {
276 | "status": "REVOKED",
277 | "reason": "KEY_COMPROMISE"
278 | },
279 | "cdee0d31cb8400838344756231940aea": {
280 | "status": "REVOKED",
281 | "reason": "KEY_COMPROMISE"
282 | },
283 | "c578cd2e254c12dff8ee2ac82f93410a": {
284 | "status": "REVOKED",
285 | "reason": "KEY_COMPROMISE"
286 | },
287 | "e7daf1046d38581b22f1dd7946b15f1": {
288 | "status": "REVOKED",
289 | "reason": "KEY_COMPROMISE"
290 | },
291 | "8d76fce4395906995adf0de84b80e2ec": {
292 | "status": "REVOKED",
293 | "reason": "KEY_COMPROMISE"
294 | },
295 | "82d779713c8ee285e8a7ffd61cbfb7ed": {
296 | "status": "REVOKED",
297 | "reason": "KEY_COMPROMISE"
298 | },
299 | "fc0a3c9f31721c524c3bd84afa72cbe3": {
300 | "status": "REVOKED",
301 | "reason": "KEY_COMPROMISE"
302 | },
303 | "b8ac6e0771a0958aeaa4b68a111a5dee": {
304 | "status": "REVOKED",
305 | "reason": "KEY_COMPROMISE"
306 | },
307 | "94f4943f978b93b4d7f4e69dc20b4d6b": {
308 | "status": "REVOKED",
309 | "reason": "KEY_COMPROMISE"
310 | },
311 | "c39c08de9731fd57d124c3e17c53faca": {
312 | "status": "REVOKED",
313 | "reason": "KEY_COMPROMISE"
314 | },
315 | "e24e5301403dcb9bad30918083fa15c7": {
316 | "status": "REVOKED",
317 | "reason": "KEY_COMPROMISE"
318 | },
319 | "dfd704581cbf9fe223b5c351fab83b4e": {
320 | "status": "REVOKED",
321 | "reason": "KEY_COMPROMISE"
322 | },
323 | "dfd0bf6bb1cb606ef65572412c0d1ac8": {
324 | "status": "REVOKED",
325 | "reason": "KEY_COMPROMISE"
326 | },
327 | "4d818d8a042b22646a42c395e5c86d6": {
328 | "status": "REVOKED",
329 | "reason": "KEY_COMPROMISE"
330 | },
331 | "7f9ec229afd8185d8432f408108e0991": {
332 | "status": "REVOKED",
333 | "reason": "KEY_COMPROMISE"
334 | },
335 | "846736b71487a74075ed6f33f58e4b33": {
336 | "status": "REVOKED",
337 | "reason": "KEY_COMPROMISE"
338 | },
339 | "14e38b3979edef06d0e95b7131a08b22": {
340 | "status": "REVOKED",
341 | "reason": "KEY_COMPROMISE"
342 | },
343 | "c2272cf25f9ccac5b5633a36b5e08fa9": {
344 | "status": "REVOKED",
345 | "reason": "KEY_COMPROMISE"
346 | },
347 | "8868809403284598250": {
348 | "status": "REVOKED",
349 | "reason": "KEY_COMPROMISE"
350 | },
351 | "15443728027744674372": {
352 | "status": "REVOKED",
353 | "reason": "KEY_COMPROMISE"
354 | },
355 | "224403031710863989": {
356 | "status": "REVOKED",
357 | "reason": "KEY_COMPROMISE"
358 | },
359 | "3882667606589968590": {
360 | "status": "REVOKED",
361 | "reason": "KEY_COMPROMISE"
362 | },
363 | "8398415515671998339": {
364 | "status": "REVOKED",
365 | "reason": "KEY_COMPROMISE"
366 | },
367 | "13965740041072508681": {
368 | "status": "REVOKED",
369 | "reason": "KEY_COMPROMISE"
370 | },
371 | "70771aada0054842160ef0764bce1623": {
372 | "status": "REVOKED",
373 | "reason": "KEY_COMPROMISE"
374 | },
375 | "119e72132a781e012ce7a8e68533b140": {
376 | "status": "REVOKED",
377 | "reason": "KEY_COMPROMISE"
378 | },
379 | "4507699620177564323": {
380 | "status": "REVOKED",
381 | "reason": "KEY_COMPROMISE"
382 | },
383 | "fb15cf8fb17f479ab86309b964bc879f": {
384 | "status": "REVOKED",
385 | "reason": "KEY_COMPROMISE"
386 | },
387 | "10366491491059815913": {
388 | "status": "REVOKED",
389 | "reason": "KEY_COMPROMISE"
390 | },
391 | "b58f9dea5b5fa47a71232975c9a3105f": {
392 | "status": "REVOKED",
393 | "reason": "KEY_COMPROMISE"
394 | },
395 | "df60b49f7b9046b5234e0df74ea9ce6b": {
396 | "status": "REVOKED",
397 | "reason": "KEY_COMPROMISE"
398 | },
399 | "f05d190cdad24969d3303bcf387cb9b4": {
400 | "status": "REVOKED",
401 | "reason": "KEY_COMPROMISE"
402 | },
403 | "14423003903688859038": {
404 | "status": "REVOKED",
405 | "reason": "KEY_COMPROMISE"
406 | },
407 | "b0e3b89197086be252d5eb29f930e537": {
408 | "status": "REVOKED",
409 | "reason": "KEY_COMPROMISE"
410 | },
411 | "6845757010563880491": {
412 | "status": "REVOKED",
413 | "reason": "KEY_COMPROMISE"
414 | },
415 | "b1f1481091272a4911f18d20eaa12463": {
416 | "status": "REVOKED",
417 | "reason": "KEY_COMPROMISE"
418 | },
419 | "338b275a6333cc1b59888acf75527802": {
420 | "status": "REVOKED",
421 | "reason": "KEY_COMPROMISE"
422 | },
423 | "11131729192210368711": {
424 | "status": "REVOKED",
425 | "reason": "KEY_COMPROMISE"
426 | },
427 | "6717229404067592611": {
428 | "status": "REVOKED",
429 | "reason": "KEY_COMPROMISE"
430 | },
431 | "6815517147617176510": {
432 | "status": "REVOKED",
433 | "reason": "KEY_COMPROMISE"
434 | },
435 | "583dc5cc0dda3c1f886e9b7933137098": {
436 | "status": "REVOKED",
437 | "reason": "KEY_COMPROMISE"
438 | },
439 | "c0e272fdb6e5849fd898834a1598c2fe": {
440 | "status": "REVOKED",
441 | "reason": "KEY_COMPROMISE"
442 | },
443 | "71cf6a217187e89e086b072a1fd17596": {
444 | "status": "REVOKED",
445 | "reason": "KEY_COMPROMISE"
446 | },
447 | "14803998145538567806": {
448 | "status": "REVOKED",
449 | "reason": "KEY_COMPROMISE"
450 | },
451 | "a1c043b5aa1f915e0ee2d20fefaee8c1": {
452 | "status": "REVOKED",
453 | "reason": "KEY_COMPROMISE"
454 | },
455 | "16738628654716464919": {
456 | "status": "REVOKED",
457 | "reason": "KEY_COMPROMISE"
458 | },
459 | "4f327688e1a85e71955cefd696336b91": {
460 | "status": "REVOKED",
461 | "reason": "KEY_COMPROMISE"
462 | },
463 | "2b87baacd6338c76c0dd43c8a4a634d8": {
464 | "status": "REVOKED",
465 | "reason": "KEY_COMPROMISE"
466 | },
467 | "ee6126eeddc43fc387d7753867ed3e80": {
468 | "status": "REVOKED",
469 | "reason": "KEY_COMPROMISE"
470 | },
471 | "a9fb44f216e1fc41041aa21481b9e7a6": {
472 | "status": "REVOKED",
473 | "reason": "KEY_COMPROMISE"
474 | },
475 | "dc260c2618f40c1504ea3dbc75af48bc": {
476 | "status": "REVOKED",
477 | "reason": "KEY_COMPROMISE"
478 | },
479 | "12766508004442517294": {
480 | "status": "REVOKED",
481 | "reason": "KEY_COMPROMISE"
482 | },
483 | "f005b07f550b5dd96a43e3bb6831678": {
484 | "status": "REVOKED",
485 | "reason": "KEY_COMPROMISE"
486 | },
487 | "6972031689279523646": {
488 | "status": "REVOKED",
489 | "reason": "KEY_COMPROMISE"
490 | },
491 | "a67ddc27e1036c7abdd95f1d5e7cad4f": {
492 | "status": "REVOKED",
493 | "reason": "KEY_COMPROMISE"
494 | },
495 | "39473cc0a44911d10a38971286650ad": {
496 | "status": "REVOKED",
497 | "reason": "KEY_COMPROMISE"
498 | },
499 | "f0cf9f9d6bc5a7a7d82d9f0e510e57bb": {
500 | "status": "REVOKED",
501 | "reason": "KEY_COMPROMISE"
502 | },
503 | "4e8df84b0a2c3bc222eee317c88cd7ae": {
504 | "status": "REVOKED",
505 | "reason": "KEY_COMPROMISE"
506 | },
507 | "2f7e1dd99a063e16aceefa3e6d681575": {
508 | "status": "REVOKED",
509 | "reason": "KEY_COMPROMISE"
510 | },
511 | "6393c6390b60e0cfc9fb8d6ca1d23605": {
512 | "status": "REVOKED",
513 | "reason": "KEY_COMPROMISE"
514 | },
515 | "d4c59e957b7207ec11e1a7d8cfd4cb68": {
516 | "status": "REVOKED",
517 | "reason": "KEY_COMPROMISE"
518 | },
519 | "9c2051b3327baf0eb364d3ab96e1a3fb": {
520 | "status": "REVOKED",
521 | "reason": "KEY_COMPROMISE"
522 | },
523 | "bd1a9e9125a39b590cab7deecec05222": {
524 | "status": "REVOKED",
525 | "reason": "KEY_COMPROMISE"
526 | },
527 | "13554058501592369784": {
528 | "status": "REVOKED",
529 | "reason": "KEY_COMPROMISE"
530 | },
531 | "983a895183f5f1271d79202533722279": {
532 | "status": "REVOKED",
533 | "reason": "KEY_COMPROMISE"
534 | },
535 | "7fdc29d6e5f98ea6d13eb5e737ce705": {
536 | "status": "REVOKED",
537 | "reason": "KEY_COMPROMISE"
538 | },
539 | "3556819627137484722": {
540 | "status": "REVOKED",
541 | "reason": "KEY_COMPROMISE"
542 | },
543 | "ff540c3b97a46444f86ef71653e1df18": {
544 | "status": "REVOKED",
545 | "reason": "KEY_COMPROMISE"
546 | },
547 | "205941609533867482": {
548 | "status": "REVOKED",
549 | "reason": "KEY_COMPROMISE"
550 | },
551 | "a7c4afb483f1227dc82993f27d1c0998": {
552 | "status": "REVOKED",
553 | "reason": "KEY_COMPROMISE"
554 | },
555 | "6051ed8207d2d1c0bf927f9e2ada4b48": {
556 | "status": "REVOKED",
557 | "reason": "KEY_COMPROMISE"
558 | },
559 | "49c141a849df35acb6aaede2226f9e9b": {
560 | "status": "REVOKED",
561 | "reason": "KEY_COMPROMISE"
562 | },
563 | "e6710ab8649ebcfff1c399f0b233795a": {
564 | "status": "REVOKED",
565 | "reason": "KEY_COMPROMISE"
566 | },
567 | "3642e8ebda76a49229811a336135a82c": {
568 | "status": "REVOKED",
569 | "reason": "KEY_COMPROMISE"
570 | },
571 | "a7dc53700e9fc9847d4fea65c29da1e3": {
572 | "status": "REVOKED",
573 | "reason": "KEY_COMPROMISE"
574 | },
575 | "8ec25f23f03dbb50b8c16b8a00c1b385": {
576 | "status": "REVOKED",
577 | "reason": "KEY_COMPROMISE"
578 | },
579 | "1765470235229526865": {
580 | "status": "REVOKED",
581 | "reason": "KEY_COMPROMISE"
582 | },
583 | "4f9a18bc60b33deaf47659718c8e46f3": {
584 | "status": "REVOKED",
585 | "reason": "KEY_COMPROMISE"
586 | },
587 | "794603fd166a8b853084f94969b6f76a": {
588 | "status": "REVOKED",
589 | "reason": "KEY_COMPROMISE"
590 | },
591 | "9691410294288259865": {
592 | "status": "REVOKED",
593 | "reason": "KEY_COMPROMISE"
594 | },
595 | "dfe4a9b2dafa2bf5f641962cb3d5a332": {
596 | "status": "REVOKED",
597 | "reason": "KEY_COMPROMISE"
598 | },
599 | "33554d4e522d915d5dadf16f907c50f7": {
600 | "status": "REVOKED",
601 | "reason": "KEY_COMPROMISE"
602 | },
603 | "fdf3b3c1e92cec617335708d84e23d66": {
604 | "status": "REVOKED",
605 | "reason": "KEY_COMPROMISE"
606 | },
607 | "30d9c1c5524174bfbf439e9e73cdb79d": {
608 | "status": "REVOKED",
609 | "reason": "KEY_COMPROMISE"
610 | },
611 | "3751979701730164589": {
612 | "status": "REVOKED",
613 | "reason": "KEY_COMPROMISE"
614 | },
615 | "928a090e80bb6aee9db4e92b37e41509": {
616 | "status": "REVOKED",
617 | "reason": "KEY_COMPROMISE"
618 | },
619 | "649dbea9cb64ce308588905214fa361c": {
620 | "status": "REVOKED",
621 | "reason": "KEY_COMPROMISE"
622 | },
623 | "de9e893188f2e3a04e632f909270a491": {
624 | "status": "REVOKED",
625 | "reason": "KEY_COMPROMISE"
626 | },
627 | "2cf66a251b227a1b9ed6d4e019ea6b36": {
628 | "status": "REVOKED",
629 | "reason": "KEY_COMPROMISE"
630 | },
631 | "27ed27b2a8c46be59c98ea4711d0dc5f": {
632 | "status": "REVOKED",
633 | "reason": "KEY_COMPROMISE"
634 | },
635 | "2e028083625fd6ef9f74637ff449da5a": {
636 | "status": "REVOKED",
637 | "reason": "KEY_COMPROMISE"
638 | },
639 | "99eca9a3d7ce7c2d84476402c1e448cf": {
640 | "status": "REVOKED",
641 | "reason": "KEY_COMPROMISE"
642 | },
643 | "9d96f1e695269851494a91d48601a1d8": {
644 | "status": "REVOKED",
645 | "reason": "KEY_COMPROMISE"
646 | },
647 | "2600c3f9b352130017f198e556d57a52": {
648 | "status": "REVOKED",
649 | "reason": "KEY_COMPROMISE"
650 | },
651 | "9705747036760232149": {
652 | "status": "REVOKED",
653 | "reason": "KEY_COMPROMISE"
654 | },
655 | "3154d0663898188cca623ad25bc7271d": {
656 | "status": "REVOKED",
657 | "reason": "KEY_COMPROMISE"
658 | },
659 | "ce88396f2a456fc603cd766c78eacf13": {
660 | "status": "REVOKED",
661 | "reason": "KEY_COMPROMISE"
662 | },
663 | "13503260129030804995": {
664 | "status": "REVOKED",
665 | "reason": "KEY_COMPROMISE"
666 | },
667 | "1948b1f11ae6b513949d71d85462161f": {
668 | "status": "REVOKED",
669 | "reason": "KEY_COMPROMISE"
670 | },
671 | "fff56c1b1b7af0a7818eed63918c7abc": {
672 | "status": "REVOKED",
673 | "reason": "KEY_COMPROMISE"
674 | },
675 | "8758766de23bcb4724f9c10da041246e": {
676 | "status": "REVOKED",
677 | "reason": "KEY_COMPROMISE"
678 | },
679 | "8cb65966a99f08fa218afd99ec0e046a": {
680 | "status": "REVOKED",
681 | "reason": "KEY_COMPROMISE"
682 | },
683 | "13478723519430940204": {
684 | "status": "REVOKED",
685 | "reason": "KEY_COMPROMISE"
686 | },
687 | "4466280473208039047": {
688 | "status": "REVOKED",
689 | "reason": "KEY_COMPROMISE"
690 | },
691 | "8626111651415796206": {
692 | "status": "REVOKED",
693 | "reason": "KEY_COMPROMISE"
694 | },
695 | "fa303060f00a7d95cba05e1274907eda": {
696 | "status": "REVOKED",
697 | "reason": "KEY_COMPROMISE"
698 | },
699 | "5564751976450306924": {
700 | "status": "REVOKED",
701 | "reason": "KEY_COMPROMISE"
702 | },
703 | "10669975075318677953": {
704 | "status": "REVOKED",
705 | "reason": "KEY_COMPROMISE"
706 | },
707 | "2768878a858bffb3af12180a1ee5ed7a": {
708 | "status": "REVOKED",
709 | "reason": "KEY_COMPROMISE"
710 | },
711 | "2330e5e1e0a351ab4fc74c464ce88ed3": {
712 | "status": "REVOKED",
713 | "reason": "KEY_COMPROMISE"
714 | },
715 | "4be08979d68acd09934104b6bd2edda5": {
716 | "status": "REVOKED",
717 | "reason": "KEY_COMPROMISE"
718 | },
719 | "68d1984f7ba32bea63baa680bc5a556c": {
720 | "status": "REVOKED",
721 | "reason": "KEY_COMPROMISE"
722 | },
723 | "5145721877299830915": {
724 | "status": "REVOKED",
725 | "reason": "KEY_COMPROMISE"
726 | },
727 | "8e7c77d159509217d9e11cbfc2664681": {
728 | "status": "REVOKED",
729 | "reason": "KEY_COMPROMISE"
730 | },
731 | "5192399fb1d5fdfe95c4f2fb002ac5f": {
732 | "status": "REVOKED",
733 | "reason": "KEY_COMPROMISE"
734 | },
735 | "11918519357273683794": {
736 | "status": "REVOKED",
737 | "reason": "KEY_COMPROMISE"
738 | },
739 | "e00cc58c1ed1f7027f3dbc4e87d33199": {
740 | "status": "REVOKED",
741 | "reason": "KEY_COMPROMISE"
742 | },
743 | "3d8cbfb0f47429cc8165cf175e239a20": {
744 | "status": "REVOKED",
745 | "reason": "KEY_COMPROMISE"
746 | },
747 | "13325600579469253471": {
748 | "status": "REVOKED",
749 | "reason": "KEY_COMPROMISE"
750 | },
751 | "5214c6faf95197b2079a0a02c688421": {
752 | "status": "REVOKED",
753 | "reason": "KEY_COMPROMISE"
754 | },
755 | "551b630fbcd8b33a17f001f3d5b08f93": {
756 | "status": "REVOKED",
757 | "reason": "KEY_COMPROMISE"
758 | },
759 | "b3758e92dacf53edd06fa10d9a4361c9": {
760 | "status": "REVOKED",
761 | "reason": "KEY_COMPROMISE"
762 | },
763 | "33c18997768f13c04f7b81679632bf65": {
764 | "status": "REVOKED",
765 | "reason": "KEY_COMPROMISE"
766 | },
767 | "6355987390329458305": {
768 | "status": "REVOKED",
769 | "reason": "KEY_COMPROMISE"
770 | },
771 | "a3140abd9214f9db70b46964699c8cfb": {
772 | "status": "REVOKED",
773 | "reason": "KEY_COMPROMISE"
774 | },
775 | "3ec3e740a09fc63de719ed99dde9001": {
776 | "status": "REVOKED",
777 | "reason": "KEY_COMPROMISE"
778 | },
779 | "53e23541cbcde87c85555e180f8b4397": {
780 | "status": "REVOKED",
781 | "reason": "KEY_COMPROMISE"
782 | },
783 | "3b2c71a24f20eee5d71d51cd8533d188": {
784 | "status": "REVOKED",
785 | "reason": "KEY_COMPROMISE"
786 | },
787 | "93248cf706c6f2e26e7e83d4c86bea0": {
788 | "status": "REVOKED",
789 | "reason": "KEY_COMPROMISE"
790 | },
791 | "7aee28c4caf600d64355540e33269a57": {
792 | "status": "REVOKED",
793 | "reason": "KEY_COMPROMISE"
794 | },
795 | "3472939056772264175": {
796 | "status": "REVOKED",
797 | "reason": "KEY_COMPROMISE"
798 | },
799 | "b6e4b48e13ed2b06f9ef6fb16c0e37b2": {
800 | "status": "REVOKED",
801 | "reason": "KEY_COMPROMISE"
802 | },
803 | "bc32a062ce42973daa8e184bdb5810de": {
804 | "status": "REVOKED",
805 | "reason": "KEY_COMPROMISE"
806 | },
807 | "6254754cf6193d69f8370e6398f1956d": {
808 | "status": "REVOKED",
809 | "reason": "KEY_COMPROMISE"
810 | },
811 | "2a305e8eda6380f554ab0964f62ff187": {
812 | "status": "REVOKED",
813 | "reason": "KEY_COMPROMISE"
814 | },
815 | "af92c90e19f0da1673d19056937b46d3": {
816 | "status": "REVOKED",
817 | "reason": "KEY_COMPROMISE"
818 | },
819 | "4271430637556221188": {
820 | "status": "REVOKED",
821 | "reason": "KEY_COMPROMISE"
822 | },
823 | "10696134136102907523": {
824 | "status": "REVOKED",
825 | "reason": "KEY_COMPROMISE"
826 | },
827 | "d9a1ef01a1606b4eec1b34bbbe8d044e": {
828 | "status": "REVOKED",
829 | "reason": "KEY_COMPROMISE"
830 | },
831 | "10631151104397693527": {
832 | "status": "REVOKED",
833 | "reason": "KEY_COMPROMISE"
834 | },
835 | "20581dbacd135140e41ce15fa4820589": {
836 | "status": "REVOKED",
837 | "reason": "KEY_COMPROMISE"
838 | },
839 | "15950000780909930300": {
840 | "status": "REVOKED",
841 | "reason": "KEY_COMPROMISE"
842 | },
843 | "587213a0a017a3151c3e0d772f3b459a": {
844 | "status": "REVOKED",
845 | "reason": "KEY_COMPROMISE"
846 | },
847 | "16279865861478413754": {
848 | "status": "REVOKED",
849 | "reason": "KEY_COMPROMISE"
850 | },
851 | "97c5b89e9e51eff9e9897e92f865d21e": {
852 | "status": "REVOKED",
853 | "reason": "KEY_COMPROMISE"
854 | },
855 | "e6508499faf6a244d959a9a8d633caf4": {
856 | "status": "REVOKED",
857 | "reason": "KEY_COMPROMISE"
858 | },
859 | "14117867490237308293": {
860 | "status": "REVOKED",
861 | "reason": "KEY_COMPROMISE"
862 | },
863 | "b0645f9b21d8a8394f5e3475c35244e2": {
864 | "status": "REVOKED",
865 | "reason": "KEY_COMPROMISE"
866 | },
867 | "94494997671214484": {
868 | "status": "REVOKED",
869 | "reason": "KEY_COMPROMISE"
870 | },
871 | "6a44e14ef662d48d2fb413c808081fa": {
872 | "status": "REVOKED",
873 | "reason": "KEY_COMPROMISE"
874 | },
875 | "dfa7255055f80aa26fd9eb94217c7941": {
876 | "status": "REVOKED",
877 | "reason": "KEY_COMPROMISE"
878 | },
879 | "72d3b4e0d47b6f8887179ec2d300dad9": {
880 | "status": "REVOKED",
881 | "reason": "KEY_COMPROMISE"
882 | },
883 | "ce9ee7250269cc92daebc877ed9130f0": {
884 | "status": "REVOKED",
885 | "reason": "KEY_COMPROMISE"
886 | },
887 | "4373482b09e5d1c30144d74de4ed24c8": {
888 | "status": "REVOKED",
889 | "reason": "KEY_COMPROMISE"
890 | },
891 | "ad8257dd3a64436eed9bc69ed7f81a8e": {
892 | "status": "REVOKED",
893 | "reason": "KEY_COMPROMISE"
894 | },
895 | "f14187a6788de6b3ae4fd7c651d93aee": {
896 | "status": "REVOKED",
897 | "reason": "KEY_COMPROMISE"
898 | },
899 | "fc8643f646dc253c7b2a9ce69694036e": {
900 | "status": "REVOKED",
901 | "reason": "KEY_COMPROMISE"
902 | },
903 | "5272326329417510368": {
904 | "status": "REVOKED",
905 | "reason": "KEY_COMPROMISE"
906 | },
907 | "8123a63ed4783bc34c7ac20c8646f5a3": {
908 | "status": "REVOKED",
909 | "reason": "KEY_COMPROMISE"
910 | },
911 | "f10247aa2c62f6b8a73178026e9bc0b7": {
912 | "status": "REVOKED",
913 | "reason": "KEY_COMPROMISE"
914 | },
915 | "670acdd6e75f1834afe8568e4b090b8d": {
916 | "status": "REVOKED",
917 | "reason": "KEY_COMPROMISE"
918 | },
919 | "df922e62524b836180720612b9619a3a": {
920 | "status": "REVOKED",
921 | "reason": "KEY_COMPROMISE"
922 | },
923 | "13672903365956275417": {
924 | "status": "REVOKED",
925 | "reason": "KEY_COMPROMISE"
926 | },
927 | "14243129576127828603": {
928 | "status": "REVOKED",
929 | "reason": "KEY_COMPROMISE"
930 | },
931 | "424ab07c0f341f6a01fdb4d34798dd05": {
932 | "status": "REVOKED",
933 | "reason": "KEY_COMPROMISE"
934 | },
935 | "407d5f958d5fc95972cac240a900aa48": {
936 | "status": "REVOKED",
937 | "reason": "KEY_COMPROMISE"
938 | },
939 | "14096919803101624708": {
940 | "status": "REVOKED",
941 | "reason": "KEY_COMPROMISE"
942 | },
943 | "4f2db225d3384d2b9157941accf3ff6e": {
944 | "status": "REVOKED",
945 | "reason": "KEY_COMPROMISE"
946 | },
947 | "2d1b9bffc223503cde80405a71765905": {
948 | "status": "REVOKED",
949 | "reason": "KEY_COMPROMISE"
950 | },
951 | "5bad8e7d165b7a311e2b57621556506f": {
952 | "status": "REVOKED",
953 | "reason": "KEY_COMPROMISE"
954 | },
955 | "c3e63dff2bb50259fbd025733ecdd90b": {
956 | "status": "REVOKED",
957 | "reason": "KEY_COMPROMISE"
958 | },
959 | "457a612fd7e053298c4ee9d4b7691f44": {
960 | "status": "REVOKED",
961 | "reason": "KEY_COMPROMISE"
962 | },
963 | "511ef62d13cc31325eba9eac0774b5b1": {
964 | "status": "REVOKED",
965 | "reason": "KEY_COMPROMISE"
966 | },
967 | "4a359c9bec46babfbf94a2fe01c835bb": {
968 | "status": "REVOKED",
969 | "reason": "KEY_COMPROMISE"
970 | },
971 | "b329005210913255b99fa1c9f0844349": {
972 | "status": "REVOKED",
973 | "reason": "KEY_COMPROMISE"
974 | },
975 | "9e80eca04c949e335ee919de518bebbf": {
976 | "status": "REVOKED",
977 | "reason": "KEY_COMPROMISE"
978 | },
979 | "41d46d7986af544bc236bf833bded3a7": {
980 | "status": "REVOKED",
981 | "reason": "KEY_COMPROMISE"
982 | },
983 | "b216046ea1a9a39afe7a7bf846c2fd73": {
984 | "status": "REVOKED",
985 | "reason": "KEY_COMPROMISE"
986 | },
987 | "4775152230268351286": {
988 | "status": "REVOKED",
989 | "reason": "KEY_COMPROMISE"
990 | },
991 | "72736ea426dcd06ff0bbeb5a4dd79948": {
992 | "status": "REVOKED",
993 | "reason": "KEY_COMPROMISE"
994 | },
995 | "b8e48e0044936226009f11f3275692b7": {
996 | "status": "REVOKED",
997 | "reason": "KEY_COMPROMISE"
998 | },
999 | "24d407abdcb818b82418df9075f0ff44": {
1000 | "status": "REVOKED",
1001 | "reason": "KEY_COMPROMISE"
1002 | },
1003 | "73b3dcaca88c01fd6280fe072c1cbde6": {
1004 | "status": "REVOKED",
1005 | "reason": "KEY_COMPROMISE"
1006 | },
1007 | "a49e49a2a870d4e1de40aeaab37c8ca3": {
1008 | "status": "REVOKED",
1009 | "reason": "KEY_COMPROMISE"
1010 | },
1011 | "11481610630634287040": {
1012 | "status": "REVOKED",
1013 | "reason": "KEY_COMPROMISE"
1014 | },
1015 | "b680b2b314e7a715e390e14a33020908": {
1016 | "status": "REVOKED",
1017 | "reason": "KEY_COMPROMISE"
1018 | },
1019 | "e62b0afb8f80f139ef082bfc319c91af": {
1020 | "status": "REVOKED",
1021 | "reason": "KEY_COMPROMISE"
1022 | },
1023 | "ba3146d2bfb27978e943fab925bbeb85": {
1024 | "status": "REVOKED",
1025 | "reason": "KEY_COMPROMISE"
1026 | },
1027 | "8935204412779183185": {
1028 | "status": "REVOKED",
1029 | "reason": "KEY_COMPROMISE"
1030 | },
1031 | "faf84c1e7cd532045119e470d80be817": {
1032 | "status": "REVOKED",
1033 | "reason": "KEY_COMPROMISE"
1034 | },
1035 | "e0e2b831ac104ecccc5e5dd3a2f11b75": {
1036 | "status": "REVOKED",
1037 | "reason": "KEY_COMPROMISE"
1038 | },
1039 | "e1efed25187ebe05b745c7f466e57599": {
1040 | "status": "REVOKED",
1041 | "reason": "KEY_COMPROMISE"
1042 | },
1043 | "31b9588015bfba8e5b2762c87fb083cd": {
1044 | "status": "REVOKED",
1045 | "reason": "KEY_COMPROMISE"
1046 | },
1047 | "68d889ddd7bbdba0c50fe275576582ae": {
1048 | "status": "REVOKED",
1049 | "reason": "KEY_COMPROMISE"
1050 | },
1051 | "20c6af508272184d8dcae68f145835d0": {
1052 | "status": "REVOKED",
1053 | "reason": "KEY_COMPROMISE"
1054 | },
1055 | "10628994157453962498": {
1056 | "status": "REVOKED",
1057 | "reason": "KEY_COMPROMISE"
1058 | },
1059 | "2863739566415969992": {
1060 | "status": "REVOKED",
1061 | "reason": "KEY_COMPROMISE"
1062 | },
1063 | "be38635630e27b8d14049230d2cf8b12": {
1064 | "status": "REVOKED",
1065 | "reason": "KEY_COMPROMISE"
1066 | },
1067 | "c4b25c81d5f2adb396621cf1da8cd206": {
1068 | "status": "REVOKED",
1069 | "reason": "KEY_COMPROMISE"
1070 | },
1071 | "d3dcd288c1343eeb42f68f1ec707aa15": {
1072 | "status": "REVOKED",
1073 | "reason": "KEY_COMPROMISE"
1074 | },
1075 | "4c665ca6ca9a6671ea6c8c75f491dca": {
1076 | "status": "REVOKED",
1077 | "reason": "KEY_COMPROMISE"
1078 | },
1079 | "9b60240e40d15b581525433b9c1b699e": {
1080 | "status": "REVOKED",
1081 | "reason": "KEY_COMPROMISE"
1082 | },
1083 | "28a18b4f04d8e0ba1469e6f08128eb1": {
1084 | "status": "REVOKED",
1085 | "reason": "KEY_COMPROMISE"
1086 | },
1087 | "8940841425273370276": {
1088 | "status": "REVOKED",
1089 | "reason": "KEY_COMPROMISE"
1090 | },
1091 | "3177d1aafc14b92a33cd42c652d30692": {
1092 | "status": "REVOKED",
1093 | "reason": "KEY_COMPROMISE"
1094 | },
1095 | "a71808b06c9145429099a1aaaac0616b": {
1096 | "status": "REVOKED",
1097 | "reason": "KEY_COMPROMISE"
1098 | },
1099 | "a030ebea4ad0f0f5c7d30ce666c04828": {
1100 | "status": "REVOKED",
1101 | "reason": "KEY_COMPROMISE"
1102 | },
1103 | "9cde3eda4299bdd9bb585390e30a8f3b": {
1104 | "status": "REVOKED",
1105 | "reason": "KEY_COMPROMISE"
1106 | },
1107 | "595bf8afe78ffd88220c9339451ac155": {
1108 | "status": "REVOKED",
1109 | "reason": "KEY_COMPROMISE"
1110 | },
1111 | "9233668dceaa5b567e4cf9f52bd2e1e0": {
1112 | "status": "REVOKED",
1113 | "reason": "KEY_COMPROMISE"
1114 | },
1115 | "a321977211fe24e3d2dc8f76c083a08": {
1116 | "status": "REVOKED",
1117 | "reason": "KEY_COMPROMISE"
1118 | },
1119 | "846713e0424db838fa4a991d943c4549": {
1120 | "status": "REVOKED",
1121 | "reason": "KEY_COMPROMISE"
1122 | },
1123 | "a80f47c0862d94d9269be02b83c37b53": {
1124 | "status": "REVOKED",
1125 | "reason": "KEY_COMPROMISE"
1126 | },
1127 | "43a65376e35524afc045906d7071cdf7": {
1128 | "status": "REVOKED",
1129 | "reason": "KEY_COMPROMISE"
1130 | },
1131 | "16932cc7a3865cea312d84702032b55e": {
1132 | "status": "REVOKED",
1133 | "reason": "KEY_COMPROMISE"
1134 | },
1135 | "792e307458b653a6141d8a2d55a7d7": {
1136 | "status": "REVOKED",
1137 | "reason": "KEY_COMPROMISE"
1138 | },
1139 | "9734b6a853e67cd88f8f197f09f5b7ad": {
1140 | "status": "REVOKED",
1141 | "reason": "KEY_COMPROMISE"
1142 | },
1143 | "15735730174267438273": {
1144 | "status": "REVOKED",
1145 | "reason": "KEY_COMPROMISE"
1146 | },
1147 | "5ea29375f11952555ebae69b1a1991d8": {
1148 | "status": "REVOKED",
1149 | "reason": "KEY_COMPROMISE"
1150 | },
1151 | "8621345197686984555": {
1152 | "status": "REVOKED",
1153 | "reason": "KEY_COMPROMISE"
1154 | },
1155 | "6654493384142859524": {
1156 | "status": "REVOKED",
1157 | "reason": "KEY_COMPROMISE"
1158 | },
1159 | "53290dbb4f94c781223e541e524ddcd0": {
1160 | "status": "REVOKED",
1161 | "reason": "KEY_COMPROMISE"
1162 | },
1163 | "ddd542d3ab5936ad7fd7e336769f8c73": {
1164 | "status": "REVOKED",
1165 | "reason": "KEY_COMPROMISE"
1166 | },
1167 | "be1c1c337bea50e15973446559a6d9fc": {
1168 | "status": "REVOKED",
1169 | "reason": "KEY_COMPROMISE"
1170 | },
1171 | "cbbab31cd003e49bcf7161f250813585": {
1172 | "status": "REVOKED",
1173 | "reason": "KEY_COMPROMISE"
1174 | },
1175 | "b39c7850e07ffb8e3474c8bfaa09fe9d": {
1176 | "status": "REVOKED",
1177 | "reason": "KEY_COMPROMISE"
1178 | },
1179 | "11088723024112326817": {
1180 | "status": "REVOKED",
1181 | "reason": "KEY_COMPROMISE"
1182 | },
1183 | "c67256011aeebd5b499a79d0a68174a1": {
1184 | "status": "REVOKED",
1185 | "reason": "KEY_COMPROMISE"
1186 | },
1187 | "ef7634571778ff1f882a40929711dadf": {
1188 | "status": "REVOKED",
1189 | "reason": "KEY_COMPROMISE"
1190 | },
1191 | "ba76f7cf58dde094159eaa0ad7dd4815": {
1192 | "status": "REVOKED",
1193 | "reason": "KEY_COMPROMISE"
1194 | },
1195 | "d8952e9b744ae2b97eeaf0d237817677": {
1196 | "status": "REVOKED",
1197 | "reason": "KEY_COMPROMISE"
1198 | },
1199 | "4052208266068406503": {
1200 | "status": "REVOKED",
1201 | "reason": "KEY_COMPROMISE"
1202 | },
1203 | "1100c01705cf01afba09f4969c659705": {
1204 | "status": "REVOKED",
1205 | "reason": "KEY_COMPROMISE"
1206 | },
1207 | "92b6427efac231cf7da973d68b705d46": {
1208 | "status": "REVOKED",
1209 | "reason": "KEY_COMPROMISE"
1210 | },
1211 | "80479dd5006b90da882e13dcd19d0d3b": {
1212 | "status": "REVOKED",
1213 | "reason": "KEY_COMPROMISE"
1214 | },
1215 | "c3cf50f9c7b1fbc5019239edaa57b8be": {
1216 | "status": "REVOKED",
1217 | "reason": "KEY_COMPROMISE"
1218 | },
1219 | "24b08e455268f973f79e8af13419a04f": {
1220 | "status": "REVOKED",
1221 | "reason": "KEY_COMPROMISE"
1222 | },
1223 | "33d367c4f4e2ce7e51fd5dac92da62bc": {
1224 | "status": "REVOKED",
1225 | "reason": "KEY_COMPROMISE"
1226 | },
1227 | "c4bb59d6dcad28194dd534da18028287": {
1228 | "status": "REVOKED",
1229 | "reason": "KEY_COMPROMISE"
1230 | },
1231 | "4aecbb55ac95669cbd322a709f8b8242": {
1232 | "status": "REVOKED",
1233 | "reason": "KEY_COMPROMISE"
1234 | },
1235 | "5893256412279433040": {
1236 | "status": "REVOKED",
1237 | "reason": "KEY_COMPROMISE"
1238 | },
1239 | "b8af8941ed0939add111eb8e8b3f74c3": {
1240 | "status": "REVOKED",
1241 | "reason": "KEY_COMPROMISE"
1242 | },
1243 | "bf26a255d9bab04bd5e2a797b2c3e13d": {
1244 | "status": "REVOKED",
1245 | "reason": "KEY_COMPROMISE"
1246 | },
1247 | "ac74231d6efe02a918c52138c5e6a288": {
1248 | "status": "REVOKED",
1249 | "reason": "KEY_COMPROMISE"
1250 | },
1251 | "13208021490800717034": {
1252 | "status": "REVOKED",
1253 | "reason": "KEY_COMPROMISE"
1254 | },
1255 | "73de4f1c7f6540c3407c8f08c87dfc52": {
1256 | "status": "REVOKED",
1257 | "reason": "KEY_COMPROMISE"
1258 | },
1259 | "38bf5e098b9b9ffcccb7eee84fb9c09c": {
1260 | "status": "REVOKED",
1261 | "reason": "KEY_COMPROMISE"
1262 | },
1263 | "1497138949090246232": {
1264 | "status": "REVOKED",
1265 | "reason": "KEY_COMPROMISE"
1266 | },
1267 | "2a6fef545d4b8578bafb8245408fee26": {
1268 | "status": "REVOKED",
1269 | "reason": "KEY_COMPROMISE"
1270 | },
1271 | "452cd762f790c607b69946c27e383a4b": {
1272 | "status": "REVOKED",
1273 | "reason": "KEY_COMPROMISE"
1274 | },
1275 | "9867094464352066174": {
1276 | "status": "REVOKED",
1277 | "reason": "KEY_COMPROMISE"
1278 | },
1279 | "8887999446032040142": {
1280 | "status": "REVOKED",
1281 | "reason": "KEY_COMPROMISE"
1282 | },
1283 | "14191869834556450245": {
1284 | "status": "REVOKED",
1285 | "reason": "KEY_COMPROMISE"
1286 | },
1287 | "6ab1c2d064b242edc2dff1d95f688140": {
1288 | "status": "REVOKED",
1289 | "reason": "KEY_COMPROMISE"
1290 | },
1291 | "ab63439eabd211ed9cfbcc9d0b7d9972": {
1292 | "status": "REVOKED",
1293 | "reason": "KEY_COMPROMISE"
1294 | },
1295 | "fddd5e6a8d584b1a8141682a12bf5f75": {
1296 | "status": "REVOKED",
1297 | "reason": "KEY_COMPROMISE"
1298 | },
1299 | "24e6c13f4999fa3924e08994257323de": {
1300 | "status": "REVOKED",
1301 | "reason": "KEY_COMPROMISE"
1302 | },
1303 | "5f1f2c2f2c3f26bb8f111a279e634510": {
1304 | "status": "REVOKED",
1305 | "reason": "KEY_COMPROMISE"
1306 | },
1307 | "e1052a8a3ad9d5eebf23dae79cdf5fb3": {
1308 | "status": "REVOKED",
1309 | "reason": "KEY_COMPROMISE"
1310 | },
1311 | "57b3857f2784b1a37b356f821e4b6db0": {
1312 | "status": "REVOKED",
1313 | "reason": "KEY_COMPROMISE"
1314 | },
1315 | "10455742914461326988": {
1316 | "status": "REVOKED",
1317 | "reason": "KEY_COMPROMISE"
1318 | },
1319 | "a7c8f6f90f75a7fc7ee7db95c366dadf": {
1320 | "status": "REVOKED",
1321 | "reason": "KEY_COMPROMISE"
1322 | },
1323 | "4c40d55668244c65f690acd61040c369": {
1324 | "status": "REVOKED",
1325 | "reason": "KEY_COMPROMISE"
1326 | },
1327 | "6b9bf9652484e73952e9301e86ef7412": {
1328 | "status": "REVOKED",
1329 | "reason": "KEY_COMPROMISE"
1330 | },
1331 | "3da1dc524b8324ce144fd77b53897f57": {
1332 | "status": "REVOKED",
1333 | "reason": "KEY_COMPROMISE"
1334 | },
1335 | "d7126a65f10da48342714f7707c1c4bc": {
1336 | "status": "REVOKED",
1337 | "reason": "KEY_COMPROMISE"
1338 | },
1339 | "cd8225b35cfd298bf5356503e39feefa": {
1340 | "status": "REVOKED",
1341 | "reason": "KEY_COMPROMISE"
1342 | },
1343 | "72a09b54cf99c9cba6da5a96706cd3f9": {
1344 | "status": "REVOKED",
1345 | "reason": "KEY_COMPROMISE"
1346 | },
1347 | "d4370bfca57f597151a18427664bf093": {
1348 | "status": "REVOKED",
1349 | "reason": "KEY_COMPROMISE"
1350 | },
1351 | "cdef9adbc817a11faab9cbf410f0705d": {
1352 | "status": "REVOKED",
1353 | "reason": "KEY_COMPROMISE"
1354 | },
1355 | "f9a0b9888d7a76c58c99c226b7706747": {
1356 | "status": "REVOKED",
1357 | "reason": "KEY_COMPROMISE"
1358 | },
1359 | "7d7fd8b16f3b60fad552cb5af07d6aca": {
1360 | "status": "REVOKED",
1361 | "reason": "KEY_COMPROMISE"
1362 | },
1363 | "a6d4145d111b92c3a0254ba9745db9e3": {
1364 | "status": "REVOKED",
1365 | "reason": "KEY_COMPROMISE"
1366 | },
1367 | "94f191b632e0b448c576f70519693edb": {
1368 | "status": "REVOKED",
1369 | "reason": "KEY_COMPROMISE"
1370 | },
1371 | "3106306f29d13aef6a388d72e8e7bbab": {
1372 | "status": "REVOKED",
1373 | "reason": "KEY_COMPROMISE"
1374 | },
1375 | "d8c0880797d6f8571a050ed24ed074e1": {
1376 | "status": "REVOKED",
1377 | "reason": "KEY_COMPROMISE"
1378 | },
1379 | "b2963c20818a6588e3dab4a34ecb2b69": {
1380 | "status": "REVOKED",
1381 | "reason": "KEY_COMPROMISE"
1382 | },
1383 | "584d08a5cc306a991920a0def351a22d": {
1384 | "status": "REVOKED",
1385 | "reason": "KEY_COMPROMISE"
1386 | },
1387 | "9868d88a7b2f02cc2c625baf889af17": {
1388 | "status": "REVOKED",
1389 | "reason": "KEY_COMPROMISE"
1390 | },
1391 | "3557c27e3615017ab8c7d2b4edf5a10f": {
1392 | "status": "REVOKED",
1393 | "reason": "KEY_COMPROMISE"
1394 | },
1395 | "16964934668758645558": {
1396 | "status": "REVOKED",
1397 | "reason": "KEY_COMPROMISE"
1398 | },
1399 | "3cc2065cd9d758b7b4ccb42f67f310e1": {
1400 | "status": "REVOKED",
1401 | "reason": "KEY_COMPROMISE"
1402 | },
1403 | "77e24e974232bec792932a6d9cad855c": {
1404 | "status": "REVOKED",
1405 | "reason": "KEY_COMPROMISE"
1406 | },
1407 | "e022d351fb24f904d7cf76a74a932f25": {
1408 | "status": "REVOKED",
1409 | "reason": "KEY_COMPROMISE"
1410 | },
1411 | "1c94ce366c473a12088308148b7dc866": {
1412 | "status": "REVOKED",
1413 | "reason": "KEY_COMPROMISE"
1414 | },
1415 | "5ae2c1d4d4a678e71f2e7b489c2a2e4a": {
1416 | "status": "REVOKED",
1417 | "reason": "KEY_COMPROMISE"
1418 | },
1419 | "476860a2ea20f8112cf0bec8c845663b": {
1420 | "status": "REVOKED",
1421 | "reason": "KEY_COMPROMISE"
1422 | },
1423 | "93fbd4381bd491ad3d6dba8572cb01be": {
1424 | "status": "REVOKED",
1425 | "reason": "KEY_COMPROMISE"
1426 | },
1427 | "1cd8e467497e9ef0ada5bf15c9f922de": {
1428 | "status": "REVOKED",
1429 | "reason": "KEY_COMPROMISE"
1430 | },
1431 | "6597002198956766176": {
1432 | "status": "REVOKED",
1433 | "reason": "KEY_COMPROMISE"
1434 | },
1435 | "435f04d984cebaa7757b312a5f943067": {
1436 | "status": "REVOKED",
1437 | "reason": "KEY_COMPROMISE"
1438 | },
1439 | "f87b4fb3a9645d3e8abc73ed76fb0572": {
1440 | "status": "REVOKED",
1441 | "reason": "KEY_COMPROMISE"
1442 | },
1443 | "e8c84860ca10ea6aec4221e7afafcc1a": {
1444 | "status": "REVOKED",
1445 | "reason": "KEY_COMPROMISE"
1446 | },
1447 | "b7ac5bec96bd1de444c48457a13a858d": {
1448 | "status": "REVOKED",
1449 | "reason": "KEY_COMPROMISE"
1450 | },
1451 | "d16eec885e26129773878f9058704a63": {
1452 | "status": "REVOKED",
1453 | "reason": "KEY_COMPROMISE"
1454 | },
1455 | "1219e1543a92a9d2cae73a61625e9aab": {
1456 | "status": "REVOKED",
1457 | "reason": "KEY_COMPROMISE"
1458 | },
1459 | "b2a34feff0273b2f61298e02afe897bd": {
1460 | "status": "REVOKED",
1461 | "reason": "KEY_COMPROMISE"
1462 | },
1463 | "2a20089c6bc09179b28fa91542065d91": {
1464 | "status": "REVOKED",
1465 | "reason": "KEY_COMPROMISE"
1466 | },
1467 | "62e957ed597044819a0d49db6cfb9f38": {
1468 | "status": "REVOKED",
1469 | "reason": "KEY_COMPROMISE"
1470 | },
1471 | "a485f500019e8d664dc93c37a6a0c859": {
1472 | "status": "REVOKED",
1473 | "reason": "KEY_COMPROMISE"
1474 | },
1475 | "7384636828590053418": {
1476 | "status": "REVOKED",
1477 | "reason": "KEY_COMPROMISE"
1478 | },
1479 | "1961a915b048a8a457f3cf134cac94a1": {
1480 | "status": "REVOKED",
1481 | "reason": "KEY_COMPROMISE"
1482 | },
1483 | "b4aa79bf570cfe9bfb3fa59c24beb6db": {
1484 | "status": "REVOKED",
1485 | "reason": "KEY_COMPROMISE"
1486 | },
1487 | "11020791951271937866": {
1488 | "status": "REVOKED",
1489 | "reason": "KEY_COMPROMISE"
1490 | },
1491 | "c9208715e4912840d27bc5485fb08032": {
1492 | "status": "REVOKED",
1493 | "reason": "KEY_COMPROMISE"
1494 | },
1495 | "80f554df8f4db5e168b665e37674767b": {
1496 | "status": "REVOKED",
1497 | "reason": "KEY_COMPROMISE"
1498 | },
1499 | "b29207249b68c6712fbf243e6f318c9f": {
1500 | "status": "REVOKED",
1501 | "reason": "KEY_COMPROMISE"
1502 | },
1503 | "133149eb867d7d1cdb6a3555bb5489ad": {
1504 | "status": "REVOKED",
1505 | "reason": "KEY_COMPROMISE"
1506 | },
1507 | "ba98ecaf60d94aaa6c8ac685247a152d": {
1508 | "status": "REVOKED",
1509 | "reason": "KEY_COMPROMISE"
1510 | },
1511 | "7aca5ae4929be0870316c52a831254d0": {
1512 | "status": "REVOKED",
1513 | "reason": "KEY_COMPROMISE"
1514 | },
1515 | "12958730390904191521": {
1516 | "status": "REVOKED",
1517 | "reason": "KEY_COMPROMISE"
1518 | },
1519 | "7d2e383f6ecdcb69e62e6acbd9a356f": {
1520 | "status": "REVOKED",
1521 | "reason": "KEY_COMPROMISE"
1522 | },
1523 | "40a987951a45ead9ab2d4e3ab55bfc86": {
1524 | "status": "REVOKED",
1525 | "reason": "KEY_COMPROMISE"
1526 | },
1527 | "50e4fb9e6313d2fc048bff0537c9d9bc": {
1528 | "status": "REVOKED",
1529 | "reason": "KEY_COMPROMISE"
1530 | },
1531 | "d426ecd919711485e4d1e923cb9cd367": {
1532 | "status": "REVOKED",
1533 | "reason": "KEY_COMPROMISE"
1534 | },
1535 | "cc7b471209b7047084b2179373239c29": {
1536 | "status": "REVOKED",
1537 | "reason": "KEY_COMPROMISE"
1538 | },
1539 | "5bf5f851b04dd628def22feb04c3cec6": {
1540 | "status": "REVOKED",
1541 | "reason": "KEY_COMPROMISE"
1542 | },
1543 | "331fa3b0bc8f1899dd70bcb1a364c312": {
1544 | "status": "REVOKED",
1545 | "reason": "KEY_COMPROMISE"
1546 | },
1547 | "3010000535011146404": {
1548 | "status": "REVOKED",
1549 | "reason": "KEY_COMPROMISE"
1550 | },
1551 | "11387632805333568160": {
1552 | "status": "REVOKED",
1553 | "reason": "KEY_COMPROMISE"
1554 | },
1555 | "3ee622a0ecbd09ac188f5c4855a619f": {
1556 | "status": "REVOKED",
1557 | "reason": "KEY_COMPROMISE"
1558 | },
1559 | "5810985728898152653": {
1560 | "status": "REVOKED",
1561 | "reason": "SOFTWARE_FLAW"
1562 | },
1563 | "16623831713806747857": {
1564 | "status": "REVOKED",
1565 | "reason": "SOFTWARE_FLAW"
1566 | },
1567 | "1653902323508258478": {
1568 | "status": "REVOKED",
1569 | "reason": "SOFTWARE_FLAW"
1570 | },
1571 | "4754188387179831718": {
1572 | "status": "REVOKED",
1573 | "reason": "SOFTWARE_FLAW"
1574 | },
1575 | "18207673658158413385": {
1576 | "status": "REVOKED",
1577 | "reason": "SOFTWARE_FLAW"
1578 | },
1579 | "12327620949908374012": {
1580 | "status": "REVOKED",
1581 | "reason": "SOFTWARE_FLAW"
1582 | },
1583 | "14813405412631444771": {
1584 | "status": "REVOKED",
1585 | "reason": "SOFTWARE_FLAW"
1586 | },
1587 | "7857171223917578575": {
1588 | "status": "REVOKED",
1589 | "reason": "SOFTWARE_FLAW"
1590 | },
1591 | "1415893393487464817": {
1592 | "status": "REVOKED",
1593 | "reason": "SOFTWARE_FLAW"
1594 | },
1595 | "3060172519121275631": {
1596 | "status": "REVOKED",
1597 | "reason": "SOFTWARE_FLAW"
1598 | },
1599 | "1954785483012959664": {
1600 | "status": "REVOKED",
1601 | "reason": "SOFTWARE_FLAW"
1602 | },
1603 | "10845561047281622937": {
1604 | "status": "REVOKED",
1605 | "reason": "SOFTWARE_FLAW"
1606 | },
1607 | "2496041401547087770": {
1608 | "status": "REVOKED",
1609 | "reason": "SOFTWARE_FLAW"
1610 | },
1611 | "6885722966767738507": {
1612 | "status": "REVOKED",
1613 | "reason": "SOFTWARE_FLAW"
1614 | },
1615 | "5566180295247644916": {
1616 | "status": "REVOKED",
1617 | "reason": "SOFTWARE_FLAW"
1618 | },
1619 | "927486855755331393": {
1620 | "status": "REVOKED",
1621 | "reason": "SOFTWARE_FLAW"
1622 | },
1623 | "6165452071192422130": {
1624 | "status": "REVOKED",
1625 | "reason": "SOFTWARE_FLAW"
1626 | },
1627 | "15282787245290348368": {
1628 | "status": "REVOKED",
1629 | "reason": "SOFTWARE_FLAW"
1630 | },
1631 | "11313542145862450150": {
1632 | "status": "REVOKED",
1633 | "reason": "SOFTWARE_FLAW"
1634 | },
1635 | "11246999805035486387": {
1636 | "status": "REVOKED",
1637 | "reason": "SOFTWARE_FLAW"
1638 | },
1639 | "10623557657433978240": {
1640 | "status": "REVOKED",
1641 | "reason": "SOFTWARE_FLAW"
1642 | },
1643 | "1440276514173143642": {
1644 | "status": "REVOKED",
1645 | "reason": "SOFTWARE_FLAW"
1646 | },
1647 | "7102180478812285056": {
1648 | "status": "REVOKED",
1649 | "reason": "SOFTWARE_FLAW"
1650 | },
1651 | "3949279890763234464": {
1652 | "status": "REVOKED",
1653 | "reason": "SOFTWARE_FLAW"
1654 | }
1655 | }
1656 | }
--------------------------------------------------------------------------------
/res/pem/aosp_ec.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7l1ex+HA220Dpn7mthvsTWpdamgu
3 | D/9/SQ59dx9EIm29sa/6FsvHrcV30lacqrewLVQBXT5DKyqO107sSHVBpA==
4 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/res/pem/aosp_rsa.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCia63rbi5EYe/VDoLmt5TRdSMf
3 | d5tjkWP/96r/C3JHTsAsQ+wzfNes7UA+jCigZtX3hwszl94OuE4TQKuvpSe/lWmg
4 | MdsGUmX4RFlXYfC78hdLt0GAZMAoDo9Sd47b0ke2RekZyOmLw9vCkT/X11DEHTVm
5 | +Vfkl5YLCazOkjWFmwIDAQAB
6 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/res/pem/google.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAr7bHgiuxpwHsK7Qui8xU
3 | FmOr75gvMsd/dTEDDJdSSxtf6An7xyqpRR90PL2abxM1dEqlXnf2tqw1Ne4Xwl5j
4 | lRfdnJLmN0pTy/4lj4/7tv0Sk3iiKkypnEUtR6WfMgH0QZfKHM1+di+y9TFRtv6y
5 | //0rb+T+W8a9nsNL/ggjnar86461qO0rOs2cXjp3kOG1FEJ5MVmFmBGtnrKpa73X
6 | pXyTqRxB/M0n1n/W9nGqC4FSYa04T6N5RIZGBN2z2MT5IKGbFlbC8UrW0DxW7AYI
7 | mQQcHtGl/m00QLVWutHQoVJYnFPlXTcHYvASLu+RhhsbDmxMgJJ0mcDpvsC4PjvB
8 | +TxywElgS70vE0XmLD+OJtvsBslHZvPBKCOdT0MS+tgSOIfga+z1Z1g7+DVagf7q
9 | uvmag8jfPioyKvxnK/EgsTUVi2ghzq8wm27ud/mIM7AY2qEORR8Go3TVB4HzWQgp
10 | Zrt3i5MIlCaY504LzSRiigHCzAPlHws+W0rB5N+er5/2pJKnfBSDiCiFAVtCLOZ7
11 | gLiMm0jhO2B6tUXHI/+MRPjy02i59lINMRRev56GKtcd9qO/0kUJWdZTdA2XoS82
12 | ixPvZtXQpUpuL12ab+9EaDK8Z4RHJYYfCT3Q5vNAXaiWQ+8PTWm2QgBR/bkwSWc+
13 | NpUFgNPN9PvQi8WEg5UmAGMCAwEAAQ==
14 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/res/pem/knox.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBhbGuLrpql5I2WJmrE5kEVZOo+dgA
3 | 46mKrVJf/sgzfzs2u7M9c1Y9ZkCEiiYkhTFE9vPbasmUfXybwgZ2EM30A1ABPd12
4 | 4n3JbEDfsB/wnMH1AcgsJyJFPbETZiy42Fhwi+2BCA5bcHe7SrdkRIYSsdBRaKBo
5 | ZsapxB0gAOs0jSPRX5M=
6 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimmyXYC/KeyboxChecker/cc57c222f13ce4dab10d762e97e014c87ac4e5eb/screenshot.png
--------------------------------------------------------------------------------
/setting/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2023/11/25 下午9:05
3 | # @Author : sudoskys
4 | # @File : __init__.py.py
5 | # @Software: PyCharm
6 |
--------------------------------------------------------------------------------
/setting/telegrambot.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2023/11/18 上午12:32
3 | # @File : schema.py
4 | # @Software: PyCharm
5 | from typing import Optional
6 |
7 | import requests
8 | from dotenv import load_dotenv
9 | from loguru import logger
10 | from pydantic import Field, model_validator
11 | from pydantic_settings import BaseSettings, SettingsConfigDict
12 |
13 |
14 | class TelegramBot(BaseSettings):
15 | """
16 | 代理设置
17 | """
18 |
19 | token: Optional[str] = Field(None, validation_alias="TELEGRAM_BOT_TOKEN")
20 | proxy_address: Optional[str] = Field(
21 | None, validation_alias="TELEGRAM_BOT_PROXY_ADDRESS"
22 | ) # "all://127.0.0.1:7890"
23 | bot_link: Optional[str] = Field(None, validation_alias="TELEGRAM_BOT_LINK")
24 | bot_id: Optional[str] = Field(None, validation_alias="TELEGRAM_BOT_ID")
25 | bot_username: Optional[str] = Field(None, validation_alias="TELEGRAM_BOT_USERNAME")
26 | model_config = SettingsConfigDict(
27 | env_file=".env", env_file_encoding="utf-8", extra="ignore"
28 | )
29 |
30 | @model_validator(mode="after")
31 | def bot_validator(self):
32 | if self.proxy_address:
33 | logger.success(f"TelegramBot proxy was set to {self.proxy_address}")
34 | if self.token is None:
35 | logger.info("\n🍀Check:Telegrambot token is empty")
36 | if self.bot_id is None and self.token:
37 | try:
38 | from telebot import TeleBot
39 |
40 | # 创建 Bot
41 | if self.proxy_address is not None:
42 | from telebot import apihelper
43 |
44 | if "socks5://" in self.proxy_address:
45 | self.proxy_address = self.proxy_address.replace(
46 | "socks5://", "socks5h://"
47 | )
48 | apihelper.proxy = {"https": self.proxy_address}
49 | _bot = TeleBot(token=self.token).get_me()
50 | self.bot_id = str(_bot.id)
51 | self.bot_username = _bot.username
52 | self.bot_link = f"https://t.me/{self.bot_username}"
53 | except requests.exceptions.ConnectTimeout:
54 | logger.error(
55 | "\n🍀TelegramBot Connect Error --error ConnectTimeout, Please Check Your Network To Telegram"
56 | )
57 | raise requests.exceptions.ConnectTimeout
58 | except Exception as e:
59 | logger.error(f"\n🍀TelegramBot Connect Error --error {e}")
60 | else:
61 | logger.success(
62 | f"🍀TelegramBot Init Connection Success --bot_name {self.bot_username} --bot_id {self.bot_id}"
63 | )
64 | return self
65 |
66 | @property
67 | def available(self):
68 | return self.token is not None
69 |
70 |
71 | load_dotenv()
72 | BotSetting = TelegramBot()
73 |
--------------------------------------------------------------------------------