Skip to content
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

Add a CSPRNG (ie. SecureRandom) to the Kotlin StdLib #184

Closed
JLLeitschuh opened this issue Mar 28, 2019 · 22 comments
Closed

Add a CSPRNG (ie. SecureRandom) to the Kotlin StdLib #184

JLLeitschuh opened this issue Mar 28, 2019 · 22 comments
Labels

Comments

@JLLeitschuh
Copy link

JLLeitschuh commented Mar 28, 2019

Problem

Kotlin 1.3 added support for an official Koltin Random which is awesome!

Without an official Cryptographically secure pseudorandom number generator (ie. SecureRandom) Kotlin can't by default support creating truly random numbers without platform-specific implementations.

Dan Kaminsky did an interesting talk at Defcon about why more standard libraries should offer CSPRNG by default. So many software security bugs have been caused purely because someone on the implementation side goofed and used a predictable Random number generator.

(The part covering random number generators starts at 17 min)
https://youtu.be/xneBjc8z0DE?t=1021

Java and Kotlin's Random is a Pseudo Random Number Generator (PRNG). (A "linear congruential PRNG").
This means the next value can easily be calculated if you have two previous values.

https://crypto.stackexchange.com/questions/51686/how-to-determine-the-next-number-from-javas-random-method

According to @ilya-g:

The default implementation of Random is using a pseudo-random source whichever available in the platform (e.g. ThreadLocalRandom or java.util.Random in JVM, Math.random in JS etc).
The seeded implementation uses XORWOW algorithm. Neither of them are cryptographically secure.

This is the original discussion thread on slack from October 29th, 2018:
https://kotlinlang.slack.com/archives/C0922A726/p1540830858324300

Solution

Add official support for a CSPRNG to the Kotlin standard library.

JVM

This could just be implemented as a decorator over Java's SecureRandom

Native

For Linux/Unix based machines, this could pull entropy or actual values from /dev/urandom.
For windows, a similar API also exists.

Javascript

Most modern browsers support crypto.getRandomValues as does NodeJS.

Use Cases for Secure Random

Here are some places you really don't want a predictable RNG.

  • Creation of a session key or cookie for a web application
  • Creation of a Cross-Site Request Forgery Token (CSRF)
  • Gambling or Games of Chance
  • Implementing any sort of functionality where predictable random number generation could be abused by users

Standards

Here's a quote from the documentation on Java's SecureRandom:

A cryptographically strong random number minimally complies with the statistical random number generator tests specified in FIPS 140-2, Security Requirements for Cryptographic Modules, section 4.9.1. Additionally, SecureRandom must produce non-deterministic output. Therefore any seed material passed to a SecureRandom object must be unpredictable, and all SecureRandom output sequences must be cryptographically strong, as described in RFC 4086: Randomness Requirements for Security.
- Java 10 Secure Random Documentation

Any implementation of Secure Random should also follow these similar standards.

Additional Resources & Justification

@ilya-g
Copy link
Member

ilya-g commented Mar 29, 2019

Could you expand the proposal with some details?

  • what is the proposed SecureRandom, is it another implementation of kotlin.random.Random abstract class?
  • how users are supposed to get an instance of SecureRandom?
  • what is the expected behavior if the platform does not support secure random number source?

Also I remember there was an observation by @DALDEI that some not-precisely-specified generic "secure" random may not meet the requirements of real-world use cases.
So what are the use cases where the proposed implementation of SecureRandom would be enough?

@JLLeitschuh
Copy link
Author

@ilya-g: Before you read this, just a heads up, I modified the top post since you last read it.

Fundamental Language Question

I believe that this entire question around expectations of an RNG really hinges upon the primary users and intended users of the language.

Accedemic Usage

If the primarily intended usage of the language is purely academic, then a deterministic PRNG is a fast and efficient way of supplying RNG.

In an accedemic setting PRNG have the following advantages:

  • Fast & Non-Blocking
  • Produce consistent output with a known seed cross-platform
  • Enable reproducible unit testing
  • Enable reproducible simulations that utilize RNG

In an academic setting a PRNG has the following disadvantages:

  • The output might not be "random enough"

Production Usage

If the primary intended usage of the language is pure as corporate/production workhorse, for example in Mobile Apps, Web Servers, and Web Frontends, there are different expectations of a deterministic RNG.

In a production codebase deterministic PRNG have the following advantages:

  • Fast & Non-Blocking
  • They enable reproducible unit testing

