/
659.txt
1458 lines (1132 loc) · 67.1 KB
/
659.txt
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
[5] [DFN[Base64]] は、[[オクテット列]]を64種類の[[英数字]]などに転写する[[符号化方式]]の一種です。
[NOTE[
[135] 一般に [Q[base 64]] は[Q[64進数]]を意味します。特に[[大文字]]で [Q[Base64]]
と書いた場合や、[[インターネット]]で言われる場合には、 [[MIME]] の
[[Base64]] を指します。
]NOTE]
[196] 元々[[インターネットメール]]で[[バイナリー]]データを転送するための仕組みとして考案されました。
[[文字コード]]の異なる様々な[[システム]]間で転送される[[電子メール]]では、
任意の[[バイナリー]]データを転送することができなかったため、
限られた[[ASCII文字]]で[[符号化]]する手段が必要でした。
その後徐々に適用範囲が拡大され多種多様な目的で使われるようになりました。
[58] いくつかのバリエーションがあり、どれを使うべきなのか注意が必要です。
* 仕様書
[REFS[
- [115] [CITE@en[RFC 4648 - The Base16, Base32, and Base64 Data Encodings]] ([TIME[2018-01-28 17:12:45 +09:00]]) <https://tools.ietf.org/html/rfc4648#section-4>
- [830] [CITE@en[RFC 4648 - The Base16, Base32, and Base64 Data Encodings]] ([TIME[2012-04-15 07:19:30 +09:00]] 版) <https://tools.ietf.org/html/rfc4648#section-5>
- [86] '''[CITE@en[Infra Standard]] ([TIME[2017-08-17 16:48:46 +09:00]]) <https://infra.spec.whatwg.org/#forgiving-base64>'''
]REFS]
* 符号化方式の概要
[27]
オクテット値3つ (8ビット×3 = 24ビット) を4文字 (6ビット×4)
で表現します。ですからデータ量は3分の4倍、33%増加になります。
64文字 (と、特殊用途に使われる [CODE(char)[=]]) は、
[[ISO/IEC 646の版]]で全て共通に存在し、しかも [[EBCDIC]]
の全ての版で使える文字から選ばれたそうです。
[FIG(list)[ [116] [DFN[Table 1: The Base 64 Alphabet]]
[PRE[
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
]PRE]
]FIG]
[28]
Base64 は6ビット単位になりますが、オクテット列の長さと必ずしも
一致する (6と8の公倍数の長さになる) とは限らないので、
[CODE(char)[=]] で埋めて調節します。この結果、 Base64 data は必ず
4の整数倍の長さになります。
* 符号化
[136] '''[[Base64]] による[[符号化]]'''は、
任意の[[バイト列]]を [[Base64]] の [[ASCII文字列]]へと変換する処理です。
[89] [DFN[forgiving-base64 encode]] は、[[バイト列]][VAR[データ]]を次のようにします
[SRC[>>86]]。
[FIG(steps)[
= [90] [VAR[データ]]に [[RFC 4648]] 第4章 [[Base64]] を適用した結果を返します。
]FIG]
[117] [[RFC 4648]] 第4章 [[Base64]] は、
[[バイト列]][VAR[データ]]を次のようにします。
[FIG(steps)[
= [118] [VAR[塊]]を、[[空バイト列]]に設定します。
= [202] [VAR[結果]]を、[[空文字列]]に設定します。
= [119] [VAR[データ]]の各[[バイト]][VAR[バイト]]について、順に、
== [120] [VAR[塊]]の末尾に、[VAR[バイト]]を追加します。
== [122] [VAR[塊]]の[F[長さ]]が [N[3]] の場合、
=== [198] [VAR[ビット列0]]を、[VAR[塊]] [ [N[0]] ] の上位6ビットに設定します。
=== [199] [VAR[ビット列1]]を、[VAR[塊]] [ [N[0]] ] の下位2ビットを上位2ビット、
[VAR[塊]] [ [N[1]] ] の上位4ビットを下位4ビットとする[[ビット列]]に設定します。
=== [200] [VAR[ビット列2]]を、[VAR[塊]] [ [N[1]] ] の下位4ビットを上位4ビット、
[VAR[塊]] [ [N[2]] ] の上位2ビットを下位2ビットとする[[ビット列]]に設定します。
=== [201] [VAR[ビット列3]]を、[VAR[塊]] [ [N[2]] ] の下位6ビットに設定します。
=== [216] [VAR[結果]]の末尾に、
[VAR[ビット列0]]、[VAR[ビット列1]]、[VAR[ビット列2]]、[VAR[ビット列3]]のそれぞれが
[[The Base 64 Alphabet]] の第1列の値である行の第2列の値を順に追加します。
=== [215] [VAR[塊]]を、[[空バイト列]]に設定します。
= [204] [VAR[塊]]の[F[長さ]]が [N[2]] の場合、
== [205] [VAR[ビット列0]]を、[VAR[塊]] [ [N[0]] ] の上位6ビットに設定します。
== [206] [VAR[ビット列1]]を、[VAR[塊]] [ [N[0]] ] の下位2ビットを上位2ビット、
[VAR[塊]] [ [N[1]] ] の上位4ビットを下位4ビットとする[[ビット列]]に設定します。
== [207] [VAR[ビット列2]]を、[VAR[塊]] [ [N[1]] ] の下位4ビットを上位4ビット、
[N[0]] を下位2ビットとする[[ビット列]]に設定します。
== [208] [VAR[ビット列3]]を、 [I[(pad)]] に設定します。
== [217] [VAR[結果]]の末尾に、
[VAR[ビット列0]]、[VAR[ビット列1]]、[VAR[ビット列2]]、[VAR[ビット列3]]のそれぞれが
[[The Base 64 Alphabet]] の第1列の値である行の第2列の値を順に追加します。
= [209] [VAR[塊]]の[F[長さ]]が [N[1]] の場合、
== [210] [VAR[ビット列0]]を、[VAR[塊]] [ [N[0]] ] の上位6ビットに設定します。
== [211] [VAR[ビット列1]]を、[VAR[塊]] [ [N[0]] ] の下位2ビットを上位2ビット、
[N[0]] を下位4ビットとする[[ビット列]]に設定します。
== [212] [VAR[ビット列2]]を、 [I[(pad)]] に設定します。
== [213] [VAR[ビット列3]]を、 [I[(pad)]] に設定します。
== [203] [VAR[結果]]の末尾に、
[VAR[ビット列0]]、[VAR[ビット列1]]、[VAR[ビット列2]]、[VAR[ビット列3]]のそれぞれが
[[The Base 64 Alphabet]] の第1列の値である行の第2列の値を順に追加します。
= [214] [VAR[結果]]を返します。
]FIG]
-*-*-
[123] 次の文脈で用いられます。
[FIG(middle list)[ [124] [[forgiving-base64 encode]] の[[応用]]
- [CODE[atob]]
- [CODE[Sec-WebSocket-Key:]]
]FIG]
* 復号
[137] '''[[Base64]] による[[復号]]'''は、
[[Base64]] の [[ASCII文字列]]をその表す[[バイト列]]へと変換する処理です。
[91] [DFN[forgiving-base64 decode]] は、[[文字列]][VAR[データ]]を次のようにします
[SRC[>>86]]。
[FIG(steps)[
= [92] [VAR[データ]]から[[ASCII空白]]をすべて削除します。
= [93] [VAR[データ]]の[F[長さ]] [[%]] [N[4]] が [N[0]] の場合、
== [94] [VAR[データ]]の末尾が [CODE[==]] か [CODE[=]] なら、これを削除します。
= [95] [VAR[データ]]の[F[長さ]] [[%]] [N[4]] が [N[1]] の場合、
== [96] [[失敗]]を返し、ここで停止します。
= [97] [VAR[データ]]に [CODE[+]]、[CODE[/]]、[[ASCII英数字]]のいずれでもない[[符号位置]]が含まれる場合、
== [98] [[失敗]]を返し、ここで停止します。
= [99] [VAR[出力]]を、新しい[[空バイト列]]に設定します。
= [100] [VAR[バッファー]]を、新しい空[[ビット列]]に設定します。
= [101] [VAR[データ]]に含まれる[[符号位置]][VAR[符号位置]]について、順に、
== [102] [VAR[n]] を、[[RFC 4648]] [[Table 1: The Base 64 Alphabet]]
の第2列が[VAR[符号位置]]である[[行]]の第1列の値に設定します。
== [103] [VAR[バッファー]]の末尾に、[VAR[n]] と等しく6ビットで[[大エンディアン]]の[[ビット列]]を追加します。
== [104] [VAR[バッファー]]の[F[長さ]]が24ビットの場合、
=== [105] [VAR[バッファー]]を3桁の[[大エンディアン]][[8ビット整数]]と解釈したものを、
[VAR[出力]]の末尾に順に追加します。
=== [106] [VAR[バッファー]]を、空に設定します。
= [107] [VAR[バッファー]]の[F[長さ]]が12ビットの場合、
== [108] [VAR[バッファー]]の先頭8ビットを
1桁の[[大エンディアン]][[8ビット整数]]と解釈したものを、
[VAR[出力]]の末尾に順に追加します。
= [109] [VAR[バッファー]]の[F[長さ]]が18ビットの場合、
== [110] [VAR[バッファー]]の先頭16ビットを
2桁の[[大エンディアン]][[8ビット整数]]と解釈したものを、
[VAR[出力]]の末尾に順に追加します。
= [111] [VAR[出力]]を返します。
]FIG]
[125] 次の文脈で用いられます。
[FIG(middle list)[ [126] [[forgiving-base64 decode]] の[[応用]]
- [CODE[btoa]]
- [[[CODE[data:]] URL処理器]]
]FIG]
[225] [[仕様書]]上 [[forgiving-base64 decode]] は入力が[[文字列]]として定義されています。
[[[CODE[data:]] URL処理器]]では入力が[[バイト列]]となるため、
[[同型復号]]を通しています。
* Base64 の仕様書とバリエーション
[138] 「[[Base64]]」と呼ばれているものは、
注意して観察すると色々なバリエーションがあることがわかります。
[[Base64]] は有用で様々な用途に活用されてきたのですが、
その過程で[[仕様書]]の規定の部分を[[コピペ]]したり、
用途依存の細かい改変を加えたりされたため、
単一の定義と言えるものが存在しなくなってしまいました。
[23] どの[[仕様書]]の定義を参照するかという[[政治的]]な問題の他に、
技術的に様々な違いがありますが、
主として次のような観点で比較できます。
- [139] [[字母]]。[[ASCII英数字]]はそのまま使われることが多いですが、
それ以外の[[記号]]は差し替えられていることがあります。
- [31] [[詰め]]。末尾の余分なデータを表す「詰め文字」を必須とするもの、
省略可能とするもの、禁止しているものがあります。
- [140] [[空白]]・[[改行]]。[[行長]]を固定するもの、
制限するもの、[[改行]]を禁止するものがあります。
- [141] [[誤り処理]]。不正な入力が与えられたときの回復処理を規定するもの、
処理を中断することが求められるもの、
明確な規定がないものがあります。
** 電子メールの Base64
[145] [[Base64]] は最初に [[PEM]] で導入されました。
[[PEM]] は特別な名前を与えず、単に「printable encoding」 (印字可能符号化)
と呼んでいました。 [SRC[>>142, >>143, >>144]]
[146] [[字母]]や[[詰め]]については既に後の時代と同じ規定となっていました。
符号化後の最終行以外の各行は、64文字としなければならないとされていました。
誤り処理の明確な規定はありませんでした。
[147] [[字母]]は、当時使われていた [[ASCII]] や [[EBCDIC]]
を[[文字コード]]とするシステムで問題なく扱えるものが選ばれていました。
行長制限は、[[SMTP]] の制約に由来するものでした。
[148] [[PEM]] の [[Base64]] は、あくまで [[PEM]] のプロトコルの一部を構成するもので、
汎用的な利用を想定したものではありませんでした。 [[Base64]] の[[字母]]に加え、 [[PEM]]
での利用上特別な意味を持った区切りの[[文字]] [CODE[*]]
も[[字母]]の1つとして挙げられていました。
[166] 符号化の方法は規定されていましたが、復号の方法は明確には定められていませんでした。
[FIG(list middle)[ [157] [[PEM]] [[Base64]] の[[応用]]
- [[PEM]] [[署名]]
]FIG]
[REFS[
- [142] [CITE@en[RFC 989 - Privacy enhancement for Internet electronic mail: Part I: Message encipherment and authentication procedures]] ([TIME[2018-01-22 01:26:57 +09:00]]) <https://tools.ietf.org/html/rfc989#section-4.3>
- [143] [CITE@en[RFC 1040 - Privacy enhancement for Internet electronic mail: Part I: Message encipherment and authentication procedures]] ([TIME[2018-01-21 19:31:09 +09:00]]) <https://tools.ietf.org/html/rfc1040#section-4.3.2.4>
- [144] [CITE@en[RFC 1113 - Privacy enhancement for Internet electronic mail: Part I - message encipherment and authentication procedures]] ([TIME[2018-01-28 19:33:06 +09:00]]) <https://tools.ietf.org/html/rfc1113#section-4.3.2.4>
]REFS]
-*-*-
[25] [[MIME]] は、 [[PEM]] から派生して独自の [[Base64]] を規定しました
[SRC[>>149, >>150, >>43]]。 [[Base64]] という名称はここで与えられました。
[151] 基本的には [[PEM]] と同内容ですが、いくつかの違いがありました。
[152] [[MIME]] では特別な意味を持たない [CODE[*]] は[[字母]]に含まれませんでした。
[153] 行長制限は、76文字[[以下]]とされました。
[154] [[字母]]以外は無視するべきことと定められ、
[[字母]]、[[改行]]、[[空白]]以外は誤りと考えられるため警告を出したり、
場合によっては拒絶するのもよいとされました。
[155] [[RFC 1521]] は [CODE[====]] のようなあり得ない[[詰め]]を無視することを定めていましたが、
改訂版の [[RFC 2045]] ではなぜか削除されました。
[156] このように [[PEM]] とは違って誤り処理が定められたことは注目に値しますが、
起こり得るすべての誤りケースをカバーできてはいませんでした。
[FIG(list middle)[ [158] [[MIME]] [[Base64]] の[[応用]]
- [[MIME]] [CODE(MIME)[Base64]] [[転送符号化]]
- [CODE(MIME)[[[x-gzip64]]]] 転送符号化
- [CODE(MIME)[[[Content-MD5]]:]] ヘッダー
- [CODE(822)[Face:]] ヘッダー
- MIME [CODE(ABNF)[[[encoded-word]]]] [CODE(MIME)[B]] 符号化
- [[uuencode]] 風表現 >>3
- [32] [CODE(ABNF)[[[instance-digest]]]]
([CODE(ABNF)[[[digest-algorithm]]]] が
[CODE(HTTP)[[[SHA]]]] または [CODE(HTTP)[[[MD5]]]] の時)
- [[Atom 0.3]] [CODE[mode=base64]] (→ [[RFC 2045]])
- [[OAuth 1.0]] [CODE[HMAC-SHA1]] (→ [[RFC 2045]])
- [[OAuth 1.0]] [CODE[RSA-SHA1]] (→ [[RFC 2045]])
]FIG]
[170] [CODE[Content-MD5:]] を定める [[RFC 1864]] は「base64」としか言っておらず、
どこで規定される何を指すのかは曖昧ですが、 [[MIME]] の追加機能ですから、
[[MIME]] の定義と解釈するのが自然でしょう。
[[ヘッダー値]]として使うため[[改行]]を自由には挿入できないはずですが、
符号化される値は十分短いため、実際には問題とはなりません。
[827] [[基本認証]]の [[credentials]] では [[MIME]] の [[RFC 1521]] や [[RFC 2045]] の
[[Base64]] から行長制限を撤廃したものと規定されていました [SRC[>>826, >>183, >>828]]。
厳密に読めば制限が撤廃されたのは良いとして、[[改行]]が認められるのかは不明でした。
この点は後の改訂で明確化されました (>>185)。
[171] [CODE[data:]] を定める [[RFC 2397]] は「base64」としか言っておらず、
どこで規定される何を指すのかは曖昧ですが、[[参考文献]]として示された
[[MIME]] の [[RFC 2045]] だけが文脈から推測できる候補でした。
しかし行長制限の扱いと [[URL]] としての構文の矛盾など、
[[著者]]の意図を断言するのは難しい状態でした。
(出版から20年後にようやく [CITE[Fetch Standard]] により明確化されることになります。)
[224] [[OAuth 1.0]] の [CODE[HMAC-SHA1]] や [CODE[RSA-SHA1]]
は [[RFC 2045]] の [[Base64]] を採用していました。
符号化される値は十分短いため、
行長制限に達することはありません。
[REFS[
- [149] [CITE@en[RFC 1341 - MIME (Multipurpose Internet Mail Extensions): Mechanisms for Specifying and Describing the Format of Internet Message Bodies]] ([TIME[2018-01-21 20:29:24 +09:00]]) <https://tools.ietf.org/html/rfc1341#page-17>
- [150] [CITE@en[RFC 1521 - MIME (Multipurpose Internet Mail Extensions) Part One: Mechanisms for Specifying and Describing the Format of Internet Message Bodies]] ([TIME[2018-01-21 18:17:10 +09:00]]) <https://tools.ietf.org/html/rfc1521#section-5.2>
- [43] [CITE@en[RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies]] ([TIME[2015-03-22 13:13:15 +09:00]] 版) <https://tools.ietf.org/html/rfc2045#section-6.8>
- [826] [CITE@en[RFC 1945 - Hypertext Transfer Protocol -- HTTP/1.0]] ([TIME[2012-02-18 23:25:56 +09:00]] 版) <https://tools.ietf.org/html/rfc1945#section-11.1>
- [183] [CITE@en[RFC 2068 - Hypertext Transfer Protocol -- HTTP/1.1]] ([TIME[2018-01-28 09:40:08 +09:00]]) <https://tools.ietf.org/html/rfc2068#section-11.1>
- [828] [CITE@en[RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication]] ([TIME[2012-01-09 21:04:30 +09:00]] 版) <https://tools.ietf.org/html/rfc2617#section-2>
[FIG(quote)[
[FIGCAPTION[
[73] [CITE@en[draft-ietf-usefor-cancel-lock-01 - Cancel-Locks in Usenet articles.]]
([TIME[2016-10-31 14:51:38 +09:00]])
<https://tools.ietf.org/html/draft-ietf-usefor-cancel-lock-01>
]FIGCAPTION]
> The encoding of the binary key or lock is performed in accordance with
the Base64 Transfer Encoding defined in '''['''RFC-2045''']'''.
]FIG]
]REFS]
-*-*-
[74] [[PGPメッセージ交換形式]]もまた、独自に [[Base64]] を規定しており、
[DFN[Radix-64]] と呼んでいます [SRC[>>159, >>160, >>161]]。
[162] [[RFC 1991]] の規定は曖昧なものでした。
[163] [[RFC 2440]] や [[RFC 4880]] は、 [[MIME]] の [[RFC 2045]]
と同内容の [[Base64]] を規定しています。歴史的経緯によるものか、
[[MIME]] の [[Base64]] への言及は一切ありません。
しかし明らかに同じテキストを流用しています。
ですが全く同じではなく、解釈次第ではこちらの定義の方が厳密ともいえます。
[FIG(list middle)[ [46] [[Radix-64]] の[[応用]]
- [[ASCII Armor]]
]FIG]
[REFS[
- [159] [CITE@en[RFC 1991 - PGP Message Exchange Formats]] ([TIME[2018-01-28 20:52:48 +09:00]]) <https://tools.ietf.org/html/rfc1991#section-2.4>
- [160] [CITE@en[RFC 2440 - OpenPGP Message Format]] ([TIME[2018-01-21 17:16:48 +09:00]]) <https://tools.ietf.org/html/rfc2440#section-6.3>
- [161] [CITE@en[RFC 4880 - OpenPGP Message Format]] ([TIME[2018-01-21 18:54:46 +09:00]]) <https://tools.ietf.org/html/rfc4880#section-6.3>
]REFS]
** IETF の Base64
[15] [[IETF]] はその後 [[Base64]] (と [[Base32]] と [[Base16]]) のみを定める
[[RFC]] を発行しました [SRC[>>6, >>24]]。
[30] [[MIME]] 式の [[base64]] と、 [[base64url]] (>>833) との2種類が定義されています。
両者は[[字母]]のみが異なっています。
[164] [[MIME]] 式のものは、 [[MIME]] や [[OpenPGP]] に由来するものですが、
いくつか異なる点もあります。
[165] [[詰め]]は、原則として[MUST[必須]]ですが、[[応用]]は省略可能と定めることができます。
しかし[[詰め]]が省略された場合にどう処理しなければならないかは規定されていません。
[167] [[RFC 3548]] にはありませんでしたが、 [[RFC 4648]] は、
[[詰め]]の前の[[字母]]の選択時に余った[[ビット]]は [N[0]]
としなければ[MUST[ならない]]としています。
そうでない場合、[[復号]]時に拒絶しても構わないとされています。
[168] [[復号]]時に[[字母]]以外が含まれる場合、
原則として拒絶しなければ[MUST[ならず]]、
[[応用]]はそれ以外の処理方法を定めても良い、とされています。
[[電子メール]]のように行長制限が必要な場合には[[改行]]を挿入することを選べますが、
基本的には[[改行]]は含めないことになっているのが [[MIME]] との最大の違いです。
同様に[[復号]]時に不正な[[詰め]]も無視すると定めても良いことになっています。
[169] これらの [[RFC]] でも、完全な[[復号]]の方法は定められていません。
[FIG(list middle)[ [33] [[RFC 3548]] [[MIME]] 式 [[Base64]] の[[応用]]
- [[XMPP]] ([[RFC 3920]])
- [[Atom 1.0]] [CODE[atom:content]] (>>36)
]FIG]
[FIG(list middle)[ [67] [[RFC 4648]] [[MIME]] 式 [[Base64]] の[[応用]]
- [185] [[基本認証]] [[credentials]] [SRC[>>184]]
- [[YANG]] [SRC[>>72]]
- [[RFC 7804]] [SRC[>>61]]
- [[RFC 7730]] ([CODE[CRLF]] / [CODE[CR]] 挿入可) [SRC[>>60]]
- [[RFC 7468]] [CODE[.pem]] (>>197)
- [CODE[x5c]]
[HISTORY[
- [CODE(HTTP)@en[Sec-WebSocket-Key:]] [SRC[旧 RFC、旧 [CITE[Fetch Standard]]]]
]HISTORY]
]FIG]
[36]
[[RFC 4287]] の [[Atom 1.0]] における [CODE[atom:content]] では、
[[RFC 3548]] の [[MIME]] 式 [[Base64]] が使われています [SRC[>>177]]。
ただし、前後に[[空白]]があっても良いこと、
[[改行]]は [CODE[U+000A]] とすることが定められています [SRC[>>177]]。
この[[改行]]の定めが何を意味するかは不明瞭です。
[[RFC 3548]] によれば[[応用]]が明確に認めない限り[[改行]]の挿入は認められませんが、
[[RFC 4287]] が明確に認めているとは言えず、
しかしそうだとすると [[RFC 4287]] の記述は理解不能となります。
[197] [[RFC 7468]] は、 [CODE[.pem]] ファイルの [[Base64]]
を [[RFC 4648]] の [[MIME]] 式 [[Base64]] としています。
ただし、生成時には最終行以外を64文字丁度とすることと定めています
(これは [[PEM]] に由来する制約です)。
解釈時には[[空白]]を含む[[字母]]以外を無視することを認めています。
[[ABNF]] 構文上は[[詰め]]の省略が認められているようですが、
本文には明確な規定がなく、意図は不明です。
([[ABNF]] 構文は通常、緩め、厳密の3種類が用意されています。)
[REFS[
- [6] [CITE@en[RFC 3548 - The Base16, Base32, and Base64 Data Encodings]] ([TIME[2018-01-21 17:19:42 +09:00]]) <https://tools.ietf.org/html/rfc3548>
- [24] [CITE@en[RFC 4648 - The Base16, Base32, and Base64 Data Encodings]] ([TIME[2018-01-28 17:12:45 +09:00]]) <https://tools.ietf.org/html/rfc4648>
- [177] [CITE@en[RFC 4287 - The Atom Syndication Format]] ([TIME[2018-01-28 12:33:10 +09:00]]) <https://tools.ietf.org/html/rfc4287#section-4.1.3.3>
- [184] [CITE@en[RFC 7617 - The 'Basic' HTTP Authentication Scheme]] ([TIME[2018-02-02 23:41:22 +09:00]]) <https://tools.ietf.org/html/rfc7617#section-2>
[FIG(quote)[
[FIGCAPTION[
[60] [CITE@en[RFC 7730 - Resource Public Key Infrastructure (RPKI) Trust Anchor Locator]]
([TIME[2016-03-02 07:04:14 +09:00]] 版)
<https://tools.ietf.org/html/rfc7730>
]FIGCAPTION]
> 3) a subjectPublicKeyInfo '''['''RFC5280''']''' in DER format '''['''X.509''']''',
encoded in Base64 (see Section 4 of '''['''RFC4648''']'''). To avoid long
lines, <CRLF> or <LF> line breaks MAY be inserted into the
Base64-encoded string.
]FIG]
[FIG(quote)[
[FIGCAPTION[
[61] [CITE@en[RFC 7804 - Salted Challenge Response HTTP Authentication Mechanism]]
([TIME[2016-04-01 08:53:49 +09:00]] 版)
<https://tools.ietf.org/html/rfc7804#section-5.1>
]FIGCAPTION]
> Base64: An encoding mechanism defined in Section 4 of '''['''RFC4648''']'''
that converts an octet string input to a textual output string
that can be easily displayed to a human. The use of base64 in
SCRAM is restricted to the canonical form with no whitespace.
]FIG]
- [72] [CITE@en[RFC 7950 - The YANG 1.1 Data Modeling Language]]
([TIME[2016-09-15 03:32:37 +09:00]])
<https://tools.ietf.org/html/rfc7950#section-9.8>
]REFS]
** [CODE[xs:base64Binary]]
[63] [[XML Schemaデータ型]] [DFN[[CODE[xs:base64Binary]]]]
は、 [[MIME]] の [[RFC 2045]] の定義を参照しつつ、
独自の構文を規定しています [SRC[>>172]]。
[173] [[US-ASCII]] ベースの [[RFC 2045]] と違って、 [[XML Schema]]
は [[Unicode]] ベースとなっています。 ([[文字]]レベルで見れば実質的な違いはありません。)
[174] 本来の[[字母]]の他に [[XMLの空白]]が任意の位置に認められることになっています。
ただし [[XML Schema]] の[[正規化]]を経た[[字句形]]の構文上は途中に [CODE[U+0020]]
各1つのみの挿入が認められることになっています。
[[MIME]] とは違って行長制限はありません。
[176] [[正準字句形]]では[[空白]]は認められないことになっています。
[175] [[詰め]]は必須であり、[[詰め]]の前の[[字母]]の選択時に足りない[[ビット]]は [N[0]]
で埋めなければならないことになっています。
[REFS[
- [172] [CITE@EN[XML Schema Part 2: Datatypes Second Edition]] ([TIME[2017-10-02 19:29:02 +09:00]]) <https://www.w3.org/TR/xmlschema-2/#base64Binary>
]REFS]
** Web Base64
[87] [[Web]] では、 [[エラー処理]]を含め正確な[[アルゴリズム]]として[[符号化]]
(>>89) と[[復号]] (>>91) を定義した
[DFN[forgiving base64]] [SRC[>>86]] を用いています。
[88] 正常な入力のみに限ったとき、 [[RFC 4648]] 第4章の [[Base64]] と等価です。
[112] [[詰め]]は、必ず生成されますが、省略されても[[復号]]には成功します。
[[詰め]]の直前の[[字母]]の余分な[[ビット]]は、無視されます。
[113] [[空白][HTMLの空白]]は生成されませんが、無視されます。
[[字母]]と[[空白][HTMLの空白]]以外が含まれる場合や、
不正な[[詰め]]が含まれる場合は、[[復号]]に[[失敗]]します。
[114] [CITE[Infra Standard]] の [[forgiving base64]] が [[Base64]]
の歴史上最も厳密な定義となっており、特に事情がない場合、これを採用するのが望ましいと思われます。
** UTF-7 修正 Base64
[2] [[UTF-7]] は、[DFN[[RUBYB[修正Base64]@en[Modified Base64]]]]と称する[[変種]]を定義していました
[SRC[>>44, >>47]]。
[178] [[MIME]] の [[RFC 1521]] や [[RFC 2045]] を参照しつつ、
[[詰め]]の [CODE[=]] は使わないこととしていました。
[[復号]]時には、16ビット単位の列として解釈した時に余った[[ビット]]は捨てることとされていました。
余った[[ビット]]が [N[0]] でないものは [[ill-formed]] であるとされていましたが、
それをどう処理するべきかは明記されていませんでした。
[179] [[UTF-7]] では[[字母]]でない[[文字]]を[[修正Base64]]部分の終わりとみなすことになっていました。
従って[[改行]]の挿入は認められていませんでしたし、[[字母]]以外の混入時の[[復号]]の処理も明確でした。
ただし[[改行]]を挿入しないため行長制限を超えてしまうデータが認められると明記はしていませんでした。
[REFS[
- [44] [CITE@en[RFC 1642 - UTF-7 - A Mail-Safe Transformation Format of Unicode]] ([TIME[2018-01-21 18:01:49 +09:00]]) <https://tools.ietf.org/html/rfc1642#page-5>
- [47] [CITE@en[RFC 2152 - UTF-7 A Mail-Safe Transformation Format of Unicode]] ([TIME[2018-01-28 16:55:03 +09:00]]) <https://tools.ietf.org/html/rfc2152#page-5>
]REFS]
-*-*-
[7] [[IMAP]] の[[修正UTF-7]] は、 [[UTF-7]] の[[修正Base64]]を更に改変し、
[[字母]] [CODE(char)[/]] の代わりに [CODE(char)[,]] を使うとしています
[SRC[>>182, >>181]]。
[REFS[
- [182] [CITE@en[RFC 2060 - Internet Message Access Protocol - Version 4rev1]] ([TIME[2018-01-28 19:02:32 +09:00]]) <https://tools.ietf.org/html/rfc2060#section-5.1.3>
- [181] [CITE@en[RFC 3501 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1]] ([TIME[2018-02-01 03:51:41 +09:00]]) <https://tools.ietf.org/html/rfc3501#section-5.1.3>
- [180] [CITE[RFC Errata Report » RFC Editor]] ([TIME[2018-02-04 00:33:46 +09:00]]) <https://www.rfc-editor.org/errata_search.php?rfc=3501>
-- 旧 [CITE[RFC ERRATA]]
<http://www.rfc-editor.org/cgi-bin/errata.pl#rfc3501>
]REFS]
** URL 安全 Base64
[833] [DFN[[[modified Base64 for URL]]]] [SRC[>>829]] あるいは [DFN[[[base64url]]]] と呼ばれる変種は、
[[URL]] で利用しやすくした [[Base64]] の一種です。 [[Web]]
関係の分野でよく用いられるようになってきました。
[834] [[MIME]] 式との差異は次の通りです。
- [835] [[字母]]の [CODE(char)[[[+]]]] と [CODE(char)[[[/]]]] のかわりに [CODE(char)[[[-]]]]
と [CODE(char)[[[_]]]] を使う
- [836] [[詰め]]の [CODE(char)[[[=]]]] は省略する
- [837] 行長制限を設けず、[[改行]]を挿入しない
-*-*-
[838] 出典としてはしばしば [[Wikipedia]] [SRC[>>829]] が参照されます。
[839] 公的な文書としては [[RFC]] (>>30) があり、ファイル名や [[URL]]
で安全なものとして紹介されています。ただし [[RFC]] は原則として[[詰め]] [CODE(char)[[[=]]]]
は省略できないとしており、一般的な実装とは異なっています。
;; [17] [CODE[=]] は [[URL]] では [[query][URL query]] などで特別な意味を持つことがあるので、
あまり安全ではありません。 [[RFC]] は原則を貫こうとするあまり、
一般的な実装が意図的に加えた改変を無視しているのです。
;; [22] 実際には [CODE[-]] が[[ファイル名]]の先頭に来るのは必ずしも安全とはいえません。
[[URL]] で安全と言うのに留めておけばいいのに、[[RFC]] は余計な説明を加えています。
[840] [[RFC]] は既存の利用例として[[メーリング・リスト]]の記事を参照していますが、
[[URL]] が変わってしまったのか、関係ない記事になっています。本来指すべきだったと思われる
>>831、>>832 によると、元々は [[Freenet]] で使われていたのを採用したようです。
[229] [[I-JSON]] は、 [[RFC 4648]] [[base64url]] を使う[SHOULD[べき]]としています。
([[JSON]] で通常の [[Base64]] では不都合な理由はなく、敢えて [[base64url]]
を選択した理由は不明です。)
[221]
[[JSON-Base64]] は、 [[RFC 4648]] の [[URL安全Base64]] を参照しつつも、
独自に定義しています。 [[Base64]] の[[字母]]を置き換え、
[CODE[=]] を削除したものとなっています [SRC[>>220]]。
[[RFC]] を参照しているものの、 [[RFC]] が改変する前の本来の
[[URL安全Base64]] ということになります。
[234] [[RFC 7515]], [[RFC 7522]], [[RFC 7636]] [DFN[Base64url Encoding]] [SRC[>>233, >>54, >>56]] は、
[[RFC 4648]] [[base64url]] の[[詰め]]を禁止し、
[[空白]]その他の挿入も明示的に禁止しています。
また [[RFC 7515]] は[[符号化]]と[[復号]]の、
[[RFC 7636]] は[[符号化]]の実装例も掲載しています。
[236]
結局 [[IETF]] の[[プロトコル]]でも[[詰め]]のない [[base64url]] が主流にみえます。
[REFS[
- [831] [CITE[please prefer base 64 over base 32 (was: Re: '''['''p2p-hackers''']''' Bitzi (was Various identifier choices))]] ([TIME[2006-12-10 07:13:19 +09:00]] 版) <http://zgp.org/pipermail/p2p-hackers/2001-September/000317.html>
- [832] [CITE[please prefer base 64 over base 32 (was: Re: '''['''p2p-hackers''']''' Bitzi (was Various identifier choices))]] ([TIME[2006-12-10 07:13:19 +09:00]] 版) <http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html>
- [829] [CITE@en[Base64 - Wikipedia, the free encyclopedia]] ([TIME[2012-05-01 23:31:28 +09:00]] 版) <http://en.wikipedia.org/wiki/Base64#URL_applications>
- [220] [CITE[JSON-Base64 (JB64) File Format Specification]] ([TIME[2017-05-31 14:00:28 +09:00]]) <https://jb64.org/specification/>
]REFS]
-*-*-
[241]
[[復号]]の方法は厳密には規定されていません。
[242] [[RFC 7515]] は
「Base64url-decode the encoded representation of [VAR[(入力データ)]],
following the restriction that no line breaks, whitespace, or
other additional characters have been used.」
という表現を用いており [SRC[>>240]]、
緩い[[復号]]を用いないことを求めているとも読めます。
[243] [[RFC 7515]] の[[復号]]のサンプルコード [SRC[>>233]]
は、次のような挙動を示します。
ただ、あくまで実装例に過ぎず、[[復号]]方法の規定とは到底言えません。
- [244] [CODE[+]] や [CODE[/]] は [CODE[-]] や [CODE[_]] とそれぞれ同義とみなされる
- [245] 末尾の [CODE[=]] はあってもなくても同義とみなされる
- [246] 文字数を [N[4]] で割って [N[1]] となるなら、[[復号]]は失敗とする
- [247] その他は通常の [[Base64]] の方法による
-*-*-
[75] 他の [[Base64]] の変種同様、[[字母]]を置き換えるだけなので簡単に実装できます。
両対応の[[ライブラリー]]も珍しくありません。
[842] [[Perl]] の[[標準モジュール]]である [CODE(perl)@en[[[MIME::Base64]]]] [SRC[>>841]]
に実装されています。 [[Perl]] では今後はこちらが標準的な実装となっていくと思われます。
[[Wikipedia]] [SRC[>>829]] が出典とされています。
[TIME[2012-05-23T10:20:19.800Z]]
[844] >>843 は >>841 が実装される前によく用いられていました。 [[Python]]
の実装に倣った [SRC[>>843, >>845]] としつつ、 [[Wikipedia]] [SRC[>>829]] も引用しています。
[849] [[Python]] の実装というのは >>848 でしょうが、こちらは >>841、>>843
とは違って [CODE(char)[[[=]]]] を省略しません。 >>839 に従っている実装です。
;; [850] 最初からそうだったのか、それとも [[Perl]] の実装が派生した後に動作が変わったのかは不明です。
;; [851] なお、 [[Python]] の実装は >>835 の2文字を任意の文字に変更できるようですw
[REFS[
- [841] [CITE[MIME::Base64 - search.cpan.org]] ([TIME[2012-05-23 19:19:16 +09:00]] 版) <http://search.cpan.org/dist/MIME-Base64/Base64.pm#encode_base64url(_$bytes_)>
- [843] [CITE[MIME::Base64::URLSafe - search.cpan.org]] ([TIME[2012-05-23 19:21:18 +09:00]] 版) <http://search.cpan.org/dist/MIME-Base64-URLSafe/lib/MIME/Base64/URLSafe.pm>
- [845] [CITE[Kazuho@Cybozu Labs: URL と Base64]] ([TIME[2012-05-23 19:26:17 +09:00]] 版) <http://labs.cybozu.co.jp/blog/kazuho/archives/2006/01/url_base64.php>
-[848] [CITE[18.12. base64 — RFC 3548: Base16, Base32, Base64 Data Encodings — Python v2.7.3 documentation]] ([TIME[2012-05-23 16:26:05 +09:00]] 版) <http://docs.python.org/library/base64.html>
]REFS]
-*-*-
[FIG(middle list)[ [66] [[RFC 4648]] [[base64url]] の[[応用]]
- [CODE(HTTP)@en[HTTP2-Settings:]] ([[詰め]]禁止)
- [CODE[keys][PushSubscriptionJSON]] ([[詰め]]なし)
]FIG]
[FIG(middle list)[ [237] [[RFC 7515]], [[RFC 7522]], [[RFC 7636]] [[base64url]] の[[応用]]
- [[RFC 7515]]
-- [[JWS]]
--- [CODE[x5t]]
-- [[VAPID]]
- [[RFC 7522]]
- [[RFC 7636]]
- [CODE[vapid k][vapid]]
- [[[CODE[application/webpush-options+json]] [CODE[vapid]]][application/webpush-options+json]]
- [CODE[applicationServerKey]]
]FIG]
[263] [DFN[[CODE[BASE64URL([VAR[OCTETS]])]]]]
のような[[仕様書]]上の表記法が使われています [SRC[>>262]]。
[235] いくつかの [[RFC]] は、[[バイナリーデータ]]を [[RFC]]
として記述するための便宜上の方法として [[base64url]] を使っています。
[[RFC 4648]] を引用しつつ、 [[RFC]] の制約上空白を挿入することとしています。
明記はされていませんが、[[詰め]]も省略されています。
[FIG(list)[ [238] 表示用の [[base64url]] の事例
- [CITE@en[RFC 8188 - Encrypted Content-Encoding for HTTP]] ([TIME[2018-12-30 20:20:21 +09:00]]) <https://tools.ietf.org/html/rfc8188#section-3>
- [CITE@en[RFC 8291 - Message Encryption for Web Push]] ([TIME[2018-12-30 17:45:08 +09:00]]) <https://tools.ietf.org/html/rfc8291#section-5>
]FIG]
[266]
[DFN[Base64urlUInt]]
は、
[[正整数]]または [N[0]] の値について、
[[符号無し]][[大エンディアン]]表現を[[オクテット列]]としたとき、
これを
[[base64url]]
[[符号化]]したものです。
このとき[[オクテット列]]は、
当該[[整数値]]を表現するために必要な最低数の[[オクテット]]のみ用いなければ[MUST[なりません]]。
[SRC[>>265]]
[EG[
[267]
[N[0]]
は
[CODE[AA]]
となります。
[SRC[>>265]]
]EG]
[REFS[
- [239] [[RFC 7515]]
-- [233] [CITE@en[[[RFC 7515]] - JSON Web Signature ([[JWS]])]] ([TIME[2018-12-30 17:16:56 +09:00]]) <https://tools.ietf.org/html/rfc7515#page-6>
-- [240] [CITE@en[[[RFC 7515]] - JSON Web Signature ([[JWS]])]] ([TIME[2018-12-30 17:16:56 +09:00]]) <https://tools.ietf.org/html/rfc7515#page-17>
- [264] [[RFC 7518]]
-- [262] [CITE@en[[[RFC 7518]] - JSON Web Algorithms ([[JWA]])]], [TIME[2019-11-27 04:11:14 +09:00]] <https://tools.ietf.org/html/rfc7518#section-1.1>
-- [265] [CITE@en[[[RFC 7518]] - JSON Web Algorithms (JWA)]], [TIME[2019-11-27 04:11:14 +09:00]] <https://tools.ietf.org/html/rfc7518#section-2>
[FIG(quote)[
[FIGCAPTION[
[54] [CITE@en[RFC 7522 - Security Assertion Markup Language (SAML) 2.0 Profile for OAuth 2.0 Client Authentication and Authorization Grants]]
([TIME[2015-05-28 13:43:45 +09:00]] 版)
<https://tools.ietf.org/html/rfc7522>
]FIGCAPTION]
> The SAML Assertion XML data MUST be encoded using base64url, where
the encoding adheres to the definition in Section 5 of RFC 4648
'''['''RFC4648''']''' and where the padding bits are set to zero. To avoid the
need for subsequent encoding steps (by "application/x-www-form-
urlencoded" '''['''W3C.REC-html401-19991224''']''', for example), the base64url-
encoded data MUST NOT be line wrapped and pad characters ("=") MUST
NOT be included.
]FIG]
[FIG(quote)[
[FIGCAPTION[
[56] [CITE@en[RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients]]
([TIME[2015-09-17 06:51:32 +09:00]] 版)
<https://tools.ietf.org/html/rfc7636>
]FIGCAPTION]
> Base64 encoding using the URL- and filename-safe character set
defined in Section 5 of '''['''RFC4648''']''', with all trailing '='
characters omitted (as permitted by Section 3.2 of '''['''RFC4648''']''') and
without the inclusion of any line breaks, whitespace, or other
additional characters. (See Appendix A for notes on implementing
base64url encoding without padding.)
]FIG]
]REFS]
-*-*-
[268] [[RFC 8030]] [CODE[Topic:]] [[HTTPヘッダー]]は、
構文の制約を [[RFC 4648]] [[base64url]]
により定めています。[[字母]]の定義として参照しているだけで、
それが実際に [[base64url]] で符号化されたデータであることは要求していません。
;; [269] [[base64url]] 利用者の便宜を図りつつ、
その他の用途も認める趣旨 (あるいは[[復号]]しないので、
[[base64url]] としての正しさの検査までしない故の規定)
とみられます。
*** 処理
[248] [[符号化]]は、[[バイト列]][VAR[入力]]を、次のようにするべきです。
[FIG(steps)[
= [249] [VAR[結果]]を、[VAR[入力]]を [[forgiving-base64 encode]]
した結果に設定します。
= [250] [VAR[結果]]中の [CODE[+]] を、すべて [CODE[-]]
に置き換えます。
= [251] [VAR[結果]]中の [CODE[/]] を、すべて [CODE[_]]
に置き換えます。
= [252] [VAR[結果]]中の [CODE[=]] を、すべて削除します。
= [253] [VAR[結果]]を返します。
]FIG]
[254] [[復号]]は、[[文字列]][VAR[入力]]を、次のようにするべきです。
[FIG(steps)[
= [255] [VAR[入力]]中の [CODE[-]] を、すべて [CODE[+]]
に置き換えます。
= [256] [VAR[入力]]中の [CODE[_]] を、すべて [CODE[/]]
に置き換えます。
= [257] [VAR[入力]]中に
[CODE[+]], [CODE[/]], [CODE[=]],
[[ASCII英数字]]のいずれでも''ない''[[符号位置]]が含まれる場合、
== [258] [[失敗]]を返し、ここで停止します。
= [259] [VAR[入力]]を [[forgiving-base64 decode]] した結果を返します。
]FIG]
** その他のバリエーション
[9] [CODE(URI)[[[urn:urn-5]]]] [[URN]] [[名前空間]]で使っている Base64
変種は、 [CODE(char)[/]] の代わりに [CODE(char)[-]]
を使います。 (URN では [CODE(URI)[/]] が使えないため。)
また、詰め文字は使いません。
(''Namespace ID: urn-5'' <http://www.iana.org/assignments/urn-informal/urn-5>)
[16] [[RFC 3548]] 曰く、 MIME Base64 ではファイル名や [[URI]]
で安全ではないので、 [CODE(char)[/]] の代わりに [CODE(char)[~]]
を使う提案があったそうです。しかし [CODE(char)[~]] もやはりファイル・システムや
URI で安全とは言えません。
[18] [[M$XML]] は [CODE(char)[/]] の代わりに [CODE(char)[*]]
を使っていたそうです。最近の版では両方認識するそうです。
[20] [[OpenToken]] [SRC[>>19]] は[[クッキー]]で使うためとして、 [[RFC 4648]]
の [[Base64]] の[[詰め文字]]を [CODE[[[=]]]] ではなく [CODE[[[*]]]]
に変えたものを採用しています [SRC[>>19]]。
[847] [SRC[>>846]]
>
,*採用アプリ ,*変換方式
,Hibernate ,"+/ → *-"
,IMAP4 ,"+/ → +,"
,IRCu ,"+/ → []"
,Python ,"+/ → -_"
,正規表現フリー注2 ,"+/ → !-"
[REFS[
- [19] [CITE@en[draft-smith-opentoken-02 - OpenToken]] ([TIME[2014-10-16 18:11:31 +09:00]] 版) <https://tools.ietf.org/html/draft-smith-opentoken-02#section-3.1>
- [846] [CITE[Kazuho@Cybozu Labs: URL と Base64]] ([TIME[2012-05-23 19:26:17 +09:00]] 版) <http://labs.cybozu.co.jp/blog/kazuho/archives/2006/01/url_base64.php>
]REFS]
-*-*-
[29]
[[Norton AntiSpam]] は [CODE(ABNF)[[[encoded-word]]]] の最後の
[CODE(MIME)[=]] を省くそうです。 [SRC[mew-dist 25264]]
もちろんこの実装は MIME 違反です。
[39]
機械的に電子メイルを生成する類のプログラムで、
末尾に4つも [CODE(MIME)@en[=]] を付けるとんでもない符号化するものがあるそうです。
[WEAK[(しかも改善するように要求したら使っている [[MUA]] が悪いのだろうと言われたとか。。。)]]
([[名無しさん]] [sage] [WEAK[2005-12-10 07:32:30 +00:00]])
[45]
[[RFC 4387]] では固定長の[[オクテット列]]を符号化するため、常に最後が [CODE[=]] になってしまうので、
[CODE[=]] は省略することになっています [SRC[>>884]]。
[55]
[[Perl]] の [CODE(perl)@en[[[Digest::MD5]]]] や
[CODE(perl)@en[[[Digest::SHA1]]]] が出力する [[Base64]]
化[[文字列]]は、[[詰め]]が省略されています [SRC[>>853]] 。
[REFS[
- [884] [CITE@en[RFC 4387 - Internet X.509 Public Key Infrastructure Operational Protocols: Certificate Store Access via HTTP]] ([TIME[2014-06-08 08:24:17 +09:00]] 版) <http://tools.ietf.org/html/rfc4387#section-2.1>
- [853] [CITE[Digest::SHA - search.cpan.org]] ([TIME[2013-09-21 12:18:41 +09:00]] 版) <http://search.cpan.org/dist/Digest-SHA/lib/Digest/SHA.pm#PADDING_OF_BASE64_DIGESTS>
]REFS]
-*-*-
[189] [[IMAP4]] の [CODE[AUTHENTICATE]] [[命令]]は、 [[base64]]
で[[符号化]]するとされていますが、その定義は示されていません
[SRC[>>186, >>187, >>188]]。
[190] [[インターネットメール]]の[[プロトコル]]であるから [[MIME]]
の [[Base64]] ではないかと推測したいところですが、
[[ABNF]] 構文が示されており、そこでは[[改行]]が認められていません。
本文中も単数の a line となっており、複数行は認められないようです。
しかし符号化されるデータが [[MIME]] 式 [[Base64]] で1行に収まる保証はありません。
[191] 構文は、 [[MIME]] 式の[[字母]]と[[詰め]]を認めており、
それ以外の[[文字]]は一切認めていません。[[詰め]]が含まれる数は、正しくなければなりません。
[[詰め]]の前の[[字母]]の制約は構文上は現れていません。
[REFS[
- [186] [CITE@en[RFC 1730 - Internet Message Access Protocol - Version 4]] ([TIME[2018-01-21 18:00:58 +09:00]]) <https://tools.ietf.org/html/rfc1730#section-6.2.1>
- [187] [CITE@en[RFC 2060 - Internet Message Access Protocol - Version 4rev1]] ([TIME[2018-01-28 19:02:32 +09:00]]) <https://tools.ietf.org/html/rfc2060#section-6.2.1>
- [188] [CITE@en[RFC 3501 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1]] ([TIME[2018-02-01 03:51:41 +09:00]]) <https://tools.ietf.org/html/rfc3501#section-6.2.2>
]REFS]
* uuencode 風表現
[3] [[MIME]] 以外の場面でファイルを貼り付けるのに、 [[uuencode]]
みたいな書き方をすることがあるみたい。
例1:
[PRE(example)[
begin-base64 644 base64ed.data
[INS[... base64 stream ...]]
====
]PRE]
[26] 例2:
[PRE(example)[
begin-base64 644 code.tgz
[INS[... base64 stream ...]]
=
]PRE]
* 実装
[193] [[Base64]] の実装の選択時には、利用したいのがどのバリエーションで、
実装が対応しているのがどのバリエーションであるのかを慎重に検討する必要があります。
[8] [[uuencode]] も[[64進数]]であることを利用して、 uuencode
で符号化した後に [CODE[[[tr]]]] を使うという方法が使われることもあります。
** Perl
[4] [[Perl]] なら、 [CODE(perl)[[[MIME::Base64]]]] を使うのが気楽かと。
Perl 5.7.3 以降では標準で入っています。
[192] 但し、 >>2, >>7 のような変種には対応していません。
** [CODE[base64]] コマンド
[68] 一般的な [[Linux]] 環境では、 [CODE[base64]] コマンドが用意されています。
[69] [[オプション]]なしで実行すると、[[標準入力]]を[[符号化]]し、
結果を[[標準出力]]に書き込みます。
;; [71] [CODE[echo]] [[コマンド]]は [CODE[-n]] オプションなしで実行すると最後に自動的に[[改行]]を付加するので、組み合わせて使う時は注意しないといけません。
[70] [CODE[-d]] [[オプション]]つきで実行すると、[[標準入力]]を[[復号]]し、
結果を[[標準出力]]に書き込みます。
** BASE64.ASM
[FIG[
[PRE(code)[
ASSUME CS:CODE,DS:CODE
CODE SEGMENT
ORG 100H
START: MOV BX,0
START1: MOV DI,0
LOOP1: PUSH BX
PUSH DI
MOV AH,06H
MOV DL,0FFH
INT 21H
POP DI
POP BX
JNZ JUMP1
CMP DI,0
JZ END1
CMP DI,1
JZ END2
CMP DI,2
JZ END3
JUMP1: MOV BUFFER[DI],AL
INC DI
CMP DI,3
JNZ LOOP1
SHORI2: MOV CH,4
LOOP3: MOV CL,6
MOV SI,0
LOOP2: SAL BUFFER+2,1
RCL BUFFER+1,1
RCL BUFFER+0,1
RCL SI,1
DEC CL
JNZ LOOP2
PUSH BX
PUSH DI
PUSH SI
PUSH CX
MOV DL,BASE64[SI]
MOV AH,06H
INT 21H
POP CX
POP SI
POP DI
POP BX
DEC CH
JNZ LOOP3
ADD BX,DI
CMP BX,57
JNZ START1
PUSH BX
PUSH CX
PUSH DI
PUSH SI
MOV DL,0AH
MOV AH,06H
INT 21H
MOV DL,0DH
MOV AH,06H
INT 21H
POP SI
POP DI
POP CX
POP BX
JMP START
END2: MOV CH,2
JMP LOOP5
END3: MOV CH,3
LOOP5: MOV CL,6
MOV SI,0
LOOP4: SAL BUFFER+2,1
RCL BUFFER+1,1
RCL BUFFER+0,1
RCL SI,1
DEC CL
JNZ LOOP4
PUSH CX
PUSH DI
PUSH SI
MOV DL,BASE64[SI]
MOV AH,06H
INT 21H
POP SI
POP DI
POP CX
DEC CH
JNZ LOOP5
CMP DI,2
JZ JUMP2
MOV DL,'='
MOV AH,06H
INT 21H
JUMP2: MOV DL,'='
MOV AH,06H
INT 21H
;処理終了
END1: MOV AH,4CH
MOV AL,00H
INT 21H