Skip to content

Commit

Permalink
[#1561] SECURITY: avoid MD5 in doc/example code (broken/risky algorithm)
Browse files Browse the repository at this point in the history
Closes #1561
  • Loading branch information
remkop committed Jan 31, 2022
1 parent 8adcd23 commit 21c1e66
Show file tree
Hide file tree
Showing 22 changed files with 62 additions and 61 deletions.
1 change: 1 addition & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Picocli follows [semantic versioning](http://semver.org/).
* [#1558] SECURITY: Fix code scanning alert - Pinned-Dependencies in codeql-analysis.yml
* [#1559] SECURITY: Fix code scanning alert - Token-Permissions in codeql-analysis.yml
* [#1560] SECURITY: Fix code scanning alert - Binary-Artifacts - Validate Gradle Wrapper
* [#1561] SECURITY: Fix code scanning alert - Doc/example code uses a broken or risky cryptographic algorithm
* [#1491] BUILD: Add build job in CI; Thanks to [Goooler](https://github.com/Goooler) for the pull request.
* [#1482] BUILD: Optimize gradle; Thanks to [Goooler](https://github.com/Goooler) for the pull request.
* [#1461] BUILD: Allow publishing without signing for non-release versions. Thanks to [Andreas Deininger](https://github.com/deining) for raising this.
Expand Down
16 changes: 8 additions & 8 deletions docs/A-Whirlwind-Tour-of-Picocli.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ We will use this small, but realistic, example CheckSum utility to demonstrate v
.Checksum: an example picocli-based command line application
[source,java,linenums]
----
@Command(description = "Prints the checksum (MD5 by default) of a file to STDOUT.",
@Command(description = "Prints the checksum (SHA-1 by default) of a file to STDOUT.",
name = "checksum", mixinStandardHelpOptions = true, version = "checksum 3.0")
class CheckSum implements Callable<Void> {
@Parameters(index = "0", description = "The file whose checksum to calculate.")
private File file;
@Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ...")
private String algorithm = "MD5";
private String algorithm = "SHA-1";
public static void main(String[] args) {
// CheckSum implements Callable, so parsing, error handling and handling user
Expand Down Expand Up @@ -71,22 +71,22 @@ This gives an error message saying the `<file>` parameter is missing:

image:images/checksum-help.png[]

The `<file>` positional parameter does not have a default, so this a mandatory parameter. The `--algorithm` option does have a default: `"MD5"`, so it is optional.
The `<file>` positional parameter does not have a default, so this a mandatory parameter. The `--algorithm` option does have a default: `"SHA-1"`, so it is optional.

Note that our program does not have any logic to validate the user input. The validation was done automatically by picocli as part of the `CommandLine.call(Callable, String[])` invocation in our `main` method. Later we will show some alternatives that give more control to the application.

Now let's try running this program with some valid input, and see how the output compares to the GNU `md5sum` and `sha1sum` utilities:

.Comparing our `CheckSum` utility against `md5sum` and `sha1sum`
----
$ java picocli.example.CheckSum picocli-3.9.5.jar
$ java picocli.example.CheckSum --algorithm=MD5 picocli-3.9.5.jar
509e3e2602854d5b88e2e7baa476a7fe
$ md5sum picocli-3.9.5.jar
509e3e2602854d5b88e2e7baa476a7fe *picocli-3.9.5.jar
$ java picocli.example.CheckSum --algorithm=SHA1 picocli-3.9.5.jar
$ java picocli.example.CheckSum picocli-3.9.5.jar
f659a2feef0e8f7f8458aaf7d36c4d92f65320c8
$ sha1sum picocli-3.9.5.jar
Expand All @@ -110,7 +110,7 @@ The version information shown is what was specified in the command annotation: `
----
$ java picocli.example.CheckSum --help
Usage: checksum [-hV] [-a=<algorithm>] <file>
Prints the checksum (MD5 by default) of a file to STDOUT.
Prints the checksum (SHA-1 by default) of a file to STDOUT.
<file> The file whose checksum to calculate.
-a, --algorithm=<algorithm>
MD5, SHA-1, SHA-256, ...
Expand Down Expand Up @@ -805,7 +805,7 @@ private static class AlgoList extends ArrayList<String> {
}
@Option(names = {"-a", "--algorithm"}, completionCandidates = AlgoList.class,
description = "${COMPLETION-CANDIDATES}, ...")
private String algorithm = "MD5";
private String algorithm = "SHA-1";
----
Values in the `completionCandidates` list are shown as completion candidates when the user presses `[TAB]` after the `-a` option, similarly to `enum` typed options.

Expand Down Expand Up @@ -842,7 +842,7 @@ import static picocli.CommandLine.*
@Option(names = ["-a", "--algorithm"], description = [
"MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512, or",
" any other MessageDigest algorithm. See [1] for more details."])
@Field private String algorithm = "MD5"
@Field private String algorithm = "SHA-1"
files.each {
println ""+MessageDigest.getInstance(algorithm).digest(it.bytes).encodeHex()+"\t"+it
Expand Down
4 changes: 2 additions & 2 deletions docs/apidocs/overview-summary.html
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,14 @@ <h1 class="title">picocli 4.6.2 API</h1>
</p>
<pre>
&#064;Command(name = "checksum", mixinStandardHelpOptions = true, version = "Checksum 4.0",
description = "Prints the checksum (MD5 by default) of a file to STDOUT.")
description = "Prints the checksum (SHA-1 by default) of a file to STDOUT.")
class CheckSum implements Callable&lt;Integer&gt; {

&#064;Parameters(index = "0", description = "The file whose checksum to calculate.")
private File file;

&#064;Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ...")
private String algorithm = "MD5";
private String algorithm = "SHA-1";

// CheckSum implements Callable, so parsing, error handling and handling user
// requests for usage help or version help can be done with one line of code.
Expand Down
20 changes: 10 additions & 10 deletions docs/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ import java.security.MessageDigest;
import java.util.concurrent.Callable;
@Command(name = "checksum", mixinStandardHelpOptions = true, version = "checksum 4.0",
description = "Prints the checksum (MD5 by default) of a file to STDOUT.")
description = "Prints the checksum (SHA-256 by default) of a file to STDOUT.")
class CheckSum implements Callable<Integer> {
@Parameters(index = "0", description = "The file whose checksum to calculate.")
private File file;
@Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ...")
private String algorithm = "MD5";
private String algorithm = "SHA-256";
@Override
public Integer call() throws Exception { // your business logic goes here...
Expand Down Expand Up @@ -128,14 +128,14 @@ import java.security.MessageDigest
import java.util.concurrent.Callable
@Command(name = 'checksum', mixinStandardHelpOptions = true, version = 'checksum 4.0',
description = 'Prints the checksum (MD5 by default) of a file to STDOUT.')
description = 'Prints the checksum (SHA-256 by default) of a file to STDOUT.')
class Checksum implements Callable<Integer> {
@Parameters(index = '0', description = 'The file whose checksum to calculate.')
File file
@Option(names = ['-a', '--algorithm'], description = 'MD5, SHA-1, SHA-256, ...')
String algorithm = 'MD5'
String algorithm = 'SHA-256'
Integer call() throws Exception {
println MessageDigest.getInstance(algorithm).digest(file.bytes).encodeHex().toString()
Expand All @@ -158,14 +158,14 @@ import groovy.transform.Field
import java.security.MessageDigest
@Command(name = 'checksum', mixinStandardHelpOptions = true, version = 'checksum 4.0',
description = 'Prints the checksum (MD5 by default) of a file to STDOUT.')
description = 'Prints the checksum (SHA-256 by default) of a file to STDOUT.')
@picocli.groovy.PicocliScript
@Parameters(index = '0', description = 'The file whose checksum to calculate.')
@Field File file
@Option(names = ['-a', '--algorithm'], description = 'MD5, SHA-1, SHA-256, ...')
@Field String algorithm = 'MD5'
@Field String algorithm = 'SHA-256'
println MessageDigest.getInstance(algorithm).digest(file.bytes).encodeHex().toString()
----
Expand All @@ -187,14 +187,14 @@ import java.util.concurrent.Callable
import kotlin.system.exitProcess
@Command(name = "checksum", mixinStandardHelpOptions = true, version = ["checksum 4.0"],
description = ["Prints the checksum (MD5 by default) of a file to STDOUT."])
description = ["Prints the checksum (SHA-256 by default) of a file to STDOUT."])
class Checksum : Callable<Int> {
@Parameters(index = "0", description = ["The file whose checksum to calculate."])
lateinit var file: File
@Option(names = ["-a", "--algorithm"], description = ["MD5, SHA-1, SHA-256, ..."])
var algorithm = "MD5"
var algorithm = "SHA-256"
override fun call(): Int {
val fileContents = Files.readAllBytes(file.toPath())
Expand All @@ -221,14 +221,14 @@ import java.security.MessageDigest
import java.util.concurrent.Callable
@Command(name = "checksum", mixinStandardHelpOptions = true, version = Array("checksum 4.0"),
description = Array("Prints the checksum (MD5 by default) of a file to STDOUT."))
description = Array("Prints the checksum (SHA-256 by default) of a file to STDOUT."))
class Checksum extends Callable[Int] {
@Parameters(index = "0", description = Array("The file whose checksum to calculate."))
private var file: File = null
@Option(names = Array("-a", "--algorithm"), description = Array("MD5, SHA-1, SHA-256, ..."))
private var algorithm = "MD5"
private var algorithm = "SHA-256"
def call(): Int = {
val fileContents = Files.readAllBytes(file.toPath)
Expand Down
14 changes: 7 additions & 7 deletions docs/zh/picocli-2.0-groovy-scripts-on-steroids.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Picocli 2.0 增加了对其他 JVM 语言的支持,尤其是 Groovy。
您可能喜欢Picocli的使用帮助,它默认显示ANSI http://picocli.info/#_ansi_colors_and_styles[颜色和样式]
另一个您可能喜欢的功能是命令行
http://picocli.info/autocomplete.html[TAB autocompletion]。 最后,还有一些小功能,
比如说您的脚本需要零行解析代码的命令行,
比如说您的脚本需要零行解析代码的命令行,
Picocli的 http://picocli.info/#subcommands[子命令]支持,
选项和位置参数的 http://picocli.info/#_strongly_typed_everything[类型转换],
以及 http://picocli.info/#tracing[解析器跟踪],只是举几个例子。
Expand All @@ -25,8 +25,8 @@ image:cli.jpg[Alt="Picocli强大的微型命令行接口",width='20%']
== 案例

让我们来看个例子。下面的 checksum.groovy 脚本采用一个或多个文件参数,每个文件输出一个校验和文件名。默认情况下,
`checksum.groovy` 算法是 MD5,但是用户可能会指定一个不同的 MessageDigest 算法。用户可以通过 `-h` 或 `--help` 选项请
求使用帮助 。
`checksum.groovy` 算法是 SHA-1,但是用户可能会指定一个不同的 MessageDigest 算法。用户可以通过 `-h` 或 `--help` 选项请
求使用帮助 。

[source,groovy]
----
Expand All @@ -42,7 +42,7 @@ import static picocli.CommandLine.*
@Option(names = ["-a", "--algorithm"], description = [
"MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512,",
" or any other MessageDigest algorithm."])
@Field String algorithm = "MD5"
@Field String algorithm = "SHA-1"
@Option(names= ["-h", "--help"], usageHelp= true, description= "Show this help message and exit.")
@Field boolean helpRequested
Expand All @@ -52,7 +52,7 @@ files.each {
}
----
当在 `$picocli-home/examples/src/main/groovy/picocli/examples` 目录中运行时,本示例脚本给
出以下结果:
出以下结果:

[source,bash]
----
Expand Down Expand Up @@ -82,7 +82,7 @@ class Checksum {
File[] files
@Option(names = ["-a", "--algorithm"], description = ["..."])
String algorithm = "MD5"
String algorithm = "SHA-1"
@Option(names = ["-h", "--help"], usageHelp = true, description = "...")
boolean helpRequested
Expand Down Expand Up @@ -170,7 +170,7 @@ import static picocli.CommandLine.*
@Option(names = ["-a", "--algorithm"], description = [
"MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512, or",
" any other MessageDigest algorithm. See [1] for more details."])
@Field private String algorithm = "MD5"
@Field private String algorithm = "SHA-1"
@Option(names= ["-h", "--help"], usageHelp=true, description="Show this help message and exit.")
@Field private boolean helpRequested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import java.util.concurrent.Callable

@Command(name = "checksum", mixinStandardHelpOptions = true,
subcommands = [ HelpCommand::class ], version = ["checksum 4.1.4"],
description = ["Prints the checksum (MD5 by default) of file(s) to STDOUT."])
description = ["Prints the checksum (SHA-1 by default) of file(s) to STDOUT."])
class Checksum : Callable<Int> {

@Parameters(index = "0..*", description = ["The file(s) whose checksum to calculate."],
arity = "1..*", paramLabel = "<file 1> <file 2>")
val files: ArrayList<File> = arrayListOf()

@Option(names = ["-a", "--algorithm"], description = ["MD5, SHA-1, SHA-256, ..."])
var algorithm = "MD5"
var algorithm = "SHA-1"

override fun call(): Int {
for (file in files)
Expand All @@ -42,4 +42,4 @@ class Checksum : Callable<Int> {
}
}
// NOTE: below is an alternative to defining a @JvmStatic main function in a companion object:
// fun main(args: Array<String>) : Unit = exitProcess(CommandLine(Checksum()).execute(*args))
// fun main(args: Array<String>) : Unit = exitProcess(CommandLine(Checksum()).execute(*args))
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import static picocli.CommandLine.*

@Option(names = ["-a", "--algorithm"], description = ["MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512, or",
" any other MessageDigest algorithm. See [1] for more details."])
@Field private String algorithm = "MD5"
@Field private String algorithm = "SHA-1"

files.each {
println MessageDigest.getInstance(algorithm).digest(it.bytes).encodeHex().toString() + "\t" + it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import static picocli.CommandLine.*

@Option(names = ['-a', '--algorithm'], description = ['MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512,',
' or any other MessageDigest algorithm.'])
@Field private String algorithm = 'MD5'
@Field private String algorithm = 'SHA-1'

files.each {
println MessageDigest.getInstance(algorithm).digest(it.bytes).encodeHex().toString() + "\t" + it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

@Command(name = "checksum", mixinStandardHelpOptions = true, version = "checksum 4.0",
subcommands = GenerateCompletion.class, defaultValueProvider = PropertiesDefaultProvider.class,
description = "ファイルのチェックサム(デフォルトはMD5)を標準出力に表示する。",
description = "ファイルのチェックサム(デフォルトはSHA-1)を標準出力に表示する。",
header = { "@|cyan " +
" _ _ _ _ ___ \n" +
" _ | |_ | | | | |/ __|\n" +
Expand All @@ -29,7 +29,7 @@ class CheckSum implements Callable<Integer> {
private File file;

@Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ...")
private String algorithm = "MD5";
private String algorithm = "SHA-1";

public static void main(String... args) {
System.exit(new CommandLine(new CheckSum()).execute(args));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class LocaleControl implements Callable {
private File file;

@Option(names = {"-a", "--algorithm"}, descriptionKey = "Algorithms", order = 2)
private String algorithm = "MD5";
private String algorithm = "SHA-1";

@Override
public Integer call() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Label_Checksum = Checksum

# Header
usage.headerHeading = Demo: Controlling the locale of message texts%n
usage.header = This application prints the checksum (MD5 by default)
usage.header = This application prints the checksum (SHA-1 by default)
usage.header.0 = of a given file to STDOUT.%n

# Description
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Label_Checksum = Pr

# Header
usage.headerHeading = Demo: Kontrolle der Lokale von Meldungstexten%n
usage.header = Diese Anwendung gibt die Prüfsumme (Voreinstellung: MD5)
usage.header = Diese Anwendung gibt die Prüfsumme (Voreinstellung: SHA-1)
usage.header.0 = einer Datei auf STDOUT aus.%n

# Description
Expand All @@ -30,4 +30,4 @@ Locale = Locale f

# Standard help mixin options:
help = Zeige Hilfemeldung für die Anwendung
version = Zeige Versionsinformation für die Anwendung
version = Zeige Versionsinformation für die Anwendung
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public Integer call() throws Exception {
}

@Command(name = "password",
description = "Prompts for a password and prints its MD5 hash")
description = "Prompts for a password and prints its SHA-256 hash")
class EnterPasswordCommand implements Callable<Void> {

// https://github.com/remkop/picocli/issues/840
Expand All @@ -31,8 +31,8 @@ public Void call() throws Exception {
char[] password = System.console().readPassword("Password to encrypt");

byte[] raw = char2bytes(password);
MessageDigest md5 = MessageDigest.getInstance("MD5");
System.out.printf("Your password is hashed to %s.%n", base64(md5.digest(raw)));
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
System.out.printf("Your password is hashed to %s.%n", base64(sha256.digest(raw)));

Arrays.fill(password, '*');
Arrays.fill(raw, (byte) 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import kotlin.system.exitProcess

@Command(name = "checksum", mixinStandardHelpOptions = true,
subcommands = [ HelpCommand::class ], version = ["checksum 4.1.4"],
description = ["Prints the checksum (MD5 by default) of file(s) to STDOUT."])
description = ["Prints the checksum (SHA-1 by default) of file(s) to STDOUT."])
class Checksum : Callable<Int> {

@Parameters(index = "0..*", description = ["The file(s) whose checksum to calculate."],
arity = "1..*", paramLabel = "<file 1> <file 2>")
val files: ArrayList<File> = arrayListOf()

@Option(names = ["-a", "--algorithm"], description = ["MD5, SHA-1, SHA-256, ..."])
var algorithm = "MD5"
var algorithm = "SHA-1"

override fun call(): Int {
for (file in files)
Expand All @@ -43,4 +43,4 @@ class Checksum : Callable<Int> {
}
}
// NOTE: below is an alternative to defining a @JvmStatic main function in a companion object:
// fun main(args: Array<String>) : Unit = exitProcess(CommandLine(Checksum()).execute(*args))
// fun main(args: Array<String>) : Unit = exitProcess(CommandLine(Checksum()).execute(*args))
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class LocaleControl : Callable<Int> {
lateinit var file: File

@Option(names = ["-a", "--algorithm"], descriptionKey = "Algorithms", order = 2)
var algorithm = "MD5"
var algorithm = "SHA-1"

@Throws(Exception::class)
override fun call(): Int {
Expand All @@ -57,4 +57,4 @@ fun main(args: Array<String>) {

// second phase: parse all args (ignoring --locale) and run the app
exitProcess(CommandLine(LocaleControl()).execute(*args))
}
}
Loading

0 comments on commit 21c1e66

Please sign in to comment.