Safeguard
Application Security•

How do you generate secure random values and use crypto in Flutter?

Use Random.secure for tokens and keys, never the default Random, rely on vetted crypto libraries and platform key storage, and ship no secrets in the app.

Safeguard Security Team
4 min read

In Dart and Flutter, use Random.secure() for anything an attacker must not guess: tokens, nonces, salts and keys. The default Random() is not cryptographically secure. Beyond random numbers, use a maintained crypto library, keep keys in platform storage, and assume anything inside the app bundle can be read.

What does Random.secure actually promise?

The Dart API documentation says Random.secure creates a cryptographically secure random number generator, and that if the program cannot provide a secure source of random numbers it throws an UnsupportedError. That failure behavior is useful: you get an error instead of silently weak output.

The ordinary Random() constructor and the seeded Random(seed) form are built for simulations and games. A seeded generator with the same seed produces the same sequence every time, which makes it predictable by design. CWE-338 covers the weakness of using a pseudo-random generator that is not suited to security purposes.

How do you generate a token?

Draw bytes from the secure generator and encode them. For a 32 byte token:

import 'dart:convert';
import 'dart:math';

String newToken([int bytes = 32]) {
  final rng = Random.secure();
  final data = List<int>.generate(bytes, (_) => rng.nextInt(256));
  return base64UrlEncode(data);
}

Thirty-two bytes gives 256 bits of randomness before encoding, which is far beyond guessing. Do not derive tokens from timestamps, user IDs or counters, and do not truncate to a short length for convenience.

What goes wrong in mobile apps?

A constructed example. A Flutter app creates a session nonce with Random().nextInt(1 << 32) and signs requests with a key stored as a string constant. Both choices fail. The nonce space is small and the generator is not designed to resist prediction. The key sits in the compiled bundle, where an attacker can extract strings from the installed package and then forge requests as any user.

The Flutter security documentation frames the broader point: mobile code runs on devices you do not control, so protect data on the device and treat the client as untrusted.

What are the cryptography basics for app developers?

  • Do not write your own ciphers, modes or protocols. Use a maintained library and a standard authenticated mode such as AES-GCM or ChaCha20-Poly1305.
  • Use a fresh random nonce for every encryption with the same key. Reusing a nonce with GCM breaks its security.
  • Keep keys out of source code and assets. Generate them at runtime or fetch them after authentication, and store them with the platform keystore (iOS Keychain, Android Keystore) through a secure storage plugin.
  • Hash passwords on the server with a slow password hashing function such as Argon2id, scrypt or bcrypt, not in the app and not with a plain SHA-2.
  • Use TLS for every network call and do not disable certificate checks in release builds. Consider certificate pinning only with a rotation plan.
  • Never assume values passed in as compile-time defines are hidden: they are compiled into the app.

How do you check an existing app?

Search for Random( and Random.secure across the codebase and dependencies, and decide for each use whether it protects something. Search for string constants that look like keys, then rotate any you find. Review which storage plugin holds tokens and whether data backs up to the cloud unencrypted. Scan dependencies for advisories on every build.

What to do

  1. Replace Random() with Random.secure() wherever the value guards access.
  2. Generate tokens and nonces with enough bytes: at least 16, preferably 32.
  3. Handle UnsupportedError by failing closed.
  4. Remove embedded keys and rotate them.
  5. Use a vetted crypto library and an authenticated encryption mode.
  6. Store keys and tokens in platform secure storage.
  7. Do password hashing on the server.
  8. Add a lint or code review rule against the plain Random in security code.

The Safeguard IDE extensions and CLI can scan for hardcoded secrets in a Flutter repository, and dependency scanning covers pub packages.

Quick check

Is Random(seed) ever fine for security?

No. A seed makes the sequence repeatable, so anyone who knows or guesses the seed can predict every value.

Can I hide an API key in a Flutter build with obfuscation?

Obfuscation raises effort but does not protect a secret. Keep sensitive keys on a server and issue scoped, short-lived tokens to the app.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.