

Wikibooksに載っているCでbase64のデコード(下記のコード)についてわからないことがあります

[Algorithm Implementation/Miscellaneous/Base64 - Wikibooks, open books for an
open
world](https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64#C_2)

char d[]のデータは何を表しているのでしょうか?  
なぜ、66(INVALID)が多いのでしょうか?

また、6bitの値を24bitにまとめる際に`buf = buf << 6 |
c;`となっていますが、`c`との論理和をとることにはどのような意味があるのでしょうか?

[code]

    
    #define WHITESPACE 64
    #define EQUALS     65
    #define INVALID    66
    
    static const unsigned char d[] = {
        66,66,66,66,66,66,66,66,66,66,64,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,62,66,66,66,63,52,53,
        54,55,56,57,58,59,60,61,66,66,66,65,66,66,66, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
        10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,66,66,66,66,66,66,26,27,28,
        29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66
    };
    
    int base64decode (char *in, size_t inLen, unsigned char *out, size_t *outLen) { 
        char *end = in + inLen;
        char iter = 0;
        uint32_t buf = 0;
        size_t len = 0;
    
        while (in < end) {
            unsigned char c = d[*in++];
    
            switch (c) {
            case WHITESPACE: continue;   /* skip whitespace */
            case INVALID:    return 1;   /* invalid input, return error */
            case EQUALS:                 /* pad character, end of data */
                in = end;
                continue;
            default:
                buf = buf << 6 | c;
                iter++; // increment the number of iteration
                /* If the buffer is full, split it into bytes */
                if (iter == 4) {
                    if ((len += 3) > *outLen) return 1; /* buffer overflow */
                    *(out++) = (buf >> 16) & 255;
                    *(out++) = (buf >> 8) & 255;
                    *(out++) = buf & 255;
                    buf = 0; iter = 0;
    
                }   
            }
        }
    
        if (iter == 3) {
            if ((len += 2) > *outLen) return 1; /* buffer overflow */
            *(out++) = (buf >> 10) & 255;
            *(out++) = (buf >> 2) & 255;
        }
        else if (iter == 2) {
            if (++len > *outLen) return 1; /* buffer overflow */
            *(out++) = (buf >> 4) & 255;
        }
    
        *outLen = len; /* modify to reflect the actual output size */
        return 0;
    }
    
    
[/code]


CC BY-SA 3.0
2017-02-10T14:04:57.647
32565
2017-02-10T14:47:47.793
5246
question
c decode base64
Cでのbase64デコードについて


`d`はASCIIコードと64進数の対応を表しています。  
ですので配列の要素数は1バイト分の`256`で、インデックスが`A`～`Z`、`a`～`z`、`0`-`9`、`+`、`/`に対応する要素に`0`～`63`が割り振られています。


CC BY-SA 3.0
2017-02-10T14:24:22.537
32567
2017-02-10T14:24:22.537
5750
32565
answer


Base64とASCIIコードに関する基本的な知識が必要です。

Base64と言うのは6bitの値`000000`(=0)...`111111`(=63)の64通りのビットパターンを以下の規則によって、ASCII文字のうちの64個を使用して表します。

[code]

    A (0x41=65)  -> 000000(=0)
    B (0x42=66)  -> 000001(=1)
    :
    Z (0x5A=90)  -> 011001(=25)
    a (0x61=97)  -> 011010(=26)
    b (0x62=98)  -> 011011(=27)
    :
    z (0x7A=122) -> 110011(=51)
    0 (0x30=48)  -> 110100(=52)
    1 (0x31=49)  -> 110101(=53)
    :
    9 (0x39=57)  -> 111101(=61)
    + (0x2B=43)  -> 111110(=62)
    / (0x2F=47)  -> 111111(=63)
    
[/code]

例えばASCII文字の`B`は、Base64では`000001`(=1)を表すので、`B`の文字コード(0x42=66)をインデックスとして`d[66]`をアクセスすると、値が`1`になるようにできています。0...63の値を表す文字をコメントとして付け加えてやると、`d[]`はこんな風に書けます。

[code]

    static const unsigned char d[] = {
    //                                \n
        66,66,66,66,66,66,66,66,66,66,64,66,66,66,66,66,
    //
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
    //                                    +           /
        66,66,66,66,66,66,66,66,66,66,66,62,66,66,66,63,
    //   0  1  2  3  4  5  6  7  8  9           =
        52,53,54,55,56,57,58,59,60,61,66,66,66,65,66,66,
    //      A  B  C  D  E  F  G  H  I  J  K  L  M  N  O
        66, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
    //   P  Q  R  S  T  U  V  W  X  Y  Z
        15,16,17,18,19,20,21,22,23,24,25,66,66,66,66,66,
    //      a  b  c  d  e  f  g  h  i  j  k  l  m  n  o
        66,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
    //   p  q  r  s  t  u  v  w  x  y  z
        41,42,43,44,45,46,47,48,49,50,51,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
        66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66
    };
    
[/code]

**_char d[]のデータは何を表しているのでしょうか?_**

つまり文字コードをインデックスとして`d[]`の値を求めると、Base64でその文字の表す値が求められるわけです。

**_なぜ、66(INVALID)が多いのでしょうか?_**

1バイトで表される文字コードのうち、Base64で意味を持つのは上記の64文字の他はごくわずか(`=`など)しかありませんので、必然的に他の文字コードを表す位置は無効(INVALID)となります。

**_cとの論理和をとることにはどのような意味があるのでしょうか?_**

Base64では、上記のように1文字が6ビット、つまり4文字で24ビットを表します。`ABCD`と言う4文字を24ビットのデータに直す時に`ABC`まで読んだ後では

[code]

    buf=     00000000000000000000000001000010
                           <--A-><--B-><--C->
    
[/code]

となっているので、

[code]

    buf<<6 = 00000000000000000001000010000000
                     <--A-><--B-><--C->
      c =                            00000011 <- cは`D`から変換
                                       <--D->
    
[/code]

この2つの論理和をとることにより、計算後の`buf`の値が:

[code]

    buf(新)= 00000000000000000001000010000011
                     <--A-><--B-><--C-><--D->
    
[/code]

のように、`A`, `B`, `C` そして `D`の4文字の表す6ビットの値をつなげた24ビットの値にできるわけです。


CC BY-SA 3.0
2017-02-10T14:47:47.793
32568
2017-02-10T14:47:47.793
13972
32565
answer