I wrote a library in Java for Bcrypt. Bcrypt's OpenBSD implementation uses a exotic flavour of the standard RFC Base64 encoding. Since there are no standard implementations for this, I modified (and simplified) the OpenJDK Base64 implementation so it outputs OpenBSD Radix64 encoding. The OpenJDK is under "GPLv2 with Classpath Exception"

I attributed in code and in the Readme, that I use GPLv2 with this class. The bcrypt library is published under Apache 2 license.

Can somebody commercially use my library without the need to reveal their source?


By including the modified version of the OpenJDK Base64 implementation, your library has to be effectively distributed under the GPLv2 license, with or without the classpath exception.

If you keep the classpath exception, then it is possible to use your library in non-free projects.

If you drop the classpath exception, then any project using your library has to obey the GPLv2 restrictions, which means that the sources must be made available under a GPL-compatible open-source license when the project is distributed.

  • Would it be more clear to change the whole license to "GPLv2 with classpath exception" or is there any advantage of keeping my code Apache v2? (in the interest of liberal use) – patrickf Jul 26 '18 at 9:05
  • 1
    Advantage notwithstanding, you may not do so. As I think Bart made clear, the whole library must be distributed under GPLv2; the only choice you have is whether to keep the classpath exception. – MadHatter Jul 26 '18 at 10:18
  • @for3st: Yes, it would be more clear to license your files also under GPLv2 or "GPLv2 with classpath exception". And upon reading the other answer, it is actually required.. – Bart van Ingen Schenau Jul 26 '18 at 12:37

It is by default not possible to combine Apache-2 licensed code with GPLv2-licensed code. Those licenses are incompatible. The Classpath Exception (CE) does provide a path towards compatibility, as long as the GPLv2+CE code and any other code are independent modules. According to the CE:

An independent module is a module which is not derived from or based on this library.

You copied some code from the JDK, this is fine under the GPLv2+CE. However, you should take care that this code is clearly separate from your other code (to satisfy the “independent module” requirement), and to properly comply with the GPLv2+CE license. It currently looks like your project might be in violation of the GPL.

So far, all the GPL-derived code is in a single class. But it does not appear as an independent module from the rest of your code. I would suggest you move that class to a separate top-level folder, and place it into a separate Java package.

To comply with the GPL, you will also have to include a copy of the GPL and state which changes you made to the code.

Finally, it is misleading to describe the resulting project as Apache-2 licensed, as it includes GPLv2+CE licensed code. This is not at all obvious from the current README or the LICENSE. Your license should accurately describe which parts of the code are available under which license.

Once you have licensed your source code properly, we can discuss licensing of binaries (i.e. pre-built JARs). Thanks to the classpath exception is is perfectly fine to publish these under the Apache license or any other license, without restrictions or attribution requirements. Therefore your project can be used in proprietary software.

Since properly complying with the GPLv2+CE takes some effort and complicates your project license, it may be much simpler to find another library that provides base64 encoding under a permissive license.

If your Base64 dialect only differs from a more standard Base64 encoding by the used character table, you could also just transliterate the base64-encoded data. E.g. if the default character table is AB...ab...89+/ and your table is .-AB...ab...89, you only have to map the data back to the encoding index and then look up the actual character in your table, no bit shifting required. So basically:

private static int getTableIndex(char c) {
  if ('A' <= c && c <= 'A') return c - 'A';
  if ('a' <= c && c <= 'z') return c - 'a' + 26;
  if ('0' <= c && c <= '9') return c - '0' + 52;
  if (c == '+') return 62;
  if (c == '/') return 63;
  throw some exception;

for (int i = 0 ... string.length)
  string[i] = yourTable[getTableIndex(string[i])];

(For the avoidance of doubt, I wave any copyright or related rights for the above snippet to the fullest extend possible, using the CC0.)

  • 1
    Thanks amon, very good description. I will probably go the route of changing the base implemntation to the Apache Commons Codec since GPLv2 seems to be not what I want my lib to be (and also I want avoid the complex license jungle) – patrickf Jul 26 '18 at 12:32

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.