- How do I install christian-riesen/base32 in a Laravel project?
- Run composer require christian-riesen/base32 and you are done. There is no service provider, no facade, no config file and no publishable assets, so nothing needs registering in your Laravel bootstrap. The package is PSR-4 autoloaded under the Base32 namespace, so you simply import Base32\Base32 or Base32\Base32Hex and call the static methods, for example Base32::encode('fooba') which returns MZXW6YTB.
- Does christian-riesen/base32 work with Laravel 9, 10, 11 and 12?
- Yes. The library is framework-agnostic with no Laravel or PSR-7 coupling and no PHP extensions, so it deploys cleanly on the PHP 8.0+ platform that Laravel 9 through 12 already require. Its own PHP constraint is older than that, so you have headroom, but run composer require christian-riesen/base32 --dry-run and composer why-not against your platform pins before committing. Slim and Alpine build images are fine because nothing is compiled.
- Why does Base32::decode() throw InvalidArgumentException in version 2.0?
- Version 2.0 made decoding strictly RFC 4648 conformant, so malformed or non-canonical input is rejected instead of being silently stripped as in 1.x. It throws InvalidArgumentException when the string is lowercase, when its length is not a multiple of 8, when it contains characters outside the alphabet, when padding is misplaced, or when non-zero trailing bits make the encoding non-canonical. In a request path an uncaught throw becomes a 500, so wrap decode calls in a try/catch or validate the input first.
- How do I decode lowercase or space-separated Base32 secrets in PHP?
- Normalize user input before decoding, because 2.0 decoding is case-sensitive and rejects whitespace. A common pattern is $secret = strtoupper(preg_replace('/\s+/', '', $userInput)); and then Base32::decode($secret). Anything produced by Base32::encode() still decodes cleanly, so the normalization step is only needed for externally supplied strings such as TOTP secrets typed by a user.
- What is the difference between Base32 and Base32Hex?
- Both classes implement RFC 4648, but Base32Hex uses the extended hex alphabet from section 7, where the digits 0-9 come before the letters A-V, instead of the standard A-Z2-7 alphabet. The choice depends entirely on what the other system expects, since the two encodings of the same bytes are different strings. The package gives you Base32\Base32 and Base32\Base32Hex with identical encode and decode signatures, so switching is a one-line change.
- Does the package add padding, and can it decode padded Base32 strings?
- On decode, version 2.0 requires correct padding and a length that is a multiple of 8, and it throws InvalidArgumentException when padding is misplaced. Because padding conventions vary between authenticator clients and legacy APIs, verify interop with a spike rather than assuming. If a partner integration depends on padded output, pin that expectation in a test using known RFC 4648 vectors.
- Can I use christian-riesen/base32 for TOTP or two-factor secrets in Laravel?
- This package only encodes and decodes Base32; it does not implement HMAC, HOTP or TOTP itself. It was originally created alongside the author's OTP library and is commonly pulled in transitively by OTP packages, so encode your random secret with Base32::encode(random_bytes(20)) and hand the string to your OTP library. If you decode secrets coming back from users or QR provisioning, normalize case and whitespace first so strict 2.0 decoding does not throw.
- How do I unit test Laravel code that calls the static Base32::encode() method?
- The methods are static, so they cannot be mocked directly. The pragmatic pattern is a small Base32Codec contract bound as a singleton in a service provider, with a thin adapter that delegates to Base32\Base32, so your domain code depends on the interface and you can fake it in tests. For the adapter itself, test against the RFC 4648 vectors, for example encoding fooba to MZXW6YTB, plus a decode failure case asserting InvalidArgumentException.
- Is it already installed in my Laravel app as a transitive dependency?
- It often is, because OTP and two-factor packages chain to it. Run composer show --tree or composer why christian-riesen/base32 to confirm, and composer show --platform to check that the package's PHP constraint does not collide with your platform pins. If it is already in vendor/ transitively, promoting it to a declared requirement is nearly free and strictly reduces risk.
- Is christian-riesen/base32 safe to depend on in production if it has a single maintainer?
- The engineering risk is low: it is MIT licensed, has zero runtime dependencies, a very small code surface and a full set of unit tests against the RFC vectors, so it is effectively vendorable if the project ever stalls. The residual risk is governance, namely bus factor one. Keep it at arm's length behind a Base32Codec interface and adapter so a fork or replacement stays a one-file swap, and pin an explicit version rather than relying on a floating range.