Re: [netconf] base64encodedvalue== is an invalid base64 value

Carsten Bormann <cabo@tzi.org> Sat, 30 January 2021 01:48 UTC

Return-Path: <cabo@tzi.org>
X-Original-To: netconf@ietfa.amsl.com
Delivered-To: netconf@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 3FE193A1485 for <netconf@ietfa.amsl.com>; Fri, 29 Jan 2021 17:48:07 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.898
X-Spam-Level:
X-Spam-Status: No, score=-1.898 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MB6fmEKHy2ah for <netconf@ietfa.amsl.com>; Fri, 29 Jan 2021 17:48:03 -0800 (PST)
Received: from gabriel-vm-2.zfn.uni-bremen.de (gabriel-vm-2.zfn.uni-bremen.de [134.102.50.17]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 301983A1484 for <netconf@ietf.org>; Fri, 29 Jan 2021 17:48:02 -0800 (PST)
Received: from [192.168.217.152] (p5089a828.dip0.t-ipconnect.de [80.137.168.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by gabriel-vm-2.zfn.uni-bremen.de (Postfix) with ESMTPSA id 4DSHCh36z2zyfX; Sat, 30 Jan 2021 02:48:00 +0100 (CET)
Content-Type: multipart/alternative; boundary="Apple-Mail=_359AE3E3-93E5-4869-B1F5-DB95972534BF"
Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.40.0.2.32\))
From: Carsten Bormann <cabo@tzi.org>
In-Reply-To: <0100017750786b5f-6f9004c8-d56f-4f67-802b-09154dce9f3c-000000@email.amazonses.com>
Date: Sat, 30 Jan 2021 02:47:59 +0100
Cc: "netconf@ietf.org" <netconf@ietf.org>
Message-Id: <A4D41C16-5737-4A59-8FF3-C324FC36567E@tzi.org>
References: <010001774f5f7df0-89830501-6d1a-465b-a172-dd95e98e8a3e-000000@email.amazonses.com> <20210129191142.lxhtegbkgan37oyj@anna.jacobs.jacobs-university.de> <6A06C21C-70F1-40D7-A690-B2AC94BC9CB3@tzi.org> <0100017750786b5f-6f9004c8-d56f-4f67-802b-09154dce9f3c-000000@email.amazonses.com>
To: Kent Watsen <kent+ietf@watsen.net>
X-Mailer: Apple Mail (2.3654.40.0.2.32)
Archived-At: <https://mailarchive.ietf.org/arch/msg/netconf/AH49Z24FVzbvoMaJAPEwpI54Fss>
Subject: Re: [netconf] base64encodedvalue== is an invalid base64 value
X-BeenThere: netconf@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: NETCONF WG list <netconf.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/netconf>, <mailto:netconf-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/netconf/>
List-Post: <mailto:netconf@ietf.org>
List-Help: <mailto:netconf-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/netconf>, <mailto:netconf-request@ietf.org?subject=subscribe>
X-List-Received-Date: Sat, 30 Jan 2021 01:48:07 -0000

On 30. Jan 2021, at 00:26, Kent Watsen <kent+ietf@watsen.net> wrote:
> 
> 
>>> Who cares whether this value roundtrips in an examples??
>> 
>> I’d expect at least some decent implementations will check for RFC 4648’s mandate "These pad bits MUST be set to
>>  zero by conforming encoders”, just like some check for the right number of equals signs.
>> Examples that fail in decent implementations are suboptimal.
>> (They might even be used in arguments to claim that this decency needs to be removed.)
> 
> 
> 
> `base64` doesn’t produce a warning:
> 
>    $ echo "base64encodedvalue==" | base64 -d | base64
>    base64encodedvaluQ==
> 
> 
> 
> `openssl` doesn’t produce a warning:
> 
>    $ echo "base64encodedvalue==" | openssl enc -d -base64 -A | openssl enc -base64 -A
>    base64encodedvaluQ==
> 
> 
> 
> Python doesn’t produce a warning:
> 
>    $ printf "import binascii\nprint(binascii.b2a_base64(binascii.a2b_base64('base64encodedvalue=='), newline=False).decode('ascii'))" |  python -
>    base64encodedvaluQ==


Thanks for the data points; adding 1½ more:

$ ruby -rbase64 -e 'puts Base64.encode64(Base64.decode64("base64encodedvalue=="))' 
base64encodedvaluQ==
$ ruby -rbase64 -e 'puts Base64.strict_encode64(Base64.strict_decode64("base64encodedvalue=="))'
<internal:pack>:281:in `unpack1': invalid base64 (ArgumentError)
	from /opt/homebrew/Cellar/ruby/3.0.0_1/lib/ruby/3.0.0/base64.rb:74:in `strict_decode64'
	from -e:1:in `<main>'

Checking conformance is a MAY(*) for a decoder, so I’m not surprised that many don’t do that.
(Or check only on specific request, as in Ruby.)

I would strongly expect any decoder that is used in a security context to actually check, so I *am* surprised by the openssl example above.
(Well, not that much surprised; it is, well, openssl.)

I wouldn’t have reacted to this thread if I hadn’t years ago, when writing a random test case generator, been surprised by a base64 implementation that did check.
I don’t recollect the details of that, though…

Grüße, Carsten

(*) https://tools.ietf.org/html/rfc4648#section-3.5 <https://tools.ietf.org/html/rfc4648#section-3.5>
For those not familiar with RFC 2119 interoperability keywords:
MAY means that an implementation is free to do so.
Which raises the interoperability requirement that any peer implementation MUST be able to interoperate with an implementation that does.
This would be unnecessary to state in this case because that MUST is in the paragraph before.
So the intent here apparently was stressing the optionality of checking in a decoder.