7-Bit/8-Bit-Konvertierung

Manchmal ist es aus historischen oder technischen Gründen notwendig, nur Teile eines Bytes für eine Botschaft zu verwenden. Beispielsweise dürfen klassische E-Mails nur aus 7-Bit-ASCII-Zeichen bestehen. Möchte man andere Daten über das E-Mail-Format austauschen, wird es nötig, diese zuvor in ein mit E-Mails kompatibles Format umzuwandeln.

Ähnliches trifft auch auf die kürzlich vorgestellte Verschlüsselungsmethode für Lokalteile von E-Mail-Adressen zu. Während ein Byte mit seinen acht Bits grundsätzlich 256 verschiedene Zustände annehmen kann, erwartet jene Methode Eingaben nur im Bereich 0–127, es können also nur sieben Bits jedes Bytes für die Nachricht genutzt werden. Wandelt man allerdings 8-Bit-kodierte Daten zuvor in eine 7-Bit-kodierte Form um, lassen auch sie sich mit einer so beschränkten Methode verarbeiten.

Eine von zahlreichen Möglichkeiten einer solchen 8-Bit-7-Bit-Konvertierung wird auf dieser Seite dargestellt und in PHP exemplarisch realisiert.

Beispielhafte Darstellung

In der folgenden Tabelle wird eine Botschaft „süßer Käse“ in einer 8-Bit-Kodierung ISO 8859-1 dargestellt. Die farbliche Unterlegung besitzt keine inhaltliche Bedeutung, sondern dient nur der Veranschaulichung der Umwandlung von acht zu sieben Bits pro Byte und umgekehrt.

Zeichen 8 Bits je Byte 7 Bits je Byte
s
ü
ß
e
r

K
ä
s
e
01110011
11111100
11011111
01100101
01110010
00100000
01001011
11100100
01110011
01100101
.0111001
.1111111
.1101100
.0110111
.0110101
.0010010
.0100000
.1001011
.1110010
.0111000
.0110011
.....101

Fürs Umwandeln von einer 8- zu einer 7-Bit-kodierten Nachricht wird jeweils ein Block aus sieben Bytes à acht Bits in zwei Dreiecke, blau und gelb, unterteilt. Die 7-Bit-kodierte Nachricht ergibt sich, wenn das blaue Dreieck einen Schritt nach rechts und das gelbe Dreieck einen Schritt nach unten verschoben wird.

Die Umwandlung einer 7-Bit-kodierten in eine 8-Bit-kodierte Nachricht funktioniert dementsprechend so: Jeweils ein Block aus acht Bytes à sieben (genutzten) Bits wird in zwei Dreiecke unterteilt. Das blaue Dreieck wird einen Schritt nach links, das gelbe einen Schritt nach oben verschoben.

PHP-Quelltext

<?php

/* prlbr_78
*  is a class that converts between 7- and 8-bit encoded strings
*/

class prlbr_78 {    

    private static 
$up = array (137153163127);    
    private static 
$down = array (2542522482402241921280);

    
/* to7
    *  converts an 8-bit encoded $input string into a 7-bit encoded string
    */
    
public static function to7 ($input) {

        
// the empty string is encoded as empty string
        
if ($input === ''):
            return 
'';
        endif;

        
// initialize the output string and carry
        
$output '';
        
$carry 0;

        for (
$i 0$length strlen ($input); $i $length$i++):
            
// calculate the round number modulo 7
            
$r $i 7;
            
// add the carry as a character to the output every seventh round
            
if (($r === 0) && ($i !== 0)):
                
$output .= chr ($carry);
                
$carry 0;
            endif;
            
// represent an input byte as 8-bit integer
            
$integer ord ($input[$i]);
            
// add a 7-bit output byte created from the r-bit carry and the
            // lower 7 - r bits from the 8-bit input integer
            
$output .= chr ($carry | (($integer self::$down[$r]) >> 1));
            
// save the other r + 1 bits of the 8-bit integer as new carry
            
$carry $integer self::$up[$r];
        endfor;
        
        
// add the remaining carry as a character to the output
        
return $output chr ($carry);

    } 
// public static function to7
    

    /* to8
    *  converts a 7-bit encoded $input string into an 8-bit encoded string
    */
    
public static function to8 ($input) {
    
        
// initialize the output string and carry
        
$output '';
        
$carry 0;
        
        for (
$i 0$length strlen ($input); $i $length$i++):
            
// calculate the round number modulo 8
            
$r $i 8;
            
// represent an input byte as a 7-bit integer
            
$integer ord ($input[$i]);
            
// add an 8-bit output byte created from the 8 - r bits carry
            // and r bits from the 7-bit integer
            
if ($r !== 0):
                
$output .= chr ($carry | ($integer self::$up[$r 1]));
            endif;
            
// save the other 7 - r bits of the 7-bit integer as new carry
            
$carry = ($integer << 1) & self::$down[$r];
        endfor;

        return 
$output;

    } 
// public static function to8

// class prlbr_78

// end