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.
Files changed (85) hide show
  1. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/Changelog.txt +39 -0
  2. {openbadgeslib-2.0.0/openbadgeslib.egg-info → openbadgeslib-3.0.0}/PKG-INFO +27 -32
  3. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/README.md +26 -31
  4. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/__init__.py +11 -2
  5. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/badge.py +2 -2
  6. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/config.ini.example +8 -0
  7. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/mail.py +1 -1
  8. openbadgeslib-3.0.0/openbadgeslib/ob2/__init__.py +41 -0
  9. openbadgeslib-3.0.0/openbadgeslib/ob2/models.py +376 -0
  10. openbadgeslib-3.0.0/openbadgeslib/ob2/signer.py +108 -0
  11. openbadgeslib-3.0.0/openbadgeslib/ob2/verifier.py +363 -0
  12. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_keygenerator.py +3 -3
  13. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_publish.py +95 -2
  14. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_signer.py +95 -6
  15. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_verifier.py +93 -8
  16. openbadgeslib-3.0.0/openbadgeslib/signer.py +4 -0
  17. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/util.py +1 -1
  18. openbadgeslib-3.0.0/openbadgeslib/verifier.py +4 -0
  19. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0/openbadgeslib.egg-info}/PKG-INFO +27 -32
  20. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/SOURCES.txt +12 -4
  21. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_cli_json.py +11 -11
  22. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_cli_smoke.py +29 -29
  23. openbadgeslib-2.0.0/tests/test_badge_io.py → openbadgeslib-3.0.0/tests/test_ob1_badge_io.py +10 -10
  24. openbadgeslib-2.0.0/tests/test_verify_operation.py → openbadgeslib-3.0.0/tests/test_ob1_verifier.py +12 -12
  25. openbadgeslib-3.0.0/tests/test_ob2_cli.py +215 -0
  26. openbadgeslib-3.0.0/tests/test_ob2_models.py +188 -0
  27. openbadgeslib-3.0.0/tests/test_ob2_signer.py +91 -0
  28. openbadgeslib-3.0.0/tests/test_ob2_verifier.py +233 -0
  29. openbadgeslib-2.0.0/openbadgeslib/signer.py +0 -4
  30. openbadgeslib-2.0.0/openbadgeslib/verifier.py +0 -4
  31. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/LICENSE.txt +0 -0
  32. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/MANIFEST.in +0 -0
  33. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/docs/README.md +0 -0
  34. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/_jws/__init__.py +0 -0
  35. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/_jws/exceptions.py +0 -0
  36. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/_jws/utils.py +0 -0
  37. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/baking.py +0 -0
  38. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/confparser.py +0 -0
  39. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/errors.py +0 -0
  40. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/keys.py +0 -0
  41. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/logs.py +0 -0
  42. {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/__init__.py +0 -0
  43. {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/badge.py +0 -0
  44. {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/signer.py +0 -0
  45. {openbadgeslib-2.0.0/openbadgeslib/ob2 → openbadgeslib-3.0.0/openbadgeslib/ob1}/verifier.py +0 -0
  46. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/__init__.py +0 -0
  47. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/credential.py +0 -0
  48. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/did.py +0 -0
  49. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/signer.py +0 -0
  50. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/status.py +0 -0
  51. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/ob3/verifier.py +0 -0
  52. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/openbadges_init.py +0 -0
  53. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib/py.typed +0 -0
  54. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/dependency_links.txt +0 -0
  55. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/entry_points.txt +0 -0
  56. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/requires.txt +0 -0
  57. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/openbadgeslib.egg-info/top_level.txt +0 -0
  58. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/pyproject.toml +0 -0
  59. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/setup.cfg +0 -0
  60. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/config1.ini +0 -0
  61. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/conftest.py +0 -0
  62. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/images/sample1.png +0 -0
  63. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/images/sample1.svg +0 -0
  64. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/images/userimage01.svg +0 -0
  65. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/logo Python Espan/314/203a.svg" +0 -0
  66. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/logo Python Espa/303/261a.svg" +0 -0
  67. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/runtests.sh +0 -0
  68. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_confparser.py +0 -0
  69. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_docs.py +0 -0
  70. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_eddsa.py +0 -0
  71. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_jws.py +0 -0
  72. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_key_operation.py +0 -0
  73. /openbadgeslib-2.0.0/tests/test_signer_operation.py → /openbadgeslib-3.0.0/tests/test_ob1_signer.py +0 -0
  74. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_credential.py +0 -0
  75. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_did.py +0 -0
  76. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_signer.py +0 -0
  77. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_status.py +0 -0
  78. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_ob3_verifier.py +0 -0
  79. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_sign_ecc.pem +0 -0
  80. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_sign_rsa.pem +0 -0
  81. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_util.py +0 -0
  82. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_verify_ecc.pem +0 -0
  83. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/test_verify_rsa.pem +0 -0
  84. {openbadgeslib-2.0.0 → openbadgeslib-3.0.0}/tests/withoutxmlheader.svg +0 -0
  85. {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: 2.0.0
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 both **OpenBadges 2.0** (JWS compact
52
- serialisation) and **OpenBadges 3.0** (W3C Verifiable Credentials / JWT-VC).
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) with a JWS assertion (OB 2.0)
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 2.0 (default)
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 3.0
100
- openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E -V 3
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 2.0 (pin a trusted key with -l/--local or -k/--pubkey)
103
+ # 4a. Verify — OpenBadges 3.0
103
104
  openbadges-verifier -i /tmp/badge_1_recipient@example.com.svg \
104
- -r recipient@example.com -l 1
105
+ -r recipient@example.com -V 3 -k ./config/keys/verify_rsa_key_1.pem
105
106
 
106
- # 4b. Verify — OpenBadges 3.0
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 3 -k ./config/keys/verify_rsa_key_1.pem
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 openbadgeslib.ob2 import Badge, BadgeImgType, BadgeType, Signer
119
- from openbadgeslib.keys import KeyType
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
- badge = Badge(
129
- ini_name='my_badge',
130
- name='My Badge',
131
- description='Awarded for excellence',
132
- image_type=BadgeImgType.SVG,
133
- image=image,
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 = Signer(identity='recipient@example.com', badge_type=BadgeType.SIGNED)
144
- signed = signer.sign_badge(badge)
145
- signed.save_to_file('/tmp/signed_badge.svg')
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 both **OpenBadges 2.0** (JWS compact
11
- serialisation) and **OpenBadges 3.0** (W3C Verifiable Credentials / JWT-VC).
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) with a JWS assertion (OB 2.0)
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 2.0 (default)
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 3.0
59
- openbadges-signer -c ./config/config.ini -b 1 -r recipient@example.com -o /tmp/ -E -V 3
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 2.0 (pin a trusted key with -l/--local or -k/--pubkey)
62
+ # 4a. Verify — OpenBadges 3.0
62
63
  openbadges-verifier -i /tmp/badge_1_recipient@example.com.svg \
63
- -r recipient@example.com -l 1
64
+ -r recipient@example.com -V 3 -k ./config/keys/verify_rsa_key_1.pem
64
65
 
65
- # 4b. Verify — OpenBadges 3.0
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 3 -k ./config/keys/verify_rsa_key_1.pem
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 openbadgeslib.ob2 import Badge, BadgeImgType, BadgeType, Signer
78
- from openbadgeslib.keys import KeyType
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
- badge = Badge(
88
- ini_name='my_badge',
89
- name='My Badge',
90
- description='Awarded for excellence',
91
- image_type=BadgeImgType.SVG,
92
- image=image,
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 = Signer(identity='recipient@example.com', badge_type=BadgeType.SIGNED)
103
- signed = signer.sign_badge(badge)
104
- signed.save_to_file('/tmp/signed_badge.svg')
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 2.0 ─────────────────────────────────────────────────────────────
25
- from .ob2 import ( # noqa: F401
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.0 badge objects — compatibility shim, re-exports from openbadgeslib.ob2."""
2
- from .ob2.badge import (
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 .ob2 import BadgeImgType
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
+ ]