In a production codebase deterministic PRNG have the following disadvantages:

  • Enable hackers to derive the seed used to generate:
    • Session ID's allowing a single attacker to compromise the integrity of every single user logged in to the server.
    • Cross-Site Request Forgery (CSRF) Tokens allowing an attacker to bypass CSRF protections
    • Unique identifiers used to hide resources on a web server
      (Eg. The Google Drive "Share with anyone with the link" documents)
  • Usage can break the cryptographic guarantees of algorithms requiring truly random numbers.

In my opinion, Kotlin seems to be primarily used as a production workhorse language.
If we agree that this is its primary use case, the potential disadvantages of having a PRNG be the language "default" seem to outweigh the potential benefits.

Answering your Questions

I've spent some time thinking about your question and trying to come up with some concrete answers after having discussed this issue with a few people.

what is the proposed SecureRandom, is it another implementation of kotlin.random.Random abstract class?

I believe that the Random abstract class is sufficient to provide this functionality.

how users are supposed to get an instance of SecureRandom?

Also I remember there was an observation by @DALDEI that some not-precisely-specified generic "secure" random may not meet the requirements of real-world use cases.

I believe that the goal here is not to satisfy all use cases. The primary goal here should be to help protect developers who don't understand the pitfalls of insecure RNG from shooting themselves and their users in the foot.

The goal shoud not be to solve all possible use cases.

how users are supposed to get an instance of SecureRandom?

If the opportunity presented itself to be able to do this over again, ideally, SecureRandom would be the "default" for the language.

As a naive user with no deep understanding of software RNG, if I see an object or method called Random I would expect that it would truly be random.

In this hypothetical world where we could do this over again, I'd name the interface Random and then any implementation that used a PRNG would be prefixed with deterministicRandom. Calling a deterministic PRNG random is an API lying to its users.

Given that all the documentation on all of the types/methods in Random don't seem to offer any sort of guarntees about what RNG is returned by them, a secure RNG could be swapped out without breaking users.

See all of the docs on methods/types under this package:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.random/index.html

My suggestion is to move the PRNG implementations so that they are accessable with method names that acurately describe what they are predictableRandom or deterministicRandom.

what is the expected behavior if the platform does not support secure random number source?

Ideally, the API would pick the most secure default possible on the system.

Here are the CSPRNG offered by Java:

https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom

If the host system truly has no source of entropy then an exception should be thrown on construction time. I believe that these cases will be incredibly rare.

@JLLeitschuh JLLeitschuh changed the title Add SecureRandom to the Kotlin StdLib Add a CSPRNG (eg. SecureRandom) to the Kotlin StdLib Apr 4, 2019
This was referenced Apr 4, 2019
@JLLeitschuh JLLeitschuh changed the title Add a CSPRNG (eg. SecureRandom) to the Kotlin StdLib Add a CSPRNG (ie. SecureRandom) to the Kotlin StdLib Apr 4, 2019
@JLLeitschuh
Copy link
Author

@ilya-g Do you believe there's enough here to begin fleshing out a proposal PR?

@ilya-g
Copy link
Member

ilya-g commented May 17, 2019

Our main consideration against making the default random implementation SecureRandom is its performance. The cases that do not require cryptographically secure random generator such as tests, game AI, shuffling large arrays, might experience serious slowdown should the implementation be replaced with a secure one.

Could you estimate the performance of the proposed implementations and compare it to the performance of non-secure ones (e.g. JS Math.random, JDK ThreadLocalRandom, etc)? We can tolerate some slowdown, but not if it is orders of magnitude more.

@fionafibration
Copy link

I think an acceptable solution may be keeping the normal random number generator as a PRNG and adding the CSPRNG as another Random class, if sufficient warnings are given in the documentation about the dangers of using insecure random numbers.

See, for example, the Python 3 random module documentation. While Python makes the default RNG a fast, deterministic PRNG, it makes sure to warn users and guide them to the alternative for security-conscious use cases.

@JLLeitschuh
Copy link
Author

@ThePlasmaRailgun The problem is that defaults die hard and documentation generally isn't enough for nieve users.

For example, I recently discovered a popular JVM web framework called RatPack was using a ThreadLocalRandom for generating session ID's by default.

