From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: poffice@blade.nagaokaut.ac.jp Delivered-To: poffice@blade.nagaokaut.ac.jp Received: from kankan.nagaokaut.ac.jp (kankan.nagaokaut.ac.jp [133.44.2.24]) by blade.nagaokaut.ac.jp (Postfix) with ESMTP id 70A0B17D06B7 for ; Tue, 29 Jul 2014 14:49:48 +0900 (JST) Received: from funfun.nagaokaut.ac.jp (funfun.nagaokaut.ac.jp [133.44.2.201]) by kankan.nagaokaut.ac.jp (Postfix) with ESMTP id 54D40B5D8BE for ; Tue, 29 Jul 2014 14:27:35 +0900 (JST) Received: from funfun.nagaokaut.ac.jp (localhost.nagaokaut.ac.jp [127.0.0.1]) by funfun.nagaokaut.ac.jp (Postfix) with ESMTP id 1045C97A834 for ; Tue, 29 Jul 2014 14:27:37 +0900 (JST) X-Virus-Scanned: amavisd-new at nagaokaut.ac.jp Authentication-Results: funfun.nagaokaut.ac.jp (amavisd-new); dkim=fail (1024-bit key) reason="fail (message has been altered)" header.d=sendgrid.me Received: from funfun.nagaokaut.ac.jp ([127.0.0.1]) by funfun.nagaokaut.ac.jp (funfun.nagaokaut.ac.jp [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ebit6qBSnRTP for ; Tue, 29 Jul 2014 14:27:36 +0900 (JST) Received: from voscc.nagaokaut.ac.jp (voscc.nagaokaut.ac.jp [133.44.1.100]) by funfun.nagaokaut.ac.jp (Postfix) with ESMTP id 7478D97A82B for ; Tue, 29 Jul 2014 14:27:36 +0900 (JST) Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by voscc.nagaokaut.ac.jp (Postfix) with ESMTP id E4408952446 for ; Tue, 29 Jul 2014 14:27:24 +0900 (JST) Received: from [221.186.184.76] (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 3742A120433; Tue, 29 Jul 2014 14:27:10 +0900 (JST) X-Original-To: ruby-core@ruby-lang.org Delivered-To: ruby-core@ruby-lang.org Received: from o10.shared.sendgrid.net (o10.shared.sendgrid.net [173.193.132.135]) by neon.ruby-lang.org (Postfix) with ESMTPS id 1DBC212041F for ; Tue, 29 Jul 2014 14:27:07 +0900 (JST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sendgrid.me; h=from:to:references:subject:mime-version:content-type:content-transfer-encoding:list-id; s=smtpapi; bh=KN+y4Wvc08rQ8oMrEw++b7np+bM=; b=fUnPrD4cVkuj1xCgvy TBaTBuVQl0jP/K/A7L9WKq5GkinCGBTlOFV+VAAQXahn0qx7QAEcKUGQD0OS7utq k/OTFKmdQeiwV7CRE/enkc9Mwfo1Bvsp0vAfQFxANMI6pWv9n9o0sJ6SI2kJ5p64 OD1ICwHR56ajxNCkKfGnkp3GI= Received: by mf141.sendgrid.net with SMTP id mf141.34196.53D730A842 2014-07-29 05:27:04.668820475 +0000 UTC Received: from herokuapp.com (ec2-54-90-18-226.compute-1.amazonaws.com [54.90.18.226]) by ismtpd-001.iad1.sendgrid.net (SG) with ESMTP id 1478095e7d8.2ab1.6e8674 Tue, 29 Jul 2014 05:26:53 +0000 (GMT) Date: Tue, 29 Jul 2014 05:26:53 +0000 From: nobu@ruby-lang.org To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Redmine-MailingListIntegration-Message-Ids: 38270 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 10098 X-Redmine-Issue-Author: arrtchiu X-Redmine-Sender: nobu X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: OOF Auto-Submitted: auto-generated X-SG-EID: ync6xU2WACa70kv/Ymy4QrNMhiuLXJG8OTL2vJD1yS4EPd96VzJRMZV1VSXZYmze7DvFD9SPFXeHRcs8OYme7ZjaxnjErtKOPH++vrWy+ZcNCRyOvHfg8WeRTDfWHgD5CrNQXKxMES+a4BpVA2kKzhm9Q4ywGsV1ggoO1AFqBBU= X-ML-Name: ruby-core X-Mail-Count: 64112 Subject: [ruby-core:64112] [ruby-trunk - Feature #10098] [PATCH] Timing-safe string comparison for OpenSSL::HMAC X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #10098 has been updated by Nobuyoshi Nakada. Seems correct. I made a benchmark for it: ~~~ruby # bm-tsafe_eql.rb: [Feature #10098] require 'benchmark' a = "x"*1024_000 b = a+"y" c = "y"+a a << "x" n = (ARGV.shift || 100000).to_i Benchmark.bm(15) {|bm| bm.report("a==b") {n.times{a==b}} bm.report("a==c") {n.times{a==c}} bm.report("a.tsafe_eql?(b)") {n.times{a.tsafe_eql?(b)}} bm.report("a.tsafe_eql?(c)") {n.times{a.tsafe_eql?(c)}} } ~~~ It seems quite slow. | user| system| total| real ---------------|----------|----------|----------|----------- a==b | 4.660000| 0.000000| 4.660000|( 4.672629) a==c | 0.010000| 0.000000| 0.010000|( 0.007154) a.tsafe_eql?(b)| 34.330000| 0.020000| 34.350000|( 34.366759) a.tsafe_eql?(c)| 34.450000| 0.020000| 34.470000|( 34.480267) With the following patch, | user| system| total| real ---------------|----------|----------|----------|----------- a==b | 4.660000| 0.000000| 4.660000|( 4.666683) a==c | 0.000000| 0.000000| 0.000000|( 0.006657) a.tsafe_eql?(b)| 7.660000| 0.010000| 7.670000|( 7.662584) a.tsafe_eql?(c)| 7.660000| 0.000000| 7.660000|( 7.671189) ~~~ruby diff --git a/string.c b/string.c index 5c2852f..90865c0 100644 --- a/string.c +++ b/string.c @@ -2504,7 +2504,7 @@ static VALUE rb_str_tsafe_eql(VALUE str1, VALUE str2) { long len, idx; - char result; + VALUE result; const char *buf1, *buf2; str2 = StringValue(str2); @@ -2516,7 +2516,13 @@ rb_str_tsafe_eql(VALUE str1, VALUE str2) buf2 = RSTRING_PTR(str2); result = 0; - for (idx = 0; idx < len; idx++) { + idx = 0; + if (UNALIGNED_WORD_ACCESS || !((VALUE)buf1 % sizeof(VALUE)) && !((VALUE)buf2 % sizeof(VALUE))) { + for (; idx < len; idx += sizeof(VALUE)) { + result |= *(const VALUE *)(buf1+idx) ^ *(const VALUE *)(buf2+idx); + } + } + for (; idx < len; idx++) { result |= buf1[idx] ^ buf2[idx]; } ~~~ ---------------------------------------- Feature #10098: [PATCH] Timing-safe string comparison for OpenSSL::HMAC https://bugs.ruby-lang.org/issues/10098#change-48123 * Author: Matt U * Status: Open * Priority: Normal * Assignee: * Category: ext/openssl * Target version: next minor ---------------------------------------- I could be totally wrong, but it seems the standard library doesn't provide a reliable way of comparing hashes in constant-time. * The docs for `OpenSSL::HMAC` encourage the use of `Digest#to_s` (see: http://ruby-doc.org/stdlib-2.1.0/libdoc/openssl/rdoc/OpenSSL/HMAC.html#method-c-new ) * Ruby's string comparison uses memcmp, which isn't timing safe (see: http://rxr.whitequark.org/mri/source/string.c#2382 ) With this patch I propose to add an additional method, `OpenSSL::HMAC#verify`, which takes a binary string with a digest and compares it against the computed hash. ---Files-------------------------------- hmac-timing.patch (2.5 KB) hmac-timing.patch (2.48 KB) tsafe_eql.patch (2.48 KB) -- https://bugs.ruby-lang.org/