-
-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
185 additions
and
47 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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 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 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
63 changes: 63 additions & 0 deletions
63
core/src/main/java/global/namespace/truelicense/core/Filters.java
This file contains 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,63 @@ | ||
package global.namespace.truelicense.core; | ||
|
||
import global.namespace.fun.io.api.Filter; | ||
import global.namespace.fun.io.api.Socket; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
|
||
import static global.namespace.fun.io.bios.BIOS.buffer; | ||
|
||
final class Filters { | ||
|
||
/** | ||
* Returns a filter which, upon writing, first compresses the data and then encrypts it using the given filters. | ||
* Upon reading, the filter first tries to do the inverse, that is to first decrypt the data and then decompress it. | ||
* Failing that, the filter tries to swap the underlying filter, that is to first decompress the data and then | ||
* decrypt it. | ||
* This is a workaround for a bug in TrueLicense 4.0.0 and 4.0.1, where these filters were accidentally swapped, | ||
* thus (a) generating license keys which were bigger than they would need to be (because compressing encrypted data | ||
* only adds overhead and thus makes it a little bigger instead of smaller) and (b) breaking compatibility with | ||
* license keys generated by previous versions of TrueLicense. | ||
* Trying the underlying filters in both orders effectively restores compatibility with license keys generated by | ||
* *all* previous versions, with only a very small performance penalty for license keys generated by TrueLicense | ||
* 4.0.0 and 4.0.1. | ||
* Last but not least, if the filters fail in both attempts, the exception of the first attempt (which first | ||
* tried to decrypt the data and then decompress it) will be thrown, effectively discarding the exception of the | ||
* second attempt. | ||
*/ | ||
static Filter compressionAndEncryption(final Filter compression, final Filter encryption) { | ||
assert compression != null; | ||
assert encryption != null; | ||
return new Filter() { | ||
|
||
@Override | ||
public Socket<OutputStream> output(Socket<OutputStream> output) { | ||
return compression.output(encryption.output(output)); | ||
} | ||
|
||
@SuppressWarnings({"deprecation", "ResultOfMethodCallIgnored"}) | ||
@Override | ||
public Socket<InputStream> input(Socket<InputStream> input) { | ||
return () -> { | ||
try { | ||
// Use a buffer filter and do a simple one byte read-ahead test: | ||
return buffer().input(compression.input(encryption.input(input))).map(in -> { | ||
in.mark(1); | ||
in.read(); | ||
in.reset(); | ||
return in; | ||
}).get(); | ||
} catch (final IOException e) { | ||
try { | ||
return encryption.input(compression.input(input)).get(); | ||
} catch (IOException ignored) { | ||
throw e; | ||
} | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
} |
This file contains 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
70 changes: 70 additions & 0 deletions
70
core/src/test/scala/global/namespace/truelicense/core/FiltersSpec.scala
This file contains 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,70 @@ | ||
package global.namespace.truelicense.core | ||
|
||
import java.security.SecureRandom | ||
|
||
import global.namespace.fun.io.api.Filter | ||
import global.namespace.fun.io.bios.BIOS._ | ||
import global.namespace.truelicense.core.Filters.compressionAndEncryption | ||
import global.namespace.truelicense.core.FiltersSpec._ | ||
import javax.crypto.Cipher.{DECRYPT_MODE, ENCRYPT_MODE} | ||
import javax.crypto.spec.{PBEKeySpec, PBEParameterSpec} | ||
import javax.crypto.{Cipher, SecretKeyFactory} | ||
import org.scalatest.Matchers._ | ||
import org.scalatest.WordSpec | ||
import org.scalatest.prop.TableDrivenPropertyChecks._ | ||
|
||
class FiltersSpec extends WordSpec { | ||
|
||
"compressAndEncrypt()" should { | ||
"round trip compress and encrypt some data" in { | ||
forAll(Tests) { (compression, encryption) => | ||
val filter = compressionAndEncryption(compression, encryption) | ||
val store = memory map filter | ||
store content Message.getBytes | ||
new String(store.content) shouldBe Message | ||
} | ||
} | ||
|
||
"transparently read some data which has been processed in the wrong order when writing (issue #7)" in { | ||
forAll(Tests) { (compression, encryption) => | ||
val wrong = compressionAndEncryption(encryption, compression) | ||
val right = compressionAndEncryption(compression, encryption) | ||
val store = memory | ||
store map wrong content Message.getBytes | ||
new String((store map right).content) shouldBe Message | ||
} | ||
} | ||
} | ||
} | ||
|
||
private object FiltersSpec { | ||
|
||
private val Message = "Hello world!" | ||
|
||
private[this] val Algorithm = "PBEWithMD5AndDES" | ||
|
||
private[this] val Skf = SecretKeyFactory getInstance Algorithm | ||
|
||
private[this] val PbeKeySpec = new PBEKeySpec("secret".toCharArray) | ||
|
||
private[this] val PbeParameterSpec = { | ||
val salt = new Array[Byte](8) | ||
new SecureRandom nextBytes salt | ||
new PBEParameterSpec(salt, 2017) | ||
} | ||
|
||
private[this] val PBE: Filter = { | ||
cipher { outputMode: java.lang.Boolean => | ||
val secretKey = Skf generateSecret PbeKeySpec | ||
val cipher = Cipher getInstance Algorithm | ||
cipher.init(if (outputMode) ENCRYPT_MODE else DECRYPT_MODE, secretKey, PbeParameterSpec) | ||
cipher | ||
} | ||
} | ||
|
||
private val Tests = Table( | ||
("compression", "encryption"), | ||
(deflate, PBE), | ||
(gzip, PBE) | ||
) | ||
} |
This file contains 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 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 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 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 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
Oops, something went wrong.