openbadgeslib 2.0.0__tar.gz → 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/Changelog.txt +39 -0
- {openbadgeslib-2.0.0/openbadgeslib.egg-info → openbadgeslib-3.0.0}/PKG-INFO +27 -32
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/README.md +26 -31
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/__init__.py +11 -2
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/badge.py +2 -2
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/config.ini.example +8 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/mail.py +1 -1
- openbadgeslib-3.0.0/openbadgeslib/ob2/__init__.py +41 -0
- openbadgeslib-3.0.0/openbadgeslib/ob2/models.py +376 -0
- openbadgeslib-3.0.0/openbadgeslib/ob2/signer.py +108 -0
- openbadgeslib-3.0.0/openbadgeslib/ob2/verifier.py +363 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_keygenerator.py +3 -3
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_publish.py +95 -2
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_signer.py +95 -6
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_verifier.py +93 -8
- openbadgeslib-3.0.0/openbadgeslib/signer.py +4 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/util.py +1 -1
- openbadgeslib-3.0.0/openbadgeslib/verifier.py +4 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0/openbadgeslib.egg-info}/PKG-INFO +27 -32
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/SOURCES.txt +12 -4
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_cli_json.py +11 -11
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_cli_smoke.py +29 -29
- openbadgeslib-2.0.0/tests/test_badge_io.py → openbadgeslib-3.0.0/tests/test_ob1_badge_io.py +10 -10
- openbadgeslib-2.0.0/tests/test_verify_operation.py → openbadgeslib-3.0.0/tests/test_ob1_verifier.py +12 -12
- openbadgeslib-3.0.0/tests/test_ob2_cli.py +215 -0
- openbadgeslib-3.0.0/tests/test_ob2_models.py +188 -0
- openbadgeslib-3.0.0/tests/test_ob2_signer.py +91 -0
- openbadgeslib-3.0.0/tests/test_ob2_verifier.py +233 -0
- openbadgeslib-2.0.0/openbadgeslib/signer.py +0 -4
- openbadgeslib-2.0.0/openbadgeslib/verifier.py +0 -4
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/LICENSE.txt +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/MANIFEST.in +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/docs/README.md +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/_jws/__init__.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/_jws/exceptions.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/_jws/utils.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/baking.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/confparser.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/errors.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/keys.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/logs.py +0 -0
- {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/__init__.py +0 -0
- {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/badge.py +0 -0
- {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/signer.py +0 -0
- {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/verifier.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/__init__.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/credential.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/did.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/signer.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/status.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/verifier.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_init.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/py.typed +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/dependency_links.txt +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/entry_points.txt +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/requires.txt +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/top_level.txt +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/pyproject.toml +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/setup.cfg +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/config1.ini +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/conftest.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/images/sample1.png +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/images/sample1.svg +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/images/userimage01.svg +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/logo Python Espan/314/203a.svg" +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/logo Python Espa/303/261a.svg" +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/runtests.sh +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_confparser.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_docs.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_eddsa.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_jws.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_key_operation.py +0 -0
- /openbadgeslib-2.0.0/tests/test_signer_operation.py → /openbadgeslib-3.0.0/tests/test_ob1_signer.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_credential.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_did.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_signer.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_status.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_verifier.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_sign_ecc.pem +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_sign_rsa.pem +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_util.py +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_verify_ecc.pem +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_verify_rsa.pem +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/withoutxmlheader.svg +0 -0
- {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/withxmlheader.svg +0 -0
|
@@ -4,6 +4,45 @@ OpenBadgesLib - Changelog
|
|
|
4
4
|
Newest first. Dates are ISO 8601 (YYYY-MM-DD).
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
* v3.0.0 - 2026-07-01
|
|
8
|
+
|
|
9
|
+
- BREAKING: the pre-2.0 wire format previously shipped as `-V 2` is relabelled
|
|
10
|
+
OpenBadges 1.0 (`-V 1`) and frozen in the new `openbadgeslib.ob1` package (no
|
|
11
|
+
@context/type, a `uid`, a `verify` object, string `hashed`, Unix-timestamp
|
|
12
|
+
dates). `from openbadgeslib.ob2 import Signer/Verifier/Badge` no longer
|
|
13
|
+
resolves — import from `openbadgeslib.ob1` (the top-level
|
|
14
|
+
`openbadgeslib.signer` / `verifier` / `badge` shims still work).
|
|
15
|
+
|
|
16
|
+
- BREAKING: the default `-V` is now `3` (was `2`) for openbadges-signer,
|
|
17
|
+
-verifier, -publish and -keygenerator. Pass `-V 2` / `-V 1` explicitly for
|
|
18
|
+
the older generations.
|
|
19
|
+
|
|
20
|
+
- feat(ob2): new strict, spec-conformant Open Badges 2.0 implementation
|
|
21
|
+
(`openbadgeslib.ob2`). Assertions are valid JSON-LD Badge Objects with
|
|
22
|
+
`@context`, `type`, an IRI `id` (`urn:uuid:` for signed, the hosting URL for
|
|
23
|
+
hosted), a boolean `hashed`, ISO 8601 dates, and a `verification` object.
|
|
24
|
+
New `OB2Signer`, `OB2Verifier`, and dataclasses `Assertion`, `BadgeClass`,
|
|
25
|
+
`Profile`, `CryptographicKey`, `RevocationList`.
|
|
26
|
+
|
|
27
|
+
- feat(ob2): real HostedBadge verification — the assertion is fetched from its
|
|
28
|
+
own `id` over HTTPS and scope-checked against the issuer origin (default
|
|
29
|
+
same-origin, or the issuer's `startsWith` / `allowedOrigins`); the baked JWS
|
|
30
|
+
is non-gating defence-in-depth. Select it with `openbadges-signer -V 2 -H`.
|
|
31
|
+
|
|
32
|
+
- feat(ob2): SignedBadge verification resolves `verification.creator` to a
|
|
33
|
+
published `CryptographicKey` and checks its `owner` / `publicKey` back-link
|
|
34
|
+
to the issuer Profile.
|
|
35
|
+
|
|
36
|
+
- feat(publish): `openbadges-publish -V 2` emits conformant hosted metadata —
|
|
37
|
+
an issuer Profile with a `publicKey` array, a `BadgeClass` and a
|
|
38
|
+
`CryptographicKey` (`key.json`) per badge, and a `RevocationList`.
|
|
39
|
+
|
|
40
|
+
- feat(config): new optional badge keys `crypto_key` and
|
|
41
|
+
`hosted_assertions_base` for the OB 2.0 signed / hosted flows.
|
|
42
|
+
|
|
43
|
+
- OpenBadges 3.0 is unchanged.
|
|
44
|
+
|
|
45
|
+
|
|
7
46
|
* v2.0.0 - 2026-07-01
|
|
8
47
|
|
|
9
48
|
- BREAKING (OB3): OpenBadges 3.0 credentials are now secured with the native
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openbadgeslib
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: A library to sign and verify OpenBadges
|
|
5
5
|
Author-email: Luis González Fernández <luisgf@luisgf.es>, Jesús Cea Avión <jcea@jcea.es>
|
|
6
6
|
License: LGPLv3
|
|
@@ -48,12 +48,13 @@ Dynamic: license-file
|
|
|
48
48
|
|
|
49
49
|
A Python library and CLI for signing and verifying
|
|
50
50
|
[Open Badges](https://www.imsglobal.org/activity/digital-badges) embedded in SVG
|
|
51
|
-
and PNG image files. It supports
|
|
52
|
-
|
|
51
|
+
and PNG image files. It supports strict **OpenBadges 2.0** (JWS / hosted
|
|
52
|
+
assertions) and **OpenBadges 3.0** (W3C Verifiable Credentials / JWT-VC), plus a
|
|
53
|
+
frozen **OpenBadges 1.0** legacy format — selected with `-V {1,2,3}` (default `3`).
|
|
53
54
|
|
|
54
55
|
## Features
|
|
55
56
|
|
|
56
|
-
- Sign badge images (SVG and PNG)
|
|
57
|
+
- Sign badge images (SVG and PNG) as strict OB 2.0 JWS / hosted assertions (with a frozen OB 1.0 legacy format)
|
|
57
58
|
- Issue and verify OpenBadges 3.0 JWT-VC credentials
|
|
58
59
|
- Bake OB 3.0 JWT tokens into SVG and PNG badge images
|
|
59
60
|
- RSA 2048-bit (RS256), ECC NIST P-256 (ES256), and Ed25519 (EdDSA) key support
|
|
@@ -93,58 +94,52 @@ openbadges-init ./config/
|
|
|
93
94
|
# 2. Generate a key pair for a badge
|
|
94
95
|
openbadges-keygenerator -c ./config/config.ini -g 1
|
|
95
96
|
|
|
96
|
-
# 3a. Sign a badge — OpenBadges
|
|
97
|
+
# 3a. Sign a badge — OpenBadges 3.0 (default)
|
|
97
98
|
openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E
|
|
98
99
|
|
|
99
|
-
# 3b. Sign a badge — OpenBadges
|
|
100
|
-
openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E -V
|
|
100
|
+
# 3b. Sign a badge — strict OpenBadges 2.0
|
|
101
|
+
openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E -V 2
|
|
101
102
|
|
|
102
|
-
# 4a. Verify — OpenBadges
|
|
103
|
+
# 4a. Verify — OpenBadges 3.0
|
|
103
104
|
openbadges-verifier -i /tmp/badge_1_recipient@example.com.svg \
|
|
104
|
-
-r recipient@example.com -
|
|
105
|
+
-r recipient@example.com -V 3 -k ./config/keys/verify_rsa_key_1.pem
|
|
105
106
|
|
|
106
|
-
# 4b. Verify — OpenBadges
|
|
107
|
+
# 4b. Verify — strict OpenBadges 2.0 (pin a trusted key with -l/--local or -k/--pubkey)
|
|
107
108
|
openbadges-verifier -i /tmp/badge_1_recipient@example.com.svg \
|
|
108
|
-
-r recipient@example.com -V
|
|
109
|
+
-r recipient@example.com -V 2 -l 1
|
|
109
110
|
```
|
|
110
111
|
|
|
111
112
|
See the [Quick Start](https://github.com/luisgf/openbadgeslib/wiki/Quick-Start)
|
|
112
113
|
and [CLI Reference](https://github.com/luisgf/openbadgeslib/wiki/CLI-Reference)
|
|
113
114
|
wiki pages for the full walkthrough and every flag.
|
|
114
115
|
|
|
115
|
-
## Using the library — OpenBadges 2.0
|
|
116
|
+
## Using the library — OpenBadges 2.0 (strict)
|
|
116
117
|
|
|
117
118
|
```python
|
|
118
|
-
from
|
|
119
|
-
from openbadgeslib.
|
|
119
|
+
from datetime import datetime, timezone
|
|
120
|
+
from openbadgeslib.ob2 import OB2Signer, Assertion, IdentityObject, Verification
|
|
120
121
|
|
|
121
122
|
with open('sign.pem', 'rb') as f:
|
|
122
123
|
priv_pem = f.read()
|
|
123
|
-
with open('verify.pem', 'rb') as f:
|
|
124
|
-
pub_pem = f.read()
|
|
125
124
|
with open('badge.svg', 'rb') as f:
|
|
126
125
|
image = f.read()
|
|
127
126
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
image_url='https://example.com/badge.svg',
|
|
135
|
-
criteria_url='https://example.com/criteria.html',
|
|
136
|
-
json_url='https://example.com/badge.json',
|
|
137
|
-
verify_key_url='https://example.com/verify.pem',
|
|
138
|
-
key_type=KeyType.RSA,
|
|
139
|
-
privkey_pem=priv_pem,
|
|
140
|
-
pubkey_pem=pub_pem,
|
|
127
|
+
assertion = Assertion(
|
|
128
|
+
recipient=IdentityObject.create('recipient@example.com', salt='s4lt3d'),
|
|
129
|
+
badge='https://example.com/badge_1/badge.json',
|
|
130
|
+
verification=Verification(type='SignedBadge',
|
|
131
|
+
creator='https://example.com/badge_1/key.json'),
|
|
132
|
+
issued_on=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
141
133
|
)
|
|
142
134
|
|
|
143
|
-
signer =
|
|
144
|
-
|
|
145
|
-
|
|
135
|
+
signer = OB2Signer(privkey_pem=priv_pem, algorithm='RS256')
|
|
136
|
+
baked_svg = signer.sign_into_svg(assertion, image)
|
|
137
|
+
with open('/tmp/signed_badge.svg', 'wb') as f:
|
|
138
|
+
f.write(baked_svg)
|
|
146
139
|
```
|
|
147
140
|
|
|
141
|
+
For the frozen OpenBadges 1.0 legacy API (`Badge` / `Signer` / `Verifier`), import from `openbadgeslib.ob1` instead.
|
|
142
|
+
|
|
148
143
|
## Using the library — OpenBadges 3.0 (JWT-VC)
|
|
149
144
|
|
|
150
145
|
```python
|
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
A Python library and CLI for signing and verifying
|
|
9
9
|
[Open Badges](https://www.imsglobal.org/activity/digital-badges) embedded in SVG
|
|
10
|
-
and PNG image files. It supports
|
|
11
|
-
|
|
10
|
+
and PNG image files. It supports strict **OpenBadges 2.0** (JWS / hosted
|
|
11
|
+
assertions) and **OpenBadges 3.0** (W3C Verifiable Credentials / JWT-VC), plus a
|
|
12
|
+
frozen **OpenBadges 1.0** legacy format — selected with `-V {1,2,3}` (default `3`).
|
|
12
13
|
|
|
13
14
|
## Features
|
|
14
15
|
|
|
15
|
-
- Sign badge images (SVG and PNG)
|
|
16
|
+
- Sign badge images (SVG and PNG) as strict OB 2.0 JWS / hosted assertions (with a frozen OB 1.0 legacy format)
|
|
16
17
|
- Issue and verify OpenBadges 3.0 JWT-VC credentials
|
|
17
18
|
- Bake OB 3.0 JWT tokens into SVG and PNG badge images
|
|
18
19
|
- RSA 2048-bit (RS256), ECC NIST P-256 (ES256), and Ed25519 (EdDSA) key support
|
|
@@ -52,58 +53,52 @@ openbadges-init ./config/
|
|
|
52
53
|
# 2. Generate a key pair for a badge
|
|
53
54
|
openbadges-keygenerator -c ./config/config.ini -g 1
|
|
54
55
|
|
|
55
|
-
# 3a. Sign a badge — OpenBadges
|
|
56
|
+
# 3a. Sign a badge — OpenBadges 3.0 (default)
|
|
56
57
|
openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E
|
|
57
58
|
|
|
58
|
-
# 3b. Sign a badge — OpenBadges
|
|
59
|
-
openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E -V
|
|
59
|
+
# 3b. Sign a badge — strict OpenBadges 2.0
|
|
60
|
+
openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E -V 2
|
|
60
61
|
|
|
61
|
-
# 4a. Verify — OpenBadges
|
|
62
|
+
# 4a. Verify — OpenBadges 3.0
|
|
62
63
|
openbadges-verifier -i /tmp/badge_1_recipient@example.com.svg \
|
|
63
|
-
-r recipient@example.com -
|
|
64
|
+
-r recipient@example.com -V 3 -k ./config/keys/verify_rsa_key_1.pem
|
|
64
65
|
|
|
65
|
-
# 4b. Verify — OpenBadges
|
|
66
|
+
# 4b. Verify — strict OpenBadges 2.0 (pin a trusted key with -l/--local or -k/--pubkey)
|
|
66
67
|
openbadges-verifier -i /tmp/badge_1_recipient@example.com.svg \
|
|
67
|
-
-r recipient@example.com -V
|
|
68
|
+
-r recipient@example.com -V 2 -l 1
|
|
68
69
|
```
|
|
69
70
|
|
|
70
71
|
See the [Quick Start](https://github.com/luisgf/openbadgeslib/wiki/Quick-Start)
|
|
71
72
|
and [CLI Reference](https://github.com/luisgf/openbadgeslib/wiki/CLI-Reference)
|
|
72
73
|
wiki pages for the full walkthrough and every flag.
|
|
73
74
|
|
|
74
|
-
## Using the library — OpenBadges 2.0
|
|
75
|
+
## Using the library — OpenBadges 2.0 (strict)
|
|
75
76
|
|
|
76
77
|
```python
|
|
77
|
-
from
|
|
78
|
-
from openbadgeslib.
|
|
78
|
+
from datetime import datetime, timezone
|
|
79
|
+
from openbadgeslib.ob2 import OB2Signer, Assertion, IdentityObject, Verification
|
|
79
80
|
|
|
80
81
|
with open('sign.pem', 'rb') as f:
|
|
81
82
|
priv_pem = f.read()
|
|
82
|
-
with open('verify.pem', 'rb') as f:
|
|
83
|
-
pub_pem = f.read()
|
|
84
83
|
with open('badge.svg', 'rb') as f:
|
|
85
84
|
image = f.read()
|
|
86
85
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
image_url='https://example.com/badge.svg',
|
|
94
|
-
criteria_url='https://example.com/criteria.html',
|
|
95
|
-
json_url='https://example.com/badge.json',
|
|
96
|
-
verify_key_url='https://example.com/verify.pem',
|
|
97
|
-
key_type=KeyType.RSA,
|
|
98
|
-
privkey_pem=priv_pem,
|
|
99
|
-
pubkey_pem=pub_pem,
|
|
86
|
+
assertion = Assertion(
|
|
87
|
+
recipient=IdentityObject.create('recipient@example.com', salt='s4lt3d'),
|
|
88
|
+
badge='https://example.com/badge_1/badge.json',
|
|
89
|
+
verification=Verification(type='SignedBadge',
|
|
90
|
+
creator='https://example.com/badge_1/key.json'),
|
|
91
|
+
issued_on=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
100
92
|
)
|
|
101
93
|
|
|
102
|
-
signer =
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
signer = OB2Signer(privkey_pem=priv_pem, algorithm='RS256')
|
|
95
|
+
baked_svg = signer.sign_into_svg(assertion, image)
|
|
96
|
+
with open('/tmp/signed_badge.svg', 'wb') as f:
|
|
97
|
+
f.write(baked_svg)
|
|
105
98
|
```
|
|
106
99
|
|
|
100
|
+
For the frozen OpenBadges 1.0 legacy API (`Badge` / `Signer` / `Verifier`), import from `openbadgeslib.ob1` instead.
|
|
101
|
+
|
|
107
102
|
## Using the library — OpenBadges 3.0 (JWT-VC)
|
|
108
103
|
|
|
109
104
|
```python
|
|
@@ -21,14 +21,23 @@
|
|
|
21
21
|
License along with this library.
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
# ── OpenBadges
|
|
25
|
-
|
|
24
|
+
# ── OpenBadges 1.0 (legacy) ─────────────────────────────────────────────────────
|
|
25
|
+
# The classes formerly exposed as "OpenBadges 2.0" are the pre-2.0 wire format
|
|
26
|
+
# (no @context/type, uid, verify{}, Unix timestamps). They are re-exported here
|
|
27
|
+
# unchanged for backward compatibility; the strict OB 2.0 implementation lives
|
|
28
|
+
# in openbadgeslib.ob2 (OB2Signer/OB2Verifier).
|
|
29
|
+
from .ob1 import ( # noqa: F401
|
|
26
30
|
Signer, Verifier, VerifyInfo,
|
|
27
31
|
Badge, BadgeSigned, Assertion,
|
|
28
32
|
BadgeStatus, BadgeImgType, BadgeType,
|
|
29
33
|
extract_svg_assertion, extract_png_assertion,
|
|
30
34
|
)
|
|
31
35
|
|
|
36
|
+
# ── OpenBadges 2.0 (strict) ──────────────────────────────────────────────────
|
|
37
|
+
from .ob2 import ( # noqa: F401
|
|
38
|
+
OB2Signer, OB2Verifier, OB2VerificationError,
|
|
39
|
+
)
|
|
40
|
+
|
|
32
41
|
# ── OpenBadges 3.0 ─────────────────────────────────────────────────────────────
|
|
33
42
|
from .ob3 import ( # noqa: F401
|
|
34
43
|
OB3Signer, OB3Verifier, OB3VerificationError,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"""OpenBadges
|
|
2
|
-
from .
|
|
1
|
+
"""OpenBadges 1.0 (legacy) badge objects — compatibility shim, re-exports from openbadgeslib.ob1."""
|
|
2
|
+
from .ob1.badge import (
|
|
3
3
|
BadgeStatus, BadgeImgType, BadgeType,
|
|
4
4
|
Assertion, Badge, BadgeSigned,
|
|
5
5
|
extract_svg_assertion, extract_png_assertion,
|
|
@@ -42,6 +42,12 @@ image = https://www.issuer.badge/issuer/badge_1/badge1.svg
|
|
|
42
42
|
criteria = https://www.issuer.badge/issuer/badge_1/criteria.html
|
|
43
43
|
verify_key = https://www.issuer.badge/issuer/badge_1/verify_rsa_key.pem
|
|
44
44
|
badge = https://www.issuer.badge/issuer/badge_1/badge.json
|
|
45
|
+
; OpenBadges 2.0 (-V 2): URL of this badge's CryptographicKey JSON-LD document
|
|
46
|
+
; (published by openbadges-publish as <badge>/key.json). Used as verification.creator.
|
|
47
|
+
crypto_key = https://www.issuer.badge/issuer/badge_1/key.json
|
|
48
|
+
; OpenBadges 2.0 hosted mode (openbadges-signer -V 2 -H): base URL under which
|
|
49
|
+
; per-recipient hosted assertion JSON files are published for verification.
|
|
50
|
+
hosted_assertions_base = https://www.issuer.badge/issuer/badge_1/assertions/
|
|
45
51
|
private_key = ${paths:base_key}/sign_rsa_key_1.pem
|
|
46
52
|
public_key = ${paths:base_key}/verify_rsa_key_1.pem
|
|
47
53
|
; key_type selects the algorithm for openbadges-keygenerator: RSA (default), ECC, or ED25519
|
|
@@ -58,6 +64,8 @@ image = https://www.issuer.badge/issuer/badge_2/badge2.svg
|
|
|
58
64
|
criteria = https://www.issuer.badge/issuer/badge_2/criteria.html
|
|
59
65
|
verify_key = https://www.issuer.badge/issuer/badge_2/verify_rsa_key.pem
|
|
60
66
|
badge = https://www.issuer.badge/issuer/badge_2/badge.json
|
|
67
|
+
crypto_key = https://www.issuer.badge/issuer/badge_2/key.json
|
|
68
|
+
hosted_assertions_base = https://www.issuer.badge/issuer/badge_2/assertions/
|
|
61
69
|
private_key = ${paths:base_key}/sign_rsa_key_2.pem
|
|
62
70
|
public_key = ${paths:base_key}/verify_rsa_key_2.pem
|
|
63
71
|
key_type = RSA
|
|
@@ -30,7 +30,7 @@ from email.mime.multipart import MIMEMultipart
|
|
|
30
30
|
from email.mime.text import MIMEText
|
|
31
31
|
from email.utils import formatdate
|
|
32
32
|
from email.header import Header
|
|
33
|
-
from .
|
|
33
|
+
from .ob1 import BadgeImgType
|
|
34
34
|
from .errors import BadgeImgFormatUnsupported
|
|
35
35
|
|
|
36
36
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OpenBadges Library
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2014-2026, Luis González Fernández, luisgf@luisgf.es
|
|
5
|
+
Copyright (c) 2014-2026, Jesús Cea Avión, jcea@jcea.es
|
|
6
|
+
|
|
7
|
+
All rights reserved.
|
|
8
|
+
|
|
9
|
+
This library is free software; you can redistribute it and/or
|
|
10
|
+
modify it under the terms of the GNU Lesser General Public
|
|
11
|
+
License as published by the Free Software Foundation; either
|
|
12
|
+
version 3.0 of the License, or (at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This library is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
17
|
+
Lesser General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU Lesser General Public
|
|
20
|
+
License along with this library.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
# Strict OpenBadges 2.0 (JWS-signed / hosted Assertions with conformant
|
|
24
|
+
# JSON-LD Badge Objects). The legacy pre-2.0 format lives in openbadgeslib.ob1.
|
|
25
|
+
|
|
26
|
+
from .models import (
|
|
27
|
+
OB2_CONTEXT,
|
|
28
|
+
Assertion, IdentityObject, Verification,
|
|
29
|
+
BadgeClass, Profile, CryptographicKey, RevocationList,
|
|
30
|
+
hash_identity,
|
|
31
|
+
)
|
|
32
|
+
from .signer import OB2Signer
|
|
33
|
+
from .verifier import OB2Verifier, OB2VerificationError
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
'OB2_CONTEXT',
|
|
37
|
+
'Assertion', 'IdentityObject', 'Verification',
|
|
38
|
+
'BadgeClass', 'Profile', 'CryptographicKey', 'RevocationList',
|
|
39
|
+
'hash_identity',
|
|
40
|
+
'OB2Signer', 'OB2Verifier', 'OB2VerificationError',
|
|
41
|
+
]
|