This release fixes a security vulnerability around session ID generation and is recommended for all users.
The issue stems from the default session ID generator using a cryptographically weak pseudo-random number generator in the JDK's ThreadLocalRandom. This means that if an attacker can determine a small window for the server start time and obtain a session ID value, they can theoretically determine the sequence of session IDs. 1.6.1 uses system entropy when generating values to make the values non-determinable.

When developers see "random" on a type, they believe that it is truly random and can not be predicted. The problem seems to be that there is industry-wide cognitive dissonance between what language & library designers expect from their users and what their users actually do.

@ilya-g I am actually working on a response to your comment, but I'm busy with life things currently. I'll get to it as soon as is possible.

@karanlyons
Copy link

karanlyons commented Jul 12, 2019

(My knowledge is more towards software and security in general rather than the Kotlin ecosystem specifically, so my apologies in advance if my ignorance here renders most points moot.)

Generally speaking developers can’t be expected to understand the entirety of CS as a discipline, and it’s for this reason specifically that we build abstractions at all. The naming of insecure random number generators as “Random” in many standard libraries is, in my opinion (though I believe it’s as well shared by those with far more authority) a mistake: “random" colloquially speaking means what “cryptographically secure random” means to those who know of the distinction.

If it is at all possible to make this distinction clear directly in the API rather than indirectly (say, in the documentation), I’d strongly advice doing so. Admittedly this may be difficult at this point logistically (and it’s much for this reason that the poor naming exists in other libraries as a historical artifact), though it could look something like:

  1. Add a SecureRandom implementation.
  2. Add a new alias to Random: InsecureRandom.
  3. In the next major/minor version (depending on existing guidelines): on first invocation of Random print a warning to the developer indicating that Random is not secure, and advising them to either indicate intent through usage of InsecureRandom or use SecureRandom. Advise as well that Random will be changed in the next major/minor version (again, depending) to point to SecureRandom.
  4. Finally, alias Random to SecureRandom and move the LCRNG to InsecureRandom.

This does leave an extra noun which is a bit away from the ideal, but it avoids causing too much extra work for developers whilst keeping them secure. Regardless, at the very least lifting a SecureRandom implementation into the standard library would go a long way towards reducing the number of potential bullets in feet.

As @JLLeitschuh has already indicated Kotlin itself should be able to punt on the difficult problem of secure implementations as Java provides java.util.Random and most common JS runtimes will have global.Crypto. In the latter case, panicking and crashing when Crypto is needed and not available, whilst admittedly a poor experience, is a far better experience than trying to recover and leaving one's self vulnerable.

@JLLeitschuh
Copy link
Author

JLLeitschuh commented Jul 12, 2019

Here are some benchmarks from what @karanlyons and I have been working together on:

package randomBenchmark

import kotlin.random.Random
import kotlin.system.measureNanoTime
import java.security.SecureRandom


val secureRandom = SecureRandom()

fun secureBench(j: Int) {
    for (i in 0..j) {
        val res = ByteArray(4)
        secureRandom.nextBytes(res)
    }
}

fun insecureBench(j: Int) {
    for (i in 0..j) {
        val _res = Random.nextBits(32)
    }
}

fun main() {
    val totalRuns = 5
    val runLength = 10000

    for (i in 1..totalRuns + 1) {
        val secureTime = measureNanoTime { secureBench(runLength) }
        val insecureTime = measureNanoTime { insecureBench(runLength) }

        println("Run $i:")
        println("  ($i) secureTime: ${secureTime / runLength}ns")
        println("  ($i) insecureTime: ${insecureTime / runLength}ns")
        println("  ($i) Impact: ${secureTime / insecureTime.toDouble()}x\n")
    }
}
Run 1:
  (1) secureTime: 1971ns
  (1) insecureTime: 2221ns
  (1) Impact: 0.8872748448906839x

Run 2:
  (2) secureTime: 723ns
  (2) insecureTime: 55ns
  (2) Impact: 13.133652413993534x

Run 3:
  (3) secureTime: 720ns
  (3) insecureTime: 44ns
  (3) Impact: 16.144131713053703x

Run 4:
  (4) secureTime: 702ns
  (4) insecureTime: 39ns
  (4) Impact: 17.781646987357153x

Run 5:
  (5) secureTime: 682ns
  (5) insecureTime: 39ns
  (5) Impact: 17.28251130161705x

Run 6:
  (6) secureTime: 681ns
  (6) insecureTime: 39ns
  (6) Impact: 17.13903389660028x

As you can clearly see, once the JIT kicks in, the insecure RNG clearly outpaces the secure RNG.

