-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(tokens): add secure token generator/validator with entropy + length caps #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
5576a59
feat(tokens): add secure token generator/validator with entropy + len…
hyp3rd e24d5db
feat(encoding): add Base64/Hex/JSON codecs with validation & limits
hyp3rd b918b24
Update pkg/tokens/tokens.go
hyp3rd 0cd9f25
Update pkg/tokens/tokens.go
hyp3rd c4c8aeb
Update pkg/tokens/tokens_test.go
hyp3rd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # These are supported funding model platforms | ||
|
|
||
| github: [hyp3rd] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| package encoding | ||
|
|
||
| import ( | ||
| "encoding/base64" | ||
| "strings" | ||
| ) | ||
|
|
||
| const ( | ||
| base64DefaultMaxLength = 4096 | ||
| ) | ||
|
|
||
| // Base64Encoding identifies a base64 encoding variant. | ||
| type Base64Encoding int | ||
|
|
||
| const ( | ||
| // Base64EncodingRawURL uses URL-safe base64 without padding. | ||
| Base64EncodingRawURL Base64Encoding = iota | ||
| // Base64EncodingRawStd uses standard base64 without padding. | ||
| Base64EncodingRawStd | ||
| // Base64EncodingURL uses URL-safe base64 with padding. | ||
| Base64EncodingURL | ||
| // Base64EncodingStd uses standard base64 with padding. | ||
| Base64EncodingStd | ||
| ) | ||
|
|
||
| // Base64Option configures base64 encoding and decoding. | ||
| type Base64Option func(*base64Options) error | ||
|
|
||
| type base64Options struct { | ||
| encoding *base64.Encoding | ||
| maxLength int | ||
| } | ||
|
|
||
| // EncodeBase64 encodes data using the configured base64 encoding. | ||
| func EncodeBase64(data []byte, opts ...Base64Option) (string, error) { | ||
| cfg, err := resolveBase64Options(opts) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
| if cfg.encoding.EncodedLen(len(data)) > cfg.maxLength { | ||
| return "", ErrBase64TooLong | ||
| } | ||
|
|
||
| return cfg.encoding.EncodeToString(data), nil | ||
| } | ||
|
|
||
| // DecodeBase64 decodes a base64-encoded string. | ||
| func DecodeBase64(input string, opts ...Base64Option) ([]byte, error) { | ||
| cfg, err := resolveBase64Options(opts) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| if strings.TrimSpace(input) == "" { | ||
| return nil, ErrBase64Empty | ||
| } | ||
|
|
||
| if containsWhitespace(input) { | ||
| return nil, ErrBase64Invalid | ||
| } | ||
|
|
||
| if len(input) > cfg.maxLength { | ||
| return nil, ErrBase64TooLong | ||
| } | ||
|
|
||
| decoded, err := cfg.encoding.DecodeString(input) | ||
| if err != nil { | ||
| return nil, ErrBase64Invalid | ||
| } | ||
|
|
||
| return decoded, nil | ||
| } | ||
|
|
||
| // WithBase64Encoding sets the base64 encoding variant. | ||
| func WithBase64Encoding(encoding Base64Encoding) Base64Option { | ||
| return func(cfg *base64Options) error { | ||
| enc, err := base64Encoding(encoding) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| cfg.encoding = enc | ||
|
|
||
| return nil | ||
| } | ||
| } | ||
|
|
||
| // WithBase64MaxLength sets the maximum accepted base64 string length. | ||
| func WithBase64MaxLength(maxLength int) Base64Option { | ||
| return func(cfg *base64Options) error { | ||
| if maxLength <= 0 { | ||
| return ErrInvalidBase64Config | ||
| } | ||
|
|
||
| cfg.maxLength = maxLength | ||
|
|
||
| return nil | ||
| } | ||
| } | ||
|
|
||
| func resolveBase64Options(opts []Base64Option) (base64Options, error) { | ||
| cfg := base64Options{ | ||
| encoding: base64.RawURLEncoding, | ||
| maxLength: base64DefaultMaxLength, | ||
| } | ||
|
|
||
| for _, opt := range opts { | ||
| if opt == nil { | ||
| continue | ||
| } | ||
|
|
||
| err := opt(&cfg) | ||
| if err != nil { | ||
| return base64Options{}, err | ||
| } | ||
| } | ||
|
|
||
| err := validateBase64Options(cfg) | ||
| if err != nil { | ||
| return base64Options{}, err | ||
| } | ||
|
|
||
| return cfg, nil | ||
| } | ||
|
|
||
| func validateBase64Options(cfg base64Options) error { | ||
| if cfg.encoding == nil || cfg.maxLength <= 0 { | ||
| return ErrInvalidBase64Config | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func base64Encoding(encoding Base64Encoding) (*base64.Encoding, error) { | ||
| switch encoding { | ||
| case Base64EncodingRawURL: | ||
| return base64.RawURLEncoding, nil | ||
| case Base64EncodingRawStd: | ||
| return base64.RawStdEncoding, nil | ||
| case Base64EncodingURL: | ||
| return base64.URLEncoding, nil | ||
| case Base64EncodingStd: | ||
| return base64.StdEncoding, nil | ||
| default: | ||
| return nil, ErrInvalidBase64Config | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| // Package encoding provides bounded encoding and decoding helpers. | ||
| package encoding |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example code silently ignores errors from Generate() and Validate() using blank identifier (_). This sets a poor example for users, especially in a security-focused library. Even in example code, errors from token generation and validation should be properly handled or at least demonstrated with proper error handling patterns.