crunch -d option with simple aA charset

Sorry if this is simple, but I can't find any answer to what should be an easy question.

I am simply passing the command to crunch:

$ crunch 3 3 aA -d 1@

I would expect crunch to generate strings with 3 characters while limiting the same number of lower case letter to 1: aAA, AaA, AAa, AAA. However, my output is:

Crunch will now generate the following number of lines: 2
aAa
AaA

I tried to set -d 1@ -d 3, to keep my upper case letters, but I get the same results. What am I understanding wrong here?

Thanks a lot for your reply,


Solution 1:

What am I understanding wrong here?

crunch doesn't work like this and the manual is somewhat misleading. Its logic makes sense once you get it; and to get it you need examples (available in the manual), trials and errors.

Or this answer maybe. :)

From the manual:

crunch <min-len> <max-len> [<charset string>] [options]

[…]

charset string
You may specify character sets for crunch to use on the command line or if you leave it blank crunch will use the default character sets. The order MUST BE lower case characters, upper case characters, numbers, and then symbols. If you don't follow this order you will not get the results you want. You MUST specify either values for the character type or a plus sign. […]

Where the manual says "lower case characters", "upper case characters", "numbers", and "symbols", it could say "set 1", "set 2", "set 3" and "set 4". The default sets correspond to the terms the manual uses, respectively, but aside from this "lower case characters" is just an abstract "set 1". In this context @ refers to "set 1" and % refers to "set 3". The tool doesn't check if "set 1" or "lower case characters" are indeed lower case characters!

Consider this command:

crunch 1 1 aA bB cC dD
#          ^^          these are "lower case characters"
#             ^^       there are "upper case characters"
#                ^^    these are "numbers"
#                   ^^ these are "symbols"

The output is

a
A

because crunch by default uses "lower case characters" only. If we explicitly tell it to use "numbers"

crunch 1 1 aA bB cC dD -t %

then it will use the third set of symbols:

c
C

Your original command

crunch 3 3 aA -d 1@

specifies aA as "lower case characters" set. Yes, you did tell crunch that A was a "lower case character". Now -d:

-d numbersymbol
Limits the number of duplicate characters. -d 2@ limits the lower case alphabet to output like aab and aac. aaa would not be generated as that is 3 consecutive letters of a. The format is number then symbol where number is the maximum number of consecutive characters and symbol is the symbol of the the character set you want to limit i.e. @,%^ […]

So you told crunch that any "lower case character" (from your set, i.e. a or A) can appear at most 1 time in a row. And indeed the output you got contains neither aa nor AA.


Sometimes it's useful to forget about "lower case characters" etc., to think in terms of "set N" instead. The manual seems to be fixed on the premise that "lower case characters" should all be lower case and so on. Still (at least in Ubuntu) there is a file /usr/share/crunch/charset.lst which can be used with -f; it defines various sets that mix the four basic sets or their fragments. This strongly suggests any set acting as "lower case characters" (or "symbols", or …) is silently supported.

So if you need to generate strings so the first character is a, 0 or ( and the second character is a, 1 or ), then this is the way to go:

crunch 2 2 'a0(' 'a1)' -t @,

Try it. Notice aa appears in the output, but it's neither "a from the first set twice", nor "a from the second set twice". The pattern @, guarantees the first a is from the first set and the second a is from the second set. However this distinction is not so strict when -d is involved. The command

crunch 2 2 'a0(' 'a1)' -t @, -d 1@

will not generate aa. This observation leads to the following trick:

crunch 3 3 aA a -d 1,

The output is:

aAa
aAA
AaA
AAa
AAA

which is almost what you wanted. The mechanism seems to be like this:

  1. There is no -t, so the tool uses the first set only.
  2. It generates all possible outputs (like crunch 3 3 aA).
  3. It discards lines that contradict -d 1,. This option says there cannot be aa in the output. It doesn't matter the option refers to the second set and all the output comes from the first set. No aa. Period.

You didn't anticipate aAa because you misinterpreted -d 1@ as "limiting the number of duplicates", while it's "limiting the number of consecutive duplicates".


Finally note the answer is mostly based on observation rather than the documentation. In particular the trick seems undocumented, it may be just an accidental result of how crunch works under the hood. Future upgrades may make the tool behave differently in this matter without breaking documented features.