We would need to provide a sane warning to users that this was going to change, but I believe that changing this is an important move to protect the users of all of our software.

@fvasco
Copy link

fvasco commented Jul 12, 2019

A trivial consideration about InsecureRandom name.
A SecureRandom is designed to be used in a "secure" context, differently Random (a.k.a. InsecureRandom) is designed to be "fast" (or "portable" or something else), it is not designed to be "insecure".

My suggestion is to consider FastRandom and SecureRandom.

@IlyaGulya
Copy link

IlyaGulya commented Aug 17, 2019

Proposal looks great.
But I'm a bit worried about making SecureRandom default implementation for Random.
There's much less tasks in the wild when programmer need to have a really secure random implementation.
Mostly performance is more desirable.
Better approach IMO would be to warn (or error) when someone tries to use insecure Random in security-aware context.
I.E. distinct the Random and SecureRandom types completely (do not make SecureRandom extend Random) and make library/API developers to decide which implementation should user use.
That's much more convenient way to solve the problem, IMO.
It's the same as Kotlin's collections mutability (List/MutableList, for instance). Just restrict the API, do not change default behavior.

@JLLeitschuh
Copy link
Author

Better approach IMO would be to warn (or error) when someone tries to use insecure Random in security-aware context.

That's a really hard thing to do, especially when interfacing with other libraries.

But I'm a bit worried about making SecureRandom default implementation for Random. But I'm a bit worried about making SecureRandom default implementation for Random.

The potential negative consequences of using insecure random in a secure random context is far worse than the performance issues. I think it's fundamentally a better problem to have that developers are finding out that their code is slow and they need to switch methods that they are using for RNG, than the alternative where developers figure out that they were using insecure RNG and need to issue a CVE number for every single previous release of their library due to insecure RNG.

@ZacSweers
Copy link
Contributor

ZacSweers commented Aug 18, 2019 via email

@LouisCAD
Copy link
Contributor

LouisCAD commented Aug 18, 2019 via email

@IlyaGulya
Copy link

That's a really hard thing to do, especially when interfacing with other libraries.

But it is definitely much better than breaking backward compatibility for everyone. (yes, huge performance impact in default implementation is definitely breaking of backwards compatibility IMO). Hard != impossible.

I think kotlin should give developers abilities to make their libraries more secure, not restrict to be insecure.

Disclaimer: I completely understand why you are care so much about this security stuff, but please think about millions of other developers who most likely will not develop something security-aware at all.
Don't you think that solving security problems Is not language itself task, but a developers of relevant libraries?

@JLLeitschuh
Copy link
Author

JLLeitschuh commented Sep 16, 2019

Another example of insecure RNG that I found leaving potentially thousands of companies and potentially millions of users data exposed due to insecure RNG in a code generator called JHipster & JHipster Kotlin.

This vulnerability ended up with a a CVSS v3 score of 9.8/10

https://nvd.nist.gov/vuln/detail/CVE-2019-16303

Here's the Java issue:

jhipster/generator-jhipster#10401

Here's the Kotlin issue:
jhipster/jhipster-kotlin#183

@fluidsonic
Copy link

fluidsonic commented Jan 28, 2020

Following the discussion, there are three major scenarios for RNG:

  • Performance is most important
  • Security is most important
  • Neither is very important

Now the questions are

  1. How likely is each scenario?
  2. What are the up- and downsides for each scenario in case the default is either secure RNG or fast RNG?
  3. What's the best tradeoff?
  4. How to ease migration?

(1) How likely is each scenario?

This is difficult to answer and would require analyzing a lot of projects.
My gut feeling is that the majority of projects uses RNG without caring for best performance nor best security. Data on this would be great though.

(2) What are the up- and downsides for each scenario?

Scenario Default Effect
high performance fast Ideal out of the box. No change in default.
high performance secure Slows down existing code. Requires knowledge that the use of fast RNG must be explicit.
highly secure fast Causes security vulnerabilities due to inexperienced users and potential oversights. Requires knowledge that the use of secure RNG must be explicit.
highly secure secure Ideal out of the box. Fixes potential security flaws in existing projects where Random is used in a secure context.
perf&sec irrelevant fast Barely relevant. No change in default.
perf&sec irrelevant secure Barely relevant. Slightly slower but negligible.

(3) What's the best tradeoff?

