2016-03-30 10 views
4

Lassen Sie "awids" 12 Zeichen Länge IDs in der Basis 64 (A-Z a-z 0-9 "-" "@"). Dies ist die Eingabe.kann nicht korrekt codieren und entschlüsseln mit java.util.Base64

Mein Ziel ist es, ein bijektives Mapping zwischen diesen awids und UUID s zu erstellen, mit einigen Paddings, die als erste Eingabe die awids haben.

Beim Versuch, java.util.Base64zu verwenden, bekomme ich nach einer Decodierung und einer Codierung nicht wieder den Anfangswert. Was ist der dumme Fehler, den ich mache? :)

Mit dem reproduzierbaren Beispiel I unter dem Ausgang präsentieren ist falsch, weil die Eingabezeichenfolge nicht zurück nach einem decode() bekommen wird - encode() und die Bijektion nicht erhalten wird (Q39s/L und Q39s/A Karte beide auf den gleichen Wert).

 
    ------------------------------------------>Q39s/L (6 [51 33 39 73 2f 4c]) 
    4 [43 7f 6c fc] -> 6 [51 33 39 73 2f 41] ->Q39s/A (6 [51 33 39 73 2f 41]) 
    4 [43 7f 6c fc] -> 6 [51 33 39 73 2f 41] ->Q39s/A (6 [51 33 39 73 2f 41]) 

Hier a ein reproduzierbares Beispiel:

 


    import java.nio.charset.StandardCharsets; 
    import java.util.Base64; 
    import java.util.StringJoiner; 

    public class StackOverflowQuestion { 

     public static void main(String[] args) { 

     String halfAwid = "Q39s/L"; 

     byte[] sigBits = Base64.getDecoder().decode(halfAwid.getBytes(StandardCharsets.UTF_8)); 

     byte[] actualSigBits = Base64.getEncoder().withoutPadding().encode(sigBits); 

     String actualHalfAwid = new String(actualSigBits, StandardCharsets.UTF_8); 

     byte[] sigBits2 = Base64.getDecoder().decode(halfAwid.getBytes(StandardCharsets.UTF_8)); 
     byte[] actualSigBits2 = Base64.getEncoder().withoutPadding().encode(sigBits2); 
     String actualHalfAwid2 = new String(actualSigBits2, StandardCharsets.UTF_8); 

     System.out.println("----------------------------------------------> " 
      + halfAwid + " (" + toHexString(halfAwid) + ") " 
      + "\n" 
      + " " 
      + toHexString(sigBits) + " -> " 
      + toHexString(actualSigBits) + " -> " 
      + actualHalfAwid + " (" + toHexString(actualHalfAwid) + ") " 
      + "\n" 
      + " " 
      + toHexString(sigBits2) + " -> " 
      + toHexString(actualSigBits2) + " -> " 
      + actualHalfAwid2 + " (" + toHexString(actualHalfAwid2) + ")" 
      + ""); 
     } 

     private static String toHexString(byte[] bytes) { 
     StringJoiner joiner = new StringJoiner(" ", "" + bytes.length + " [", "]"); 
     for (byte b : bytes) { 
      joiner.add(String.format("%02x", b)); 
     } 
     return joiner.toString(); 
     } 

     private static String toHexString(String text) { 
     return toHexString(text.getBytes()); 
     } 
    } 

Zögern Sie nicht, alle anderen Fehler, die ich in dem Code zu tun zeigen, auch wenn sie nicht direkt auf die Frage in Zusammenhang steht. Vielen Dank.

Antwort

2

Die Base64-Codierung ist keine bijektive Zuordnung für alle Eingabegrößen, wenn Sie die codierten Daten als eine Folge von ganzen Bytes (oder ASCII-Zeichen) behandeln. Base64 codiert Einheiten von acht Bits zu Einheiten von sechs Bits (ergibt 64 mögliche Kombinationen für jede Einheit). Wenn Sie also vier Bytes, also 4×8=32 Bits, codieren, erhalten Sie 32/6=5⅓ Einheiten ausgegeben, was bedeutet, dass die sechste Einheit der Ausgabe wird nicht alle Bits verwenden. Wenn Sie also eine beliebige Zeichenkette behandeln, die aus sechs der 64 definierten Zeichen besteht, die Base64-codiert sind, projizieren Sie eine Folge von 64-Zeichen-Kombinationen in eine "Quell" -Sequenz von sechs Bytes mit 256-Zeichen-Kombinationen ein Datenverlust.

Sie können die Base64-Codierung als bijektive Zuordnung verwenden, wenn Sie Eingabegrößen auswählen, die auf eine ganze Anzahl von Einheiten projiziert werden können, z. Offensichtlich können sechs Quellbytes als acht Base64-codierte Bytes codiert werden. Aber es funktioniert nicht für sechs codierte Bytes. Interessanterweise wird es für Ihre tatsächlich gewünschte Größe funktionieren, wenn neun Quellbytes zu genau zwölf kodierten Bytes codiert werden: 9×8=72, .

+0

Sie haben Recht. Vielen Dank. Ich werde die 12 verschlüsselten Zeichen in 8 + 4 Zeichen teilen, was mich zu 6 Bytes (msb) + 3 Bytes (lsb) führen wird. – Costin

+0

Klare Ressource, die ich nach dem Posten der Frage gefunden habe (ja, ich weiß, ich hätte damit anfangen sollen) https://en.wikipedia.org/wiki/Base64 – Costin

Verwandte Themen