What you would need is define a one-to-one mapping of text strings (such as "v1.0.0") onto 40 digit long strings (such as "123123..."). This is also known as a bijection, although in your case an injection (a simple one-to-one mapping from inputs to outputs, not necessarily onto) may be enough. As you note, hash functions don't necessarily ensure this mapping, but there are other possibilities, such as full-period linear congruential generators (if they take a seed that you can map one-to-one onto input string values), or other reversible functions.
However, if the set of possible input strings is larger than the set of possible output strings, then you can't map all input strings one-to-one with all output strings (without creating duplicates), due to the pigeonhole principle.
For example, you can't generally map all 120-character strings one-to-one with all 40-digit strings unless you restrict the format of the 120-character strings in some way. However, your problem of creating 40-digit output strings can be solved if you can accept limiting input strings to no more than 1040 values (about 132 bits), or if you can otherwise exploit redundancy in the input strings so that they are guaranteed to compress losslessly to 40 decimal digits (about 132 bits) or less, which may or may not be possible. See also this question.
The algorithm involves two steps:
- First, transform the string to a
BigInt
by building up the string's charCodeAt()
values similarly to the stringToInt
method given in another answer. Throw an error if any charCodeAt()
is 0x80 or greater, or if the resulting BigInt
is equal to or greater than BigInt(alphabet_length)**BigInt(output_length)
.
- Then, transform the integer to another string by taking the mod of the
BigInt
and the output alphabet's size and replacing each remainder with the corresponding character in the output alphabet, until the BigInt
reaches 0.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…