Mein Verständnis ist, dass Base58Checked immer 34 Bytes lang ist und nicht weniger als 34 Bytes sein wird, selbst wenn die ersten oder letzten Bytes der RipeMD Null sind. Wenn diese Aussage nicht wahr ist, dann ist keine der folgenden Fragen von Bedeutung.
Kurze Frage
Wie sollte die Base58Checked-Adresse für den folgenden öffentlichen Schlüssel lauten?
0414C7AB38D5CC0A39B3BF5F970C572736904D40A5879BBB05BBE16911D7F35DD3E25525877587BF91EE801393FACDED26FAFA173E457F5961BA11F602CC08FE5A
Diese Test-Website sagt, dass es so sein sollte 1vwTLMCesc1vijZbscYfnr7naV9MEy8dS
, aber wenn ich mir die Logik unten ansehe, denke ich, dass es so sein sollte 11vwTLMCesc1vijZbscYfnr7naV9MEy8dS
(beachten Sie die zweite führende).
Mehr Informationen
In dieser Schleife numberToShorten
verringert sich der Wert, wenn ich herausfinde, was in den letzten Runden der Konvertierung Null ist. (z. B. "1" für einen Wert von Null und "A" für einen Rest von neun.
Der folgende unkomprimierte öffentliche Schlüssel ist ein Beispiel für einen, der mir beim Codieren eine Null lässt, mit der ich umgehen muss:
0414C7AB38D5CC0A39B3BF5F970C572736904D40A5879BBB05BBE16911D7F35DD3E25525877587BF91EE801393FACDED26FAFA173E457F5961BA11F602CC08FE5A
Hier ist mein C#-Code:
public static String sBase58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
public static String EncodeBase58(BigInteger numberToShorten)
{
// WARNING: Beware of bignumber implementations that clip leading 0x00 bytes, or prepend extra 0x00
// bytes to indicate sign - your code must handle these cases properly or else you may generate valid-looking
// addresses which can be sent to, but cannot be spent from - which would lead to the permanent loss of coins.)
const int sizeWalletImportFormat = 51;
BigInteger base58AlphabetLength = (BigInteger)sBase58Alphabet.Length;
char[] result = new char[34];
int i = 0;
while (result.Length > i && numberToShorten >= 0)
{
var lNumberRemainder = BigInteger.Remainder(numberToShorten, base58AlphabetLength);
result[result.Length - 1 - i] = sBase58Alphabet[(int)lNumberRemainder];
if (i == 31 && numberToShorten == 0)
Console.WriteLine("found one");
//Console.WriteLine("i = " + i);
//Console.WriteLine("numberToShorten= " + numberToShorten + " (Divide this by 58 to get the value below)");
//Console.WriteLine("lNumberRemainder = " + lNumberRemainder + " (Get this position in the Base58Array and append that character)");
//Console.WriteLine("result = " + new string(result));
if (numberToShorten == 0)
{
if (i != 33)
{
// Debug
Console.WriteLine("i = " + i);
break;
}
break;
}
numberToShorten = numberToShorten / base58AlphabetLength;
i++;
}
var ret = new string(result, 33 - i, result.Length - (33 - i));
return ret;
}
public static DecodedBase58Result DecodeBase58(String base58StringToExpand)
{
DecodedBase58Result ret = new DecodedBase58Result();
BigInteger base58AlphabetLength = (BigInteger)sBase58Alphabet.Length;
BigInteger numberToExtend = BigInteger.Zero;
var charsToDecode = base58StringToExpand.ToCharArray();
for (int decodePosition = 0; decodePosition <= charsToDecode.Length - 1; decodePosition++)
{
char sCurrentCharacter = charsToDecode[decodePosition];
int index = sBase58Alphabet.IndexOf(sCurrentCharacter);
if (index == -1)
throw new Exception("Not a base58 address, " + sCurrentCharacter + " isn't a valid character.");
numberToExtend = numberToExtend * base58AlphabetLength;
numberToExtend = numberToExtend + index;
//Console.WriteLine(" i = " + (base58StringToExpand.Length - decodePosition));
//Console.WriteLine(" number = " + numberToExtend);
//Console.WriteLine(" Result = " + ret);
}
ret.BigInt = numberToExtend;
return ret;
}
Das abgeschnittene Zeichen-für-Zeichen-Gebäude der Base58-Adresse ist unten. Das Problem liegt woi=32
i = 27
numberToShorten= 610398922 (Divide this by 58 to get the value below)
lNumberRemainder = 20 (Get this position in the Base58Array and append that character)
result = MCesc1vijZbscYfnr7naV9MEy8dS
i = 28
numberToShorten= 10524119 (Divide this by 58 to get the value below)
lNumberRemainder = 19 (Get this position in the Base58Array and append that character)
result = LMCesc1vijZbscYfnr7naV9MEy8dS
i = 29
numberToShorten= 181450 (Divide this by 58 to get the value below)
lNumberRemainder = 26 (Get this position in the Base58Array and append that character)
result = TLMCesc1vijZbscYfnr7naV9MEy8dS
i = 30
numberToShorten= 3128 (Divide this by 58 to get the value below)
lNumberRemainder = 54 (Get this position in the Base58Array and append that character)
result = wTLMCesc1vijZbscYfnr7naV9MEy8dS
i = 31
numberToShorten= 53 (Divide this by 58 to get the value below)
lNumberRemainder = 53 (Get this position in the Base58Array and append that character)
result = vwTLMCesc1vijZbscYfnr7naV9MEy8dS
i = 32
numberToShorten= 0 (Divide this by 58 to get the value below)
lNumberRemainder = 0 (Get this position in the Base58Array and append that character)
result = 1vwTLMCesc1vijZbscYfnr7naV9MEy8dS
i = 33
numberToShorten= 0 (Divide this by 58 to get the value below)
lNumberRemainder = 0 (Get this position in the Base58Array and append that character)
result = 11vwTLMCesc1vijZbscYfnr7naV9MEy8dS
Ich denke, Sie haben ein grundlegendes Missverständnis der Base58-Codierung. Base58checked hat keine feste Länge; seine Länge hängt von der Anzahl der führenden Nullbytes in der Eingabe ab.
Es sollte nur eine führende „1“ vorhanden sein, die den Adresstyp „Hauptnetz“ angibt. Eine zweite führende "1" würde ein ganzes führendes Nullbyte (0x00) im Pubkey-Hash selbst anzeigen, was in diesem Fall nicht zutrifft, da Ihr sha256+ripemd-160 0a33807d0764e0bc71677fbef234d4989d0c198e ist. Es hat nur ein führendes Nullnibble.
0a33
. Diese Null im RipeMD bringt mich durcheinander ... ich bin mir nicht sicher, was ich damit machen soll ...04448212C17B6D5FD88E316AFB1D79432D7BC983567CFD5945DFE2E54C2F2A5F69E234588C4C43EB7F1E7285C0F6CBC61A31385FADF7663305A6F4FF494D621F8D
Das Problem liegt in der Interpretation von Nullen in meinem Code in den höchstwertigen Bits (MSB). Ich habe meinen Code aktualisiert, um den korrekten base58hash-Code anzugeben (wie vom QT-Client verifiziert).
Da die Base58-geprüfte Kodierung immer mit 25 Bytes arbeitet (RIPEMD + Network + 4 Byte Checksum)
Der folgende öffentliche Schlüssel hat ein MSB von Null
04EF12BF0C1EC3646CE6828E7D59B4111381EB8A3DF2BBB89D53254AD70BE27498C76F6E2AB3B7FC15A69B0A44AC84659728146E46670E3C66B14222FAB82C8CF6
Da das MSB zwei Nullen hat, basiert der Base58-Hash auf einer Null1EVEDmVcV7iPvTkaw2gk89yVcCzPzaS6B7
Der folgende öffentliche Schlüssel hat ein MSB von zwei Nullen
04BAE942CC53D51498CD2E1576C1C43F125302DEF76A8A470B818C8D6BB65A82D679232E294E6F2D1C78F35BAA272EF1585F2FFE8B88769B02FBCEDD070CE50D4B
Da das MSB zwei Nullen hat, basiert der Base58-Hash auf zwei Nullen11ujQcjgoMNmbmcBkk8CXLWQy8ZerMtuN
Der folgende öffentliche Schlüssel hat ein MSB von drei Nullen
04AD8A68DF6A4553BEDD234BF2D7BFB5F0C5830F13C3A5F814AAFC03E2C92602EC1047CFE67F14D499B55F57BBE104D29E9BF6C9849771B4E3AE46FFB76FE3DFCD
Da das MSB drei Nullen hat, hasht der Base58 drei Nullen111oeV7wjVNCQttqY63jLFsg817aMEmTw
Diego Bass