Let's assume that the default changes to a secure RNG. Looking at the table above there are three constellations to consider now:

  • High performance code will be affected negatively. We can't tell how many projects are affected, but we can look into some use cases. Let's start with the ones from Ilya:
    • Tests: We need to be more specific here. What kinds of tests? This probably affects mostly larger projects that have several developers and more thorough considerations when updating any dependencies, including Kotlin. The release information can make it very clear the the default RNG changes implementation.
    • Game AI: Game developers usually have a good knowledge about achieving good performance. They can also be caught by surprise by a slowdown but will most likely figure it out quite fast, esp. when it's a well-documented change.
    • Shuffling large arrays shouldn't be a problem if Kotlin's shuffle is use, which could use fast RNG by default (any security concerns here?). Custom implementations that use Random will be impacted though. Question is how common these are.
    • What other use cases can we think of?
  • Highly sensitive code that's already using SecureRandom won't see any difference. But such sensitive code that uses Random in the future due to inexperience or oversight will be secure-by-default which is likely a good thing. Even better, existing code that incorrectly uses Random in a secure context will be fixed just by upgrading Kotlin.

(4) How to ease migration?

In case that the default changes or that developers have to explicitly choose between SecureRandom and SomeNotReallySecureRandom migration and decision can be eased in several ways:

  • Clear documentation on what kind of RNG to use in what situation and what (the new) default is. This includes the release blog post, change log, Slack, tutorials, etc.
  • Discourage the use of Random and Random.Default and prefer an explicit selection. That can also make most developers aware that the default changed to be secure.
  • Clearly label and document any non-secure RNG so that people don't use it without thinking. E.g. a FastRandom or SimpleRandom etc. may not make it clear enough that they're not suitable for security-sensitive code. Using Random as default=secure and providing a strong opt-out class/method for fast/insecure RNG would alleviate that.
  • What else can be done?

Considering the ever increasing number of security / privacy breaches that are happening and that hackers and hacks are becoming more sophisticated, focusing on a stronger secure-by-default stdlib is certainly worth considering.

@peteroupc
Copy link

peteroupc commented Mar 18, 2020

In my opinion, a cryptographic RNG is appropriate for the "security is important" and "neither is important" cases. As I write in "Random Number Generator Recommendations for Applications":

An application SHOULD use a cryptographic RNG whenever the application—

  • generates random numbers for information security purposes, or
  • generates random numbers so infrequently that the RNG's speed is not a concern.

The "performance is important" case occurs mostly in applications such as simulations and machine learning, where security is generally not a concern, but reproducibility of "random" numbers may be. Even here, a cryptographic RNG can be useful (at least for the purpose of setting a seed for the "faster" PRNG). For the "performance is important" case, the PRNG should be both high-quality and fast, and for stability purposes the PRNG implementation should use the specific algorithm in its name (not just a generic one like "Random").

Some applications care about reproducibility, and some don't. (And in fact, random numbers are not the only source of nondeterminism or inconsistency; another major one is floating-point numbers, and others include thread scheduling, parallelism, as well as changes in algorithms used by the application or libraries it uses.) For most applications that don't care about reproducibility, a cryptographic RNG is appropriate.

Shuffling large arrays shouldn't be a problem if Kotlin's shuffle is use, which could use fast RNG by default (any security concerns here?). Custom implementations that use Random will be impacted though. Question is how common these are.

The issue with shuffling is not whether a secure or insecure RNG is used, but whether the RNG is capable of producing any given arrangement (permutation) of a particular list. For a PRNG, this generally depends on the size of the list and the PRNG's state size. See my section on shuffling.

@TomTervoort
Copy link

TomTervoort commented Jan 12, 2022

In my experience it is quite common, especially in web applications, that developers require values that are supposed to be unpredictable and/or secret (e.g. API keys, session tokens, generated user passwords, password reset tokens etc.). The use cases of secure RNG's are definitely not limited to cryptographic keys and winning lottery numbers. Of course developers should be aware of this, but in practice a lot of people make the assumption that "random" means "unpredictable" and just pick the default RNG the standard library provides to them.

However, I think there might be some middle ground between a "RNG suitable for cryptographic purposes" and "RNG of which the seed can be trivially recovered after observing some output". In my opinion a default random number generator should have decent performance, be suitable for statistical application, optionally support reproducibility (i.e. manually setting a seed) and try to avoid introducing surprising security vulnerabilities in most use cases.

I'd say standard library RNG's could be roughly subdivided in the following three types:

