@@ -19,21 +19,14 @@ A secure, Rust library for generating and validating API keys with built-in secu
1919
2020## Quick Start
2121
22- ### Installation
23-
24- ``` toml
25- [dependencies ]
26- api-keys-simplified = " 0.1"
27- ```
28-
2922### Basic Usage
3023
3124``` rust
32- use api_keys_simplified :: {ApiKeyManager , Environment , KeyConfig , HashConfig };
25+ use api_keys_simplified :: {ApiKeyManagerV0 , Environment , ExposeSecret , KeyStatus , SecureString };
3326
3427fn main () -> Result <(), Box <dyn std :: error :: Error >> {
3528 // 1. Initialize with checksum (out of the box DoS protection)
36- let manager = ApiKeyManager :: init_default_config (" gpmcp_sk" )? ;
29+ let manager = ApiKeyManagerV0 :: init_default_config (" gpmcp_sk" )? ;
3730
3831 // 2. Generate a new API key
3932 let api_key = manager . generate (Environment :: production ())? ;
@@ -45,7 +38,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
4538 database :: save_user_key_hash (user_id , api_key . hash ())? ;
4639
4740 // 5. Later: verify an incoming key (checksum validated first!)
48- let provided_key = request . headers (). get (" Authorization" )? . replace (" Bearer " , "" );
41+ let provided_key_str = request . headers (). get (" Authorization" )? . replace (" Bearer " , "" );
42+ let provided_key = SecureString :: from (provided_key_str );
4943 let stored_hash = database :: get_user_key_hash (user_id )? ;
5044
5145 match manager . verify (& provided_key , & stored_hash )? {
@@ -156,10 +150,14 @@ Common API key security mistakes:
156150### Best Practices
157151
158152``` rust
159- use api_keys_simplified :: {ApiKeyManager , Environment , KeyConfig , HashConfig , KeyStatus };
153+ use api_keys_simplified :: {
154+ ApiKeyManagerV0 , Environment , ExposeSecret ,
155+ KeyStatus , SecureString , ApiKey , Hash
156+ };
157+ use chrono :: {Duration , Utc };
160158
161159// ✅ Checksums enabled by default (DoS protection - use .disable_checksum() to turn off)
162- let manager = ApiKeyManager :: init_default_config (" myapp_sk" )? ;
160+ let manager = ApiKeyManagerV0 :: init_default_config (" myapp_sk" )? ;
163161
164162// ✅ Never log keys (auto-redacted)
165163let key = manager . generate (Environment :: production ())? ;
@@ -171,11 +169,11 @@ db.save(key.hash()); // Store hash only
171169
172170// ✅ Always use HTTPS
173171let response = client . get (" https://api.example.com" )
174- . header (" Authorization" , format! (" Bearer {}" ,key . key (). expose_secret ()))
172+ . header (" Authorization" , format! (" Bearer {}" , key . key (). expose_secret ()))
175173 . send ()? ;
176174
177175// ✅ Implement key rotation
178- fn rotate_key (manager : & ApiKeyManager , user_id : u64 ) -> Result <ApiKey > {
176+ fn rotate_key (manager : & ApiKeyManagerV0 , user_id : u64 ) -> Result <ApiKey < Hash >, Box < dyn std :: error :: Error > > {
179177 let new_key = manager . generate (Environment :: production ())? ;
180178 db . revoke_old_keys (user_id )? ;
181179 db . save_new_hash (user_id , new_key . hash ())? ;
@@ -188,14 +186,18 @@ let trial_key = manager.generate_with_expiry(Environment::production(), trial_ex
188186db . save (user_id , trial_key . hash ())? ;
189187
190188// ✅ Implement key revocation for compromised keys
191- fn revoke_key (user_id : u64 , key_hash : & str ) -> Result <()> {
189+ fn revoke_key (user_id : u64 , key_hash : & str ) -> Result <(), Box < dyn std :: error :: Error > > {
192190 // Mark hash as revoked in database
193191 db . mark_revoked (user_id , key_hash )? ;
194192 Ok (())
195193}
196194
197195// ✅ Check revocation status during verification
198- fn verify_with_revocation (manager : & ApiKeyManager , key : & SecureString , user_id : u64 ) -> Result <bool > {
196+ fn verify_with_revocation (
197+ manager : & ApiKeyManagerV0 ,
198+ key : & SecureString ,
199+ user_id : u64
200+ ) -> Result <bool , Box <dyn std :: error :: Error >> {
199201 let stored_hash = db . get_user_key_hash (user_id )? ;
200202
201203 // Check if key is revoked first (fast database check)
@@ -214,7 +216,9 @@ fn verify_with_revocation(manager: &ApiKeyManager, key: &SecureString, user_id:
214216if rate_limiter . check (ip_address ). is_err () {
215217 return Err (" Too many failed attempts" );
216218}
217- manager . verify (provided_key , stored_hash )? ;
219+ // Convert incoming string to SecureString
220+ let incoming_key = SecureString :: from (request_key_string . to_string ());
221+ manager . verify (& incoming_key , & stored_hash )? ;
218222```
219223
220224## Performance
@@ -236,14 +240,20 @@ cargo test --features expensive_tests # Include timing analysis
236240## Error Handling
237241
238242``` rust
239- use api_keys_simplified :: {ApiKey , Error };
240-
241- match ApiKey :: generate_default ("" , Environment :: production ()) {
242- Ok (key ) => println ! (" Success: {}" , key . key (). expose_secret ()),
243- Err (Error :: InvalidConfig (msg )) => eprintln ! (" Config error: {}" , msg ),
244- Err (Error :: InvalidFormat ) => eprintln ! (" Invalid key format" ),
245- Err (Error :: HashingFailed (msg )) => eprintln ! (" Hashing error: {}" , msg ),
246- Err (e ) => eprintln ! (" Error: {}" , e ),
243+ use api_keys_simplified :: {ApiKeyManagerV0 , Environment , Error , ExposeSecret };
244+
245+ match ApiKeyManagerV0 :: init_default_config (" sk" ) {
246+ Ok (manager ) => {
247+ match manager . generate (Environment :: production ()) {
248+ Ok (key ) => println! (" Success: {}" , key . key (). expose_secret ()),
249+ Err (Error :: OperationFailed (op_err )) => {
250+ // Operation errors contain details (use {:?} in logs for debugging)
251+ eprintln! (" Operation error: {}" , op_err );
252+ }
253+ Err (e ) => eprintln! (" Generation error: {}" , e ),
254+ }
255+ }
256+ Err (e ) => eprintln! (" Init error: {}" , e ),
247257}
248258```
249259
0 commit comments