论权利与义务

2018年1月1日,我重回澳大利亚继续我的语言课程,并搬进了我在2017年7月预定的、位于校园内的宿舍。其基础设施相比我所在的寄宿家庭好很多,但仍有一些令我不太满意之处——由于这不是这篇文章的主题,故不再赘述。

2018年2月,语言课结束,我也顺利地通过期末考核并取得达到大学要求的成绩。在准备回国过年之际,我准备打扫房间,包括用吸尘器清洁地毯。可不知为何吸尘器几乎没有作用,完全无法除去地毯上明显的污物。我只得用粘毛滚,花近2小时将不足10m2的房间清理干净。


今天晚,又是一个偶数周末,我是要例行全面打扫卫生的。这回我再次尝试使用吸尘器,仍有相同问题。观察吸尘器储藏灰尘的透明箱,我发现了原因。

这个箱子几乎满了,连人手伸进去都很难触及的风路内圈都被污物填满。密度高到无法将其倒出,令我只得用手将其掏出。这些污物装满了两个大塑料袋,重量约1.5kg。灰尘则多到打开盖子后轻轻一碰,周遭便暴土扬烟。

而另一台吸尘器情况更为严重,出于个人健康考虑,我并未清洁它——其只要运行起来,便散发出令人作呕的、微生物降解有机物的气味;观察其储藏箱,可见其内壁附着许多霉点。

我之所以查看另一台吸尘器,是因为第一台吸尘器或因电机过热而在短时间内无法运转。由于其两侧的过滤网也布满灰尘,使得气流难以通过,这或是电机过热的原因(交流电机的外壳一般不封闭,转子上带有扇叶,通过自身旋转来散热)。

很难想象,某些人在享受权利的同时,是否有想过尽所对应的义务?

这两台吸尘器,我甚至有理由相信它们从被配发至这个宿舍,就从未清理过。在这个宿舍住过的若干人,享受了使用它的权利,难道就不尽一点义务,在使用后将它清理干净吗?

倘若每个人在享受权利的同时,都履行了与之关联的义务,这种情况还会出现吗?

如此的社会责任感都没有,很难想象某些人是接受过高等教育的!

2018年5月4日22时30分|作于(再次)用粘毛滚清洁地毯后

网贷公司的不为人知之处

以下事情发生于2017年下半年,我兼职于国内某网贷公司时。一些更详细的信息在17年11月发表的、一篇烂尾的关于"接私活"的文章中有所提及。

这家公司管理极其混乱——我作为兼职的运维人员,能透过root登录他们的服务器这都不算什么。更荒唐的是我对他们的数据库具有完全的访问权限——任何一个数据库的任何一张表都可以。

这或许是因为他们把我当devops了——他们的程序员水平实在太差,而且还不设调试环境,竟把生产环境同时用作调试。他们又以"无权限访问(生产环境的)服务器(的日志)"为理(jie)由(kou),让我协助调试。

他们的错误也十分低级——大多是少了(方|花|圆)括号、(单|双)引号的右半部分或是结尾的分号。

我甚至怀疑他们用垃圾微软的垃圾Windows的垃圾"记事本"来写程序,而不是专业的IDE。

 


一、不该出现在数据库中的东西

偶然发现他们的数据库中,用户的表中有一列皆是json编码的信息,其内容看起来像是用户的通讯录。大致如此:

其中有不少"姓名"一处是类似"爸"、"妈"的,我更加相信他们的App上传了用户的通讯录,且很有可能是在用户不知情之情况下。

我很清楚这是为什么——一旦债务人(用户)无法偿还贷款,这些信息很可能被转发至债务人(网贷公司和/或为其提供资金的金主)所雇佣的"讨债公司",后者很清楚无法从债务人本人处要回贷款,便会无休止地骚扰债务人的亲友——而亲友的信息是由这通讯录提供的。

我也曾是这种恶劣行为的受害者——2016年,我因某些客观原因及交友不慎,使我的联系方式出现在某"老赖"大学生的通讯簿中。

2017年12月,这令我在国内使用的手机号受到影响。留学期间为规避高昂漫游费用,我将国内号码的SIM卡取出。这令"讨债公司"电话骚扰不成,转而"短信轰炸",令我的手机号收到大量的网站注册验证码。

有人或有疑问,这些债务人为何不起诉拖欠还款的债务人?或因他们提供的民间借贷利率过高(远高于银行贷款),而最高法于2015年8月6日发布的司法解释指出:

第二十六条 借贷双方约定的利率未超过年利率24%,出借人请求借款人按照约定的利率支付利息的,人民法院应予支持。

借贷双方约定的利率超过年利率36%,超过部分的利息约定无效。借款人请求出借人返还已支付的超过年利率36%部分的利息的,人民法院应予支持。

——最高人民法院关于审理民间借贷案件适用法律若干问题的规定


二、保存密码,用MD5"加密"

(还是,因为其管理混乱我拥有访问其数据库的权限)偶然发现其数据库中用户的密码被保存为32位16进制字符。

这意味着该字符串可能是透过某种摘要算法生成,而其长度正好等于128bit,也就是MD5输出的散列长度。我去问他们的开发人员,用户的密码系如何保存。答曰,用MD5加密

MD5是摘要算法,而不是一种加密算法。其开发人员对密码学知识的了解可见一斑!我又问其是否对明文加盐后再Hash,对方完全不知加盐是何物,甚至还"看热闹不嫌事大"般地调侃道:又不是炒菜做饭。

业内所认可的保存密码方式一般是使用慢哈希(Slow hash),如BCrypt,其可自定义复杂度。一般的摘要算法,在现代的计算机上可以迅速输出散列,尤其是在GPU通用计算的帮助下。这样一来,使用SHA-2家族中散列最长的SHA512并加盐也无法应对GPU通计"加持"的蛮力攻击,更不必说散列短的MD5。这也是Slow Hash存在的意义。

我将此事上报,计划用BCrypt保存密码,却得如下回应。这着实令我感到震惊

修得了就修,修不了就不修。

即便有一两个出问题的,公关部会搞定,不用你操心。

总之,引起了用户恐慌就不行。你要明白,这是不能碰的红线。

由于我们不知道用户所用密码的明文,因此我设计如下解决方案:

  • 在应用内提示用户,出于安全起见请定期更改密码。
  • 老用户新设置的密码和新用户的密码使用BCrypt
  • 未更改的密码,仍使用原先方式保存
  • 需要透过密码鉴权时,判断字符串开头是否有$b$,如有则用BCrypt;如无则用MD5。

至我离开这家公司,shift到BCrypt的工作仍未完全完成,不是所有用户的密码都被安全地存储——显然有用户忽略了修改密码的提示。

但是,迫于无耻领导出于公司盈利所给予的压力,我想不出一个比我所采用的更好的解决方案。

一道Python题

UNSW的ENGG1811课程有一道期中考试例题,要求用Python实现如下功能:

给定一列表,内含变量皆为浮点数。

无论其具有奇数项或偶数项,返回奇数项之和与偶数项之和的差。

起初思路如下:

  1. 使用n = len(x)判断列表的项数
  2. pair = n // 2判断奇偶对的数量
  3. ……
  4. 然而,出问题了——如果列表包含奇数项,则奇数项的个数和偶数项不等。

于是,不得不改变了思路——先(通过求模)判断列表项数,若是奇数项,在末尾补一个0将其变为偶数项,且不影响计算结果。

由此可得如下代码:


后记:

其实在考试的45分钟里,我用了近30分钟来应付这道题(前三题没有太高难度)。如果没有一个更简便的思路来解决这个问题,恐怕再有30分钟也不够……