1. A specialized secrets generator
This would use an API like Python's secrets module, clearly focused on providing things like secret tokens or cryptographic keys. A possible implementation would be a simple wrapper around the OS CSPRNG, which is inefficient but might provide some defense-in-depth against issues such as seeds being replicated due to process or VM forking. This API could simply forbid manual seeding in its entirety, and potentially even impose a minimum length on the random tokens it provides.

2. A fast but predictable RNG
Something like java.util.Math. Very efficient but the randomness provided may not pass all statistical tests. Also completely unsuitable for values that should not be predictable.

3 A default RNG decent at most use cases
This RNG would use a fast deterministic CSRNG like the Salsa20 stream cipher. It would only communicate with the OS to get a seed but not perform any system calls afterwards. It could still allow manual seeding (allowing developers to still potentially break security by setting a guessable seed), but it any other case should not allow attackers to gain any knowledge about output before or after what they observed. Even when the user does not care about security, this RNG has the bonus that the statistical randomness of its output is as high as it can get, which is useful for scientific applications.

Ideally, I would say something like RNG #3 would be a decent default. While a modern stream ciphers like Salsa20 won't beat the performance of Java's LCG generator, it is still very fast and does not require anything from the OS after initial seeding. Note that the deterministic CSRNG's used by SecureRandom implemenations are probably pretty decent as well, so that may be a better choice than using a Kotlin stream cipher implementation or a native library.

@elizarov
Copy link
Contributor

I'm sorry to close this great discussion, but there are two fundamental problems here:

First of all, this KEEP is not the right place for it (see https://github.com/Kotlin/KEEP#contributing-ideas).

More importantly, though, the Kotlin Standard library is not the right place for any kind of cryptography primitives. Secure cryptographic primitives are very domain-specific. There are tons of conflicting requirements that need to be met in any cryptography design with tradeoffs in performance and security, there are country-specific and industry-specific rules, regulations, and recommendations, there is constant ongoing research and a never-ending stream of vulnerabilities and exploits that are being found and need to be tracked and addressed by anyone who maintains any kind of a secure system. From the standpoint of Kotlin, it means that any security-related cryptographic primitives must live in their own library and be maintained by a dedicated team with the corresponding expertise and credentials in cryptography.

@darronschall
Copy link

I came here from an internet search looking for a SecureRandom implementation for Kotlin, that I could use in a Multiplatform Mobile project. This is a great discussion, but ends without resolving anything.

Closing the loop for future folks like me 👋... there is a SecureRandom implementation via krypt-csprng that does essentially what this issue description proposes; create a Kotlin subclass of Random that delegates the work to the platform's SecureRandom implementation.

@JLLeitschuh
Copy link
Author

More importantly, though, the Kotlin Standard library is not the right place for any kind of cryptography primitives. Secure cryptographic primitives are very domain-specific.

The need for secure sources of randomness is not domain specific. Secure randomness is widely applicable. The most common use case you will see, and see done wrong, is the creation of a random string for, as an example, password reset tokens.

There are tons of conflicting requirements that need to be met in any cryptography design with tradeoffs in performance and security, there are country-specific and industry-specific rules, regulations, and recommendations, there is constant ongoing research and a never-ending stream of vulnerabilities and exploits that are being found and need to be tracked and addressed by anyone who maintains any kind of a secure system.

This rationale didn't stop JetBrains from going forward and implementing an entire HTTP server stack in the form of KTor. Honestly, the risk introduced from implementing an HTTP server, and HTTP body parser incorrectly has a much higher risk to end user software than the security a "good enough" CSPRNG offers.

From the standpoint of Kotlin, it means that any security-related cryptographic primitives must live in their own library and be maintained by a dedicated team with the corresponding expertise and credentials in cryptography.

I agree, and that solution should be centralized into a standard library that the entire industry uses, instead of being tacked-on at the end by third party libraries.

It's a refrain of the security industry that "security should be opt-out, not opt-in". Because the Kotlin standard library doesn't support a secure source of randomness, security in this area will always be opt-in.

@ronhombre
Copy link

The fact that Kotlin does not support CSPRNG out of the box honestly drives me crazy. As far as I know, almost all popular languages have their built-in SecureRandom baked into the language. If the Kotlin developers/maintainers want wider adoption of Kotlin Multiplatform(KMM), then they should give us something most programming languages offer. Having to use a 3rd-party library is a deal-breaker. Barely anyone checks those libraries to confirm whether they're actually working "Securely".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests