Shell's Home

May 21, 2019 - 1 minute read

外设接口和供电的演化史

这篇文章基本就是我根据自己的记忆翻旧帐讲古,大家随便看好了。 外设接口的上古时代 说是上古时代,我也不会从8259A级联这种地方开始讲起的。我们首先回顾的是上世纪末,我们还在用各种不同接口连接不同设备的时代。当时主流有这么几种设备和接口: 显示器:当年没有LED显示器,主流都是大屁股的CRT显示器。主流接口是VGA。大家要是用过投影仪对这个接口可能有印象,这个接口又被称为D型口,目前仍广泛存在于投影仪类设备。 音箱:音箱接口到今天都没怎么变化,主要接口是3.5mm接口,专业术语叫做TRS端子。 网卡:当年网卡还很稀罕,记忆中流行过一阵的同轴缆线。不过双绞线的标准一直没变过,使用RJ45。 鼠标键盘:最早年是AT接口,后来主流使用PS/2。 并口:主要是接打印机扫描仪什么的,扫描仪也是很后来才有。LPT。 串口:COM,和各种设备通讯。甚至可以接一根特殊的console线,对端变成RJ45去控制网络设备。这种线今天仍在使用(我手里还有一根),不过串口在电脑上已经找不到了,所以要多一根USB2COM线。 最早声音,网络,视频都需要独立的卡来支持,甚至有出现过汉卡。每个独立的卡上附带一个或多个接口,用来和特定设备连接。但后来CPU越来越快,除了显卡外大多数卡大家就都没见过了。现在的音箱接口鼠标键盘都是集成在主板上的。 LPT接口和COM接口的一大问题是,没有内在支持热插拔。当然,热接线并不一定导致问题,或者无法使用。然而各种静电击穿,驱动不良引起的问题层出不穷。所以标准过程都是关机连线,先开外设后开机,先关机后关外设。其实当年最初也没有很多人有异议,DOS时代的开机很快的。直到后来大家渐渐用上了Win95,发现没有热插拔真难过。 以上大部分的接口,都是不供电的。PS/2和TRS带有一定供电能力。PS/2提供5V/275mA的电流。TRS直接连通的耳机,其中的电信号直接推动耳机单元发音。 USB时代的开端 微软很早就开始了对USB的推动,按照wiki所述,最早的1.0协议是96年发布,2.0则要到2000年。但是96年的时候,我们对USB还并没有什么太大听闻。直到2000年后,各种USB设备层出不穷,直接带领了一个时代。 USB研发的初衷是为了解决接口统一性问题和热插拔问题。接口大致分为两类情况。一类是直观接口,里面各引脚基本就是各种直观定义。例如TRS的几个引脚,基本就是耳机单元引出线。另一类则是通讯接口,主要功能是通讯,其逻辑含义需要根据信号定义解析。通讯接口实现复杂成本很高。然而既然模拟接口的引脚和直观定义绑定,那么驱动耳机的接口就和驱动键盘的接口永远统一不起来。如此一来,每一种外设计算机就要做一个接口,没有对应接口就用不了外设。这对计算机硬件的生产和维护非常不利。而且Windows开机那么慢,每次连接断开硬件都要重启,每天别干别的就重启了。所以一个接口,统一各种插头类型,支持热插拔,就成了个强需求。而为了达到这个目标,接口自身必然是个通讯接口,内在逻辑通过软件定义解决。而通讯接口中,LPT面临复杂的同步问题。因此点对点串行通讯的USB接口兴起就是一个必然。 USB是串行通讯模式,菊花链拓扑。所以HUB的大小永远是3n+1,例如4个,7个,etc。如果个数不对,可能就是hub自身用掉了几个接口。例如我手里一个HUB网卡二合一dock,就是三个3.0接口一个千兆网口。最初速率定义为1.5Mbps,2.0提高到了480Mbps。但是实际上只有大约30MB/s。最早的电流定义我记得是100mA/500mA两种,足够驱动大多数的小电流设备。 几乎从2000往后,键盘和鼠标的主流就全是USB的了。PS/2的键盘/鼠标偶尔还用于特殊场合,例如老设备支持,或是某些情况下诊断内核死机(因为PS/2的状态灯由内核直接控制,内核不死,按键开关状态灯基本都是可行的。而USB的状态灯需要更多业务逻辑,所以更说不准)。再往后,所有相机,打印机,扫描仪,游戏手柄,统统换去了USB。更出现了U盘和mp3这种妖怪玩意,几乎人手一个。在那个上网还要拨号的年代,mp3就是个人的便携文件袋+多媒体娱乐中心。 如果我没记错的话,USB的第一次电流提升起源于移动硬盘的兴起。mp3固然方便,但是容量往往太小。我的第一个mp3只有128M(是的,你没看错,单位是兆),大概只能放20首歌。而移动硬盘一般可以做到200G以上的大小。所以大家纷纷开始区分使用,mp3就放歌,移动硬盘存数据,包括歌曲库。然后借助电脑来把移动硬盘上的歌拷去mp3里。然而,USB最初供电功率只有2.5W,很多移动硬盘功率不足,需要外接电源,用着很不习惯。所以后来逐渐兴起了1A供电的USB接口,免去了外接电源。我现在手里还有一块老式移动硬盘,320G大小,双USB供电或外接电源供电。对应的就是这个特殊的时代。 在这个时代,USB逐渐统一了各种外设,主流接口里面只剩下了显示接口,TRS端子,RJ45三种还没有被统一。显示接口是因为传输速率太高,USB支持不起来。TRS和RJ45其实也有USB版本,叫做外接声卡和外接网卡。然而由于这两个端口太过常用,往往主板上也会搭载,免得用户自己每次都要配套买两个外接件。直到今天,MBP上type-c一统天下,唯一不同的接口就是TRS。RJ45由于wifi的普及而早早下课了。至于并口串口,一般主板上也会有。但是很多主板,从买回来到报废那天,这两个接口都没用过。 手机充电的发展 和电脑独立发展的是手机的充电接口。最初手机的充电接口是专用口,用过Nokia早期手机的人应该都见过这类口。这类接口几乎无法相互借用,因此以前出门商旅人士,往往包里都背着自己专用的充电器。幸好这个时代的手机还很耐用,一周一充是正常现象,最过分也就是三天一充。至于今天,三天一充几乎就是个神话。 手机接口向着USB统一起源于Android。最早的几台Android机就是使用USB充电的。后来大家发现,USB充电可以用电脑直接给电,只用带线不需要充电器。而且这根线还能传输数据,把手机当作U盘用。这个更进一步影响了Android的流行,也让各种其他接口快速的消亡。时至今日,比较流行的自有接口定义貌似只有苹果一家了。 然而,大家也都是用手机的,应该知道,手机的电是个无底洞。一天一充,一充一天都是正常操作。这种情况下,USB电流发展也是越来越高。从一开始的5V/1A,到后来的5V/2A乃至各种奇葩协议。这是今天这篇主要说的另一个方向。 USB的各种接口和功率规范 USB接口大家应该都很熟悉。最常见的是A型,就是一般电脑上配的。手机常用的是Micro-B和更新的USB-C。其中type-c标准更新更紧凑而且双面可插拔。 至于功率规范,可能就不是每个人都熟悉了。上古时代的100mA我们就不说了,常见的经典功率规范有三种,5V/500mA=2.5W,5V/1A=5W,5V/2A=10W。今天大部分手机的充电功率,往往都在10W这个级别。这么说比较虚,我们形象点计算。以典型的手机电池,4.2V平均放电电压,3500mAh容量,80%逆变效率计算。总电池容量是4.2*3.5=14.7Wh。总充电时间为14.7⁄0.8⁄10*60=110.25分钟。加上手机在充电时还在使用,动辄充电两小时是正常现象。两小时放在功能机时代也算正常水平。然而功能机时代几天一充?功能机时代我们一天用几小时手机?今天很多人回到功能机时代首先就得饿死,因为手机用不了支付宝。电池容量上不去,我们就只能对快速充电提出越来越高的要求。就算不能一天一充,起码中午续命五分钟。 这里我们得插播一下电池性能。锂电池是一个比较优秀的电池,能量密度大,没有记忆效应。然而坑爹的是,锂电池有锂枝晶,导致电池容量会随着循环而减少,最后报废。从养护上说,最好当然慢慢充。可慢慢充满足不了我们的需要,快充又影响寿命。所以手机厂会平衡两者,设定一定的充电速率。这个速率一般是以C为单位衡量的,反映充电电流(注意,电池充电电压是不可随意变化的,一般略高于当前电池放电电压)。1C代表这块电池以这个电流1小时充满,2C就是半小时充满。反之,0.5C就是2小时。 我看到比较好的电池,基本都能做到1C充电,500次循环以上容量没有过多损耗。按照刚刚的容量计算,充电功率最小也是14.7W。随着电池容量进一步提升,这个值还会不断增大。可现在的充电功率已经达到了USB的最大功率。USB又迟迟不推出权威说法。因此各大厂家就蠢蠢欲动了。现在各大厂家都推出了各自的快充标准。其中又分了两派。 初中物理,电压电流电阻和功率的关系 这里我们要插播一点初中物理常识。功率等于电压乘电流。对于理想世界而言,USB已经锁死了电压,那么电流无限上调就好了。然而悲剧的是,在现实世界里,这需要考虑线阻。 以5V/2A的模式为例吧,简单计算就知道,等效电阻为2.5欧。因此线阻需要在0.x欧-0.0x欧这个量级,越小越好没有下限。一般来说,线越粗,接口越稳定,导电率越高。因此为了对应2A的电流,线就要开始往粗了做。所以很多支持2A充电的手机,USB线就不能随便来一根,要粗要硬,里面全是金属。而且线越长,接口越频繁插拔,线的质量就要求越高。线的标准有个规范叫做AWG。你看下面的性能表,AWG26的铜丝最大电流1.3A,最老的充电线为了省钱,往往是这个规格的铜丝。接口升级到2A后,最好要改用AWS24的铜丝,否则发热会从60升到75。如果要升级到5A这个级别,就需要AWG22的铜丝。从AWG26到AWS22,直径从0.405mm升级到了0.644mm,粗了59%,用料多了253%。所以线贵个三倍是正常操作。如果你正好有MBP,最新type-c接口的那种,他的充电线是3.25A的,应该用的是AWG22的线。观察一下苹果配的那根充电线,再找几根老的充电线,比较一下粗细软硬,心里大概就有个直观印象了。 既然现实世界限制了我们提升电流,那么只有提升电压了。然而这又有另一个问题。高压进入手机后,是不会以同等电压加到电池上的。一定有某个管理芯片进行降压扩流,同时根据电池状态计算充电电压和电流。这个管理芯片的发热,和降压差成正比。锂离子电池常见电压4.0-4.2,充电电压最高可以到4.3-4.4,和USB规定5V的电压差距并不大。然而提升电压充电,在降低线缆风险的同时,提升了手机芯片发热。 因此快充主体分为两类,一类是增压,一类是增流。 快充协议 另一方面,如果一个不支持快充的设备插上来,你不分青红皂白直接提高功率,结局就是对方设备烧坏。这还不如独立一个非USB接口。所以所有快充协议,都需要握手确认彼此的支持情况,再协商一个充电模式。协商的差异,使得快充协议分为了好几种。但无论怎么分,一个协议不是增压就是升流,或者两个都要。 QC协议:高通出品,时至今日仍然是外设最多的快充协议。细节如下: 主体为增压协议。 5V/3A=15W 9V/2A=18W: 最常见规格 12V/1.5A=18W QC自3.0起,支持灵活的电压调整 自4.0起,和PD3.0互相兼容 jd上搜”充电 QC”,结果大概5.2W件 PD协议:官方正统。细节如下: 5V/9V/15V/20V四个档位 普通线缆最大3A,以上电流需要专用5A线缆(貌似PD准备在AWG24上跑到3A,也就是75度这个级别) 某个电压档位*3A等于最大功率。功率只要支持,电压越低越好 15W以下使用5V,15-27W使用9V,27-45W使用15V,45-60W使用20V,60-100W使用20V+5A线缆 jd上搜”充电 PD”,结果大概5500件 其他快充: MTK的PE,增压。jd上找不到相关商品(毕竟是解决方案供应商) OPPO的VOOC,增流。修改USB引脚规则。jd上搜”充电 VOOC”,结果大概800件 华为的FCP/SCP,增流。jd上搜”充电 FCP”,结果大概200件。SCP结果大概100件。SuperCharge结果大概200件 协议兼容和配件选择 目前来看,总体趋势是QC向着PD过渡。毕竟QC目前是使用最广的快充协议,而QC4自己都和PD3兼容了。与其还在小众协议上坚持,不如选用支持这两大协议的配件就好。

Apr 15, 2019 - 1 minute read

996

也许很多人知道,最近有个挺火的项目,叫996.icu。这个项目主要是介绍了软件界常见的”996”加班模式,列举了相关法规和相关报道,并提出了抗议。域名的意义是,加班996,生病ICU。 这个网站在网上的讨论很热烈。我也算是在软件行业里混过一段时间。所以蹭个热点,说说个人看法。 一些基本知识 在说看法之前,首先我想把什么是正常工作,什么是996,以及关于996的一些事实情况(至少是我知道的情况)讲清楚了。否则后面讨论容易跑偏。 谈到996,首先我们需要说国家规定的理想工作状态。工作时间是一周五天,周休两天,每天八小时。当然,规定并没有说明八小时的涵盖内容,因此分为两种。一种解读是,工作八小时,午饭休息一到一个半小时,不计在内。因此9点上班的话,对应6点或者6点半下班。但是有很多福利不错的单位,午饭一小时涵盖在八小时内。因此就变成了朝九晚五的工作模式。很难想象吧。被我们嘲讽当作社畜象征的朝九晚五,其实几乎是最好的工作制。 关于加班,国家的规定是。一天最多可以加班3小时,一周最多加班8小时,一个月最多36小时(一个月4.5周计)。 关于加班工资,国家规定是。延长劳动时间,支付不低于正常工资的150%。休息日安排工作又不能补休,支付不低于正常工资的200%。法定假日安排工作,支付不低于正常工资的300%。当然,对所有公司来说,不低于都会被默认视为等于。 996和一些变种打法 讲清楚正常工作,和加班的法律规定,下面我们就可以对比一下IT圈的实际打法了。996的原始意义是,每天9点上班至9点下班,每周工作6天。按照全部工作时间计算可以看到,周工作时间是72小时。如果扣除午餐晚餐各一小时,工作时间是60小时。横竖都是超过最长工作时间的。当然,名义上叫996,实际上有不同的弹性制做法。例如10-10-6,也就是比996晚上班一个小时,总工作时间不变。这类变形统称996,代表7x小时级加班。在此之上,还有时间更长的997。工作时间70小时,累计的话是84小时,代表8x小时级加班。以及最高级007,代表168小时级加班。由于一周只有168小时,所以007也是工作时间的极限,没办法再长。这个加班制也被戏称为”License to kill”。 当然,007并不是说我们就无需睡眠了。我们可以简单计算一下一个人的时间分配。假设这个人一天睡眠7小时,吃饭两个小时,洗澡上厕所等必要的浪费时间一小时。那么一天有10小时时间是必然处于无法工作中的。因此极限状态下的加班,最长限度工作时间也就是14*7=98小时。大概就100小时,这还建立在吃住在公司的情况下。再加班,就需要压缩吃饭和睡眠时间了。软件行业赶工的情况下,有周工作时间120小时的极限情况。当然,这种状态是注定无法持久的,结束后需要一定时间的放松调整。 996一个隐性前提 其实在讨论之前,我们需要讲一个隐性前提。996认为,工作的产出和工作时间呈正比。所以为了提升产出,我们需要加班。对于现在的软件行业来说,这是一个正常假定,然而并不是一个必然。产出正比于劳动时间,这是工业化的结果。我们的软件行业,正试图将所有软件的生产流程变成一个标准化的工业制度。 然而很多软件生产过程,或者工业化大生产中的几个特殊职位,依然是依靠几个人的直觉,天赋和经验。脑子想清楚比努力干重要,机遇和灵感比脑子想清楚重要。在这些东西面前,劳动时间并没有用,或者帮不上什么大忙,或者反而有害。在这些特殊的场景下,必然是不需要加班或者996的。然而不能因为这些特殊情况的存在,而否认当前软件行业是个工业化大生产的行业(或者说要逐步进入工业化大生产)。 从这个角度说,艺术式的软件开发,既不会产生996(因为没用),也对行业现状没有帮助。因为艺术式的软件开发,注定不能通过增加人手来获得更高的收益,因而不能吸纳劳动力。 分类讨论 讨论加班工资的时候,我们需要按照几个核心问题将情况分为几类。 员工是否在招聘前就知道可能面临加班,大致会是怎样一个加班量级。 员工是否能够收到加班的对价收益。(劳资溢价计入工资或加班后计入加班费都算,福利的话需要足额) 员工是否可以选择加班或不加班,而且基本不会因为这个选择受到除了加班费外的其他影响。 问题一讨论的是透明性,二讨论的是加班工资本身,三讨论的是公平性。一和二的关系非常紧密。有一就有二。很少有公司在招聘的时候大咧咧的说我们要加班,但是请你按照市面上不加班的工资和我们谈。而反过来,有二也很可能有一。很少有公司明明需要员工加班,也明明会足额给加班费,但是招聘的时候不说明白。因为给足加班费的情况下,唯一的问题就是员工本身适不适合(或者说想不想)加班了。隐瞒这个事实,招一堆不适合的人来再开除,也很少有公司这么无聊。这种情况下常见的是,公司自己也不知道下面会有一段惨烈的加班。 按照前两个问题,我将情况分为三类,最后再讨论第三个问题。一类是招聘的时候直接说明的公司。第二类愿意给足额或基本足额工资。第三类就是只有象征性补偿,或者只有福利,或者连福利都没有。为什么这么分三类呢?因为这三类的动机和影响各自不同。 招聘时讲明的公司 第一类的问题最小。在入职前告知,不侵犯知情权,也不套住人才。合同里说清楚996,并且把公平的对价补偿也写了进去。愿意来的可以来,不愿意的可以不来。很多朋友对这类的意见是,认真负责的好公司。 当然。严格来说,在合同里约定超过48小时每周的工作时间也是违法的。所以很多公司会有工作制告知,但是并不会体现在合同中。只要这个告知早于员工接受offer,那么就可以算为此类。 这类公司,加班的动机往往是程序行业的内在动机。可能很多圈外人不知道,软件行业的效率,和项目人数的平方成反比,随着参与人数的增加而迅速降低。这个观点是Frederick在人月神话中提出的核心观点。他的解释是,软件工作中,有一部分非常重要的工作就是沟通。程序员需要让彼此了解对方意思,才能写出一致无误的软件。而沟通很难群体进行,因而沟通的成本是和团队规模的平方成正比。因此实际践行中,一个团队的理想大小,会限制在10人上下。如果要再扩充规模,往往会虚胖。即团队内实际产生战斗力的人员仍然在10人上下,其余人就是围着干零活,感觉有力使不上。因此大型软件工作往往会采用横向或纵向的模式,来切分工作。例如将一个大型系统分为几个功能模块,约定好彼此的接口,分别开发,最后联调。这样做往往使得模块和模块间产生不少问题,甚至可能导致漏洞或逻辑问题而无法使用。然而从软件工程角度讲,仍然是一个非常好的提升总体速度的方法。当然,模块的切分也是有限的。模块越多,模块间的协调成本越高,总体质量变差的可能性越大。通过模块切分的方式,也无法实现无上限的加人。 那么,我们也就很容易理解这类加班的内在理由了。加班10%能解决的工作量,招人的话需要多招20%。这意味着更多的争抢,更大的人员流动性,更多的培训,磨合。而且加人还需要重新安排团队,更细化的切分项目,更频繁的沟通会议,更高的高级管理人员成本。就算能招到人,最后总成本上升可能远远超过20%。同理,996的加班高达50%-80%,如果招人的话,大概要招2-3倍以上的人,成本则可能高达3-4倍。就算按照加班工资实打实发,加班成本也就是2.2倍。作为管理者,有百分百的动机选择加班,而不是招人。对于他们来说,更实际的做法是入职的时候直接谈一个相对于不加班2-3倍之间的溢价package。员工也能赚钱,公司也能省钱。 愿意给予相当补偿的公司 第二类公司,起码还不算坑到底。如果是一般加班,老板的选择往往是强制结成年假,而不是支付加班工资。因为休一天损失100%工资,支付加班工资可要付150%-300%。然而996的加班往往太多。总不能一个部门半个房间都在休假吧。所以也有协商,部分结算,部分转为年假。 这类公司的理由往往是一般正常公司都有的,软件行业峰谷影响。例如,做2B的知道,年底的时候各种突击花钱,突击签单,争取用光预算。到了来年三月的时候,就变成了非常紧的项目压力了。然而到了下半年接近年底的时候,项目做的差不多验收了,往往单子又会跟不上。因此有些公司会选择以年为周期进行加班和调度。年初的时候多加一些班,到年底开始强制员工休假。如果休不了才进行加班结算。 特别注明一下。首先,这类年级调度加班调休的公司,如果超出每周8小时也是违法的。其次,公司原因导致的停工,其实不需要计算为假期。如果员工不同意使用自己假期,原则上单位需要照发工资和加班补贴。让不让员工干活随意,但是钱必须发。然而,很少有员工和单位这么对着干。 基本无补偿,甚至无福利的公司 这类公司是最常见的,其基本想法就是压低工资或是降薪,或者又干脆裁员。 压低工资很好理解,这似乎是劳动力密集型行业的通病。和员工谈的时候只谈工资,招进来就往最大工作时间利用。为了让员工不走,甚至会使用押金或迟发工资这类手段。这类事情员工通常得不到政府的救济。毕竟农民工欠薪这种事都要总理亲自去要。只是加班而已,似乎也就不那么严重了。一家两家如此做,多了之后,劳方也不管你们加班不加班了,总之就按照加班的开薪资。资方说不加班,劳方不敢信。一来二去,逆向选择,不加班的公司不好混,大家就都开始加班。而一旦成为行规之后,劳方更是不会相信什么不加班的事情。其实这个情况和招聘时讲明很类似,差别在于大家对加班与否的认知不统一。劳方认为我就是值这么多钱的,不加班就是这么高工资,所以公司没有加班费,属于违法违规。公司则认为,员工根本不值这么多钱。之所以给这么高溢价,就是因为要加班。最后就很容易发生纠纷。 我常见的情况是,如果是劳方市场,员工选择权更多,资方往往倾向于招聘时讲明白。因为一旦员工入职后发现劳方和事实相差太大,可以自行离职,不怕找不到工作。那么资方就要承担成本了。而如果是资方市场,通常就是大家都揣着明白装糊涂。反正入职后跑不了。 其实程序员现在也不笨,如果是大公司的话,一般也会找人打听打听是否在加班,面试的时候也会问。但是你可以看到各大公司对加班的态度,大部分对公开媒体的态度都是粉饰加班的,只强调要求员工全情投入。实质上我们知道这个说法也就是说说,不信你试试入职后问你老板,我的工作态度端正绝对全力投入,但是我就是不加班,行不行。 降薪和裁员是大家意见最大,也是反弹最大的。毕竟996相当于公司宣布降薪一半以上,不可能没反应。这个主要是因为软件行业景气状态有波动。仔细观察毕业生薪资就能发现,往往是一年出现天价,第二年就跌穿地板。软件行业的发展不全是线性的。一旦不景气,老板就有压缩成本的动力。压缩成本两个思路,一个是降薪,一个是裁员。然而降薪不好听,裁员补偿极高。怎么办呢?两个问题有同一个解决方法,996。如果同意的话,就是变相降薪了。不同意就无补偿离职了。这个思路有个尤其恶心的实现,就是年底的时候宣布996。这时候走人,连年终奖都省了。 实话说,这种手段叫杀人一千自伤八百。因为肯放弃年终奖和赔偿的主要理由,最主要是因为有一个不错的潜在机会。与其在这里熬着,还不知道拿不拿的到。不如在新工作的margin里找回来。相反,如果没有潜在机会,那不妨先混着。然而能很快找到不错的机会的人都是什么样的人?所以这种策略下最先走的,往往都是公司里的精英。反而是公司想开掉的平庸者更有动力留下来。 公平性的影响 所谓公平性,就是员工能够自己选择是否参与996。因为从道义上说,除了上面的第一种情况,员工和公司的合同只涵盖了40小时工作时间。国家标准也只涵盖了最多48小时每周的工作时间。除此之外的时间,员工并没有义务来工作,给没给够工资都没这个义务。加班费给够了,愿意来,是自愿选择。给够了,还是不愿意来,那是个人选择。不愿意来就给穿小鞋,在bonus和升迁上刁难,甚至威胁开除,这就是逼迫了。 然而现状是,很少有公司敢于说自己是公平的,甚至很少有公司意识到这个问题。大部分公司在考评的时候,都会有一项,工作积极性。其中不愿意加班的人,这项肯定不会太好看。然而细想的话,用员工下班后的表现,考评员工的*工作*积极性,这是个什么道理呢? 一个隐性的问题 996是不是好事?当然不是,对于大多数人都不是。首先第一点无可反驳的理由。这个行为违法。要相信国家,相信法律嘛。然而法律为什么规定40个小时呢?是不是太保守了?一周最高98个小时,干个70小时不过分嘛。 996对于个人来说,既是个机遇,也是个障碍。短期来说,会有一份非常不错的收入。而且996能为程序员提供很好的上升机会。因为学东西的速度是和工作时间相关的,而上升通道是和毕业年限反相关的。一个机会,同样水平的人,一个毕业一年,一个毕业五年,当然是先选择毕业一年的,因为潜力更大。996能够极大提升新手的机会。 然而当程序员进入30后,后遗症就接踵而至。首先,996会减少员工和家人朋友相处的时间。会做程序员的人本来普遍就不会特别善于交际。相处时间进一步减少后,就很少能有足够的时间谈恋爱。所以程序员单身狗的名号不是白来的。虽说结不结婚是个私事,然而从国家总体角度来看,这当然是个坏事。都没结婚,哪里来的二胎?靠女装么?其次,996普遍减少学习的时间。这使得程序员除了公司相关技术外,自己学的东西很少。软件行业又是个更新换代非常快的行业。最后,当技能没有更新的程序员,和愿意996的竞争者竞争的时候,往往就会被淘汰。因此常有个说法,程序员过了35做不下去。这对个人和行业来说都不是个好事。 所以总体来看,最好是30岁之前996,30岁之后正常工作。然而工作制度的事情并不是随个人想法而改变的。对于行业来说,如果规定至少150%工资,那就是150%。没有人会多给。对于行业来说,一周标准是50小时,那坚持工作40小时的程序员就会失业。之所以要确定行业标准是因为,企业一定会在标准范围内最大限度的利用资源。如果没有统一的行业强制标准,会出现这么一个现象。某个企业提出加班到一周50个小时,另一个企业提出加班到60小时。25岁的程序员说我可以接受70小时,22岁的说我可以接受80小时。这么搞下去的结局是地狱。 这个问题,即便是第一类公司,也没有解决。他们能做的只有,给员工足够的工资,足够的晋升平台。但是他们却不能说给行业做了个好榜样,甚至不是一个好的竞争者。他们的成功,无疑鼓励所有公司尽情加班,只要给钱。无疑限制了程序员行业只能牺牲年轻的肝,让他们在35之后面对茫茫的未来。同时也限制了软件行业的总供给,因为35后的都转行了。 因此,国家制定了各种规章。即便牺牲总体效率,也要限制无底线的加班竞争。而且这一点不仅限制没给够补偿的公司,也要限制给够了补偿的公司。然而很遗憾的,这些规章非但没有贯彻,甚至不被理解。 主人翁意识 很多老板提到主人翁意识,提到拼搏奋斗。拼搏奋斗当然是对的,然而主人翁意识就要看员工在整件事里的收益了。我们不常提,然而又无法避免的一件事是,员工和老板很多时候不是一条心的,甚至往往是对立的。员工不是企业的拥有者,不在企业的获益里有分成(或者说不是所有员工都有分成,有也不一定是对等分成)。要求一个不从整件事里获益的人,为这件事拼搏,本身并不合逻辑。这个问题更扩大点,国家也要求每个公民有主人翁意识。为啥各位大老板不能者多劳一点,把每年的盈利全上缴国家呢?主人翁意识的前提,就是员工从整件事里获得合理的收益。而合理收益的最直观体现,当然是加班费。连加班费都没给够的公司,我们又如何能相信公司能为员工提供足够的分成呢? 事实上,主人翁意识本身就是个悖论。如果员工真的有将企业当作自己的事业来干的干劲和能力,那么他为什么不自己创业呢?现在社会,技术不是壁垒,资本不是壁垒。创业可以说是最好的时机。从这点来推论,大部分在企业内就业的人,要么是不会将自己视为企业的主人,要么就是将要创业的。 有什么可以做的 最简单的,请慎重考虑996的度,以及对人生的影响。有些公司996是因为真的临时有问题。这种公司虽然短期内不合法,但是我仍然认为值得一去。然而多短,多大程度的加班才是可接受的。这个加班又会如何影响你的人生呢?请自行仔细考虑。起码,我不希望我的读者因为996而去世。如果你觉得无法容忍,最低限度的,你应该离开。 其次,我希望大家都提升效率,更有效的工作,并离开996的公司,参与规范工作的公司。这不仅对你有帮助,而且能够帮助整个行业。因为如果做事规矩的公司,因为你而可以对抗施行996的公司,那么会给市场上多一些选项,给其他人多一点希望。 最后,我们希望大家帮助劳动法落地实施。劳动法并不是一部闲的没事干的法律,尤其是劳动时间限制这块。我们有很多法律缺失,然而加班这块法律实际存在,却没有实际实施。所以希望大家在面对权益损害的时候,能够勇敢的合法对抗。至少国家现在也在宣传依法治国,那么实践一下总没错吧。即便不想亲自对着干,也可以考虑支持或给予方便。最低限度,希望大家理解支持并同情权益受损的人。毕竟这些人,可能是你的昨天或明天。 其他行业的一点情况 当然,最后我要说的是,程序员是一个特殊的群体。我们毕竟有高收入,可能无法,但是也可能可以弥补我们加班逝去的青春。我们有发声渠道。社会还能听见我们的声音。然而社会上还有很多行业,加班程度远远超过程序员。例如出租车司机。就我了解,这个行业的特性是做一休一,24小时交班。计算一下就知道,周工作84小时,追平997。但是这是司机的日常。一年365天,连春节都要上班,还得面对程序员写的打车软件的竞争。你看出租车司机有开11365.icu吐槽一下么?又例如医生。在住院医阶段,就是住在医院里的。这个位置的意思就是007,一周98小时。而且医生需要压缩睡眠,工作时长甚至超过007,持续还得持续一年。你又看谁说我们医生太辛苦了,我们把医院关了吧。或者医生收入太低了,我们把诊费和工资翻个倍吧。 我写这些例子,并不是说大家都是这么过来的,你们程序员贱人就是矫情。我是说我们有很多不公平的工作制度,在伤害个人,在伤害行业和整个社会的未来。我们在经济大发展的年代,一切都要跑步前进,没有停下好好看路,也就罢了。现在经济不景气,大家日子都不好过。在这个时候还疯狂加班,是想干什么呢?不如趁机把这些事情扳一扳。毕竟,很多事情再不扳,就来不及了。

Dec 24, 2018 - 1 minute read

关于抵制洋节

其实这事没什么好多说的。不过节日这件事本身有点意思,所以展开说说。 节日的分类 首先,节日分为两种。法定节日和其他节日。法定节日的特殊性在于国家的承认。其中又有一类比较特殊的,公休节日,主要就是放假。很多人其实搞不清节日和假日的关系。简单点说就是节日不一定放假,例如植树节,也是我国承认的节日,但不放假。按照我国的法定假日列表,我们总共放11天假。春节和国庆各放三天,元旦,清明,劳动,端午,中秋各一天。这里我插一句,在两岸四地中,大陆放的算比较中等的。大家可以参考这张两岸四地节假日列表。大陆正常放假11天,妇女多半天,不满14岁儿童多一天,14岁以上青年多半天,军人多半天。台湾13天公休,劳工多一天。香港17天,澳门20天,但是周六只放半天,全年比台湾大陆要少26天假期。综合算下来,台湾休假最多。 如何界定一个节日 现实情况中,其实有非常多的节庆混杂的情况。有来历一致但是其他都不一样的,有时间一样来历和名目不一样的。还有其他都一样但是时间不一样的,例如圣诞节在东正教这里就是1月7日。又例如日本新年。虽然日本新年和中国春节的来历一致,但是习俗不一致。更过分的是,日本新年用的是公历,所以是在每年一月一号。还有香港的冬至和圣诞,是混在一起过的,这个也很难分清楚到底算不算传统节日。 那么,什么标志一个节呢? 一个节有几个基本属性。名称,来历/起源,习俗,时间。其中最容易不一样的就是习俗。我国各地春节习俗不一,但不能说他们就不是一个节日了。至于名字,一个节日多个名字倒是常态。关键是起源和时间,哪个能界定一个节日的唯一性呢? 我个人看法是,追溯来历一致。如果来历一致但是时间发生变化,例如中国春节和日本新年,基督教和东正教的圣诞,均归为一个节日。而如果时间一致而来历不同,例如香港冬至和圣诞,则归为两个节日。 什么叫洋节? 什么叫洋节呢?我们狭窄点定义。凡是1911年之前存在的,非中国传统节日,统统算洋节。1911年之后算新兴节日或纪念日。之所以按照1911算,是因为1911清朝结束。之后的建党建军之类的节日不会被算成洋节。 我们法定的节日里,元旦和劳动节是洋节。春节,清明,端午,中秋是传统节日。国庆是新兴节日。 哪些洋节我们不过? 我们可以对比美国节日。其中大部分节日我们都是不过的。和中国大众交集最大的有三个,元旦,圣诞,感恩节。加上流行节日里的情人节,愚人节,母亲节和万圣节,总计七个。其中只有元旦是法定节假日,其余不是法定节日,更不放假。 顺便一提。美国总计放假12天半。独立日三天,圣诞节一天半。比大陆好点,和台湾水平差不多。 这里要特别说一下美国的劳动节。美国劳动节不在五一,庆祝的事件也不一样。但是庆祝的目标是一样的。遵循上面的原则,我将其归位不同节日。 哪些传统节日我们不过? 那么中国传统有哪些节日呢?这个比较多。细表可以看汉族传统节日。其中比较大的有这么几个。春节,元宵,清明,端午,七夕,中秋,重阳,冬至。其中我们不过的节日有四个,元宵,七夕,重阳,冬至。 过节到底在过什么 实际上,近些年来过节的庆祝和纪念意味已经越来越淡。端午节变成粽子节,中秋节变成月饼节,春节都有不会去团圆的了。随着近代城市化进程,节日的宗教和纪念意义正在逐渐屈服于生活现状。拿清明为例吧。住的近的还能去爷爷奶奶坟上看一看,老家远真没办法跑个一天回去,就为了在坟上慎终追远一番,然后再一天跑回去。只能春节回去花半天上个坟。随着年轻人跑到城市里打工,家族长辈的影响力也是逐渐在减弱的。也许再过二十年,一个大家族的孙辈就不怎么回去了。这种情况下,要提倡复兴传统节日,实际上是有困难的。 洋节的本质问题 那洋节呢?为什么洋节那么火?这里我们要提出一个洋节的本质性问题。实际上我们过圣诞,并不是真的在当圣诞过。大家在圣诞夜里会去教堂么?我们过的所谓圣诞,感恩,情人,愚人,等等这些节日,本质上是一种节日,促销节。洋节会火,实际上来源于我们对他们的不了解。我们知道圣诞节有圣诞老人送礼物的传说,但是很少知道圣诞节有很多宗教活动。情人节,实际上变成了约炮节。以至于我们所过的每个中国和外国节日,基本都是,礼物,礼物,礼物。这种情况下,要扯一个我们熟悉的节日有什么和消费有关的传统比较困难。例如端午,说破天也就是吃粽子。要扯什么,我们要拿粽子丢来丢去,丢你老母啊。至于清明,促销能去促销套套么?这是要坟头蹦迪,给祖宗现场即兴表演的意思?而我们没听过的情人节,显然就有更多玩法,例如日本人搞出来的白色情人节。很明显就是促销节。更著名的应该是光棍节促销,每年都能创下网络购物的记录。所以在扯淡促进消费上,传统节日不及洋节,洋节不及新兴节日。 能不能抵制洋节? 彻底抵制的话,实际上是很难的。要彻底抵制洋节的话,就涉及到两个国定节假日,元旦和劳动节。这两个节日都是国家强制放假的。如果要彻底抵制洋节,那么就要在这四天继续上班,并且主动放弃加班费。毕竟,你都不拿他当节日了,还继续放假,或者拿三倍加班费,说不过去。所以如果是全年加班的岗位的话,那还有点基础。 如果说非彻底抵制。国家放假我还是放,但是不参与不纪念。其余非法定节假日也不参与不纪念。那么除了单身狗在情人节会有点麻烦外,和现在现状也差不多。毕竟我们现在,也就是不参与不纪念,放假和消费而已。

Aug 20, 2018 - 1 minute read

恒春潜水记录

地点在恒春的后壁湖,岸潜4次,船潜12次。岸潜地点在核电站出水口左侧右侧和软珊瑚区域(潜点就叫这个名字,俗吧)。深度都不怎么深,但是越过一堆礁石比较困难。有鞋子保护好歹脚不痛,但是这双鞋子防滑性能一般,我差点在岸边溜冰。 船潜地点在外侧的几个礁石,深度都比较大。独立礁(瞧瞧这名字起的)悬崖部分深度超过30。我有几支用了EAN32,下不了32米的深度。至于其他人,他们基本都没有DD的证,本来就不能下去。 在垦丁附近潜水,最大的风险来自于低温和大流。我本来还和潜导说我就水母衣下吧,反正水温都在29-30左右。潜导说你碰到斜温层就知道厉害。垦丁这里有很多斜温层,底层温度会骤降5度左右,我记录的最低温度是22度,3mm的湿衣冻成狗。比我在PG外岛碰到的斜温层强大的多。最大的流在3节左右。负浮力下水后还没动作抓绳,先被大流压到了梯子上。比我在泰国碰到的流还猛。比较值得欣慰的是,基本都是横流,很少有垂直流或洗衣机。不过同时也有个坏消息。垦丁这边有很多的浮潜,水上摩托和香蕉船。这几个活动的危险性就先不去说了,水上船只频繁运动的情况下,是很容易撞到的——尤其是没有SMB的情况下。 垦丁的能见度不高,一般只有5-10左右。但有趣的是,在斜温层下方,能见度反而更好。往往有10米以上。肉眼可见的原因是因为斜温层的温度有利于浮游生物的生长。不过这也造成一个问题。在垦丁水下拍照,是一定要补光的。因为上方自然光都被表层海水吸收了,底层虽然能见度不错,但光线不足。 物种多样性来说,还不错,经常能看到蓝点鳐,厚唇石鲈。我还看到了龙虾,海蛇和海龟。有看到一只豆丁海马,不知道照没照清楚。出水口左侧的软珊瑚区里,有一堆海胆正在搬家。在核电出水口附近,照道理说,水温会比较高,可能引起珊瑚白化。但实际上珊瑚还不错,偶尔见到白化。 上次在垦丁浮潜,有严重的水下垃圾问题。这次无论是船潜还是岸潜都没有看到特别严重的垃圾问题。有见过几张纸,一次见到塑料袋。比起其他国家来说没有明显糟糕。后来我考虑了一下,水下垃圾估计是因为沉没在水下的部分无法在净滩中清理。浮潜和深潜业者当然有动力去清理他们看到的垃圾(毕竟关系到他们的饭碗),但是这并不能覆盖全部海滩。因此这次我的活动范围可能被清理过,而上次的活动范围则是问题比较大的部分。 在潜水间隔和船长聊过,他们其实是渔船,属于娱乐渔业。每次出海的时候,是要有海政属的人来点人头的。这也间接造成了船的大小很大,每次出海成本很高。我这次是一条船出海一次潜两支,1000NTD。上面往往就三五个人,很多时候教练都比客人多。其他国家经常是一条小船就出去,船上也是三五个人。这样的成本差异接近数倍。 最后说说交通和生活基础设施。恒春没有通铁路,只能通过垦丁快线(巴士)来返。从恒春到左营大约是两小时左右。但是去的时候最近一班车没票,回的时候正常车都没票,最后在等加班车。可见总体运力并不是很足。住宿方面,恒春老城里有很多民宿,可选择空间很大。我很喜欢乡村鸭肉冬粉家的卤味(不是他家冬粉),和对面的洋葱冰淇淋(是的,洋葱冰激凌,恒春产洋葱)。基本来说,你可以认为,这里除了可以讲中文外,基本和你去的其他潜点没什么区别(主力语言还不是普通话,而是闽南语,大部分人聊天的时候,我感觉和东南亚没啥区别)。

Jun 14, 2018 - 13 minute read

递归有关的几个小问题

引子 在加密系列里突然出这么一个问题,确实有点怪。我犹豫了一下,还是先写了再说。 这个问题的提起,是公司老大kay提出一个问题。在反转链表的时候,如果有环怎么办。然后我们就现场写各种解环算法。这个问题本身不难,我们先看一下原始问题和解,还有带环反转。 Scheme反转链表 想了想,还是先写Scheme版本。这个版本实现简单概念清晰,个人觉得非常典型。而且对后面理解Python版本很有帮助。如果看不懂的话,可以直接去看Python版本。Python版本看不懂了再回本章来,去看Scheme入门教材。 Scheme的正解版本只有一个,就是带复制TCO版本。 (define (reverse-tco ll rslt) (if (eq? ll '()) rslt (reverse-tco (cdr ll) (cons (car ll) rslt)))) 这个版本体现了Scheme的几个特点。 递归比迭代好使。 强制要求TCO。 cons操作起来非常方便。 Python递归反转链表 def reverse_tco(ll, rslt): if not ll: return rslt return reverse_tco(ll[1], [ll[0], rslt]) 这是链表最简单的问题,也是递归论最基本的问题。注意这里采用list来模拟了lisp中的cons,不用tuple主要是后面还有环,需要修改数据。如果你不明白,可以先看Scheme版本的代码。 递归转迭代 写到这个水平,其实有一半的被面人就挂了(好水)。但是这个水平其实也就是入门水平。最低限度,也要知道上面这个递归是可转写为迭代的。更进一步的,要知道这个递归是个尾递归。下面我们把这个代码转写为迭代形态。 def reverse_iterate(ll): rslt = None while ll: rslt, ll = [ll[0], rslt], ll[1] return rslt 或者非生成节点版本。 def reverse_iterate(ll): rslt = None while ll: rslt, ll[1], ll = ll, rslt, ll[1] return rslt 这里的区别,其实是SICP第24页所说的“递归计算过程”和“递归过程”的区别。具体请直接参考原书,我就不打字摘抄了。

May 12, 2018 - 3 minute read

openssl证书相关

鸣谢和前言 首先感谢Ivan Ristić。本篇很多内容可以从他的这本书里读到。大家如果有钱,可以买来支持一下。没钱但是英文好的话,也可以直接读一下(这本书在网上是公开的)。本文没有直接复制,引用,或是完全写成读书笔记。所以原则上是不受书的版权限制的。不过如果作者有异议的话,我愿意下线这篇文章。 First of all, I wanna say thank you to Ivan Ristić. I got a lot of help from this book. You can buy one if you want, or read it personally (it’s public). This is really a good book. In this article (I mean the one you are reading currently), I don’t copy or reference directly from that book. So as far as I know, it shouldn’t have any copyright problem.

Apr 1, 2018 - 2 minute read

openssl基本密码学操作

openssl的基本检查 使用以下命令检测版本,-a可以提供完整数据。 openssl version openssl version -a speed test speed测试是openssl为你跑一下不同算法在你机器上的实际执行速度,这项测试在openssl中是一项非常有指导意义的测试。一方面,他给出了你选择算法的依据,通过实际数据告诉你每个算法能跑多快。另一方面,他可以用来评估不同硬件对算法的加速能力。如果仅仅是给出了选择算法的能力,我们一般都可以得到一个一般性结论,例如chacha20比AES快。但实际上很多CPU带有AESNI指令集,这种情况下AES的执行速度反而会更高。所以运行性能是和执行平台紧密相关的。关于这部分,可以参考Intel对OpenSSL的性能优化。 具体的测试方法是 openssl speed 后面可以跟算法,只测试特定的算法集。 我这里跑了一遍全集,挑几个重点算法说一下性能吧。 hash算法 sha256,标杆性hash算法,64字节小数据140M/s,8k大数据353M/s。sha512,170/470。hash算法的内部状态越长,在连续计算时的速度越快。 sha1,251/768。 md5,243/575。(你没看错,md5比sha1还慢) rmd160比sha256还慢,whirlpool比sha256慢。最快的是ghash,小数据4222/9732。但是见鬼的是,我查不着这是TMD什么算法(openssl list -digest-algorithms的输出里没有)。 最合适的算法,应该就是sha-512/256了吧。很安全,速度比sha256快,长度也不算太长,还能防御LEA(Length extension attack)。 对称算法 aes-128-cbc,标杆算法,120/125(M/s)。aes-192,93/103。aes-256,86/88。aes的内部状态越长,在连续计算时的速度越慢。这点和hash正好相反。 camellia128,138/167。camellia192,110/128。camellia256,109/124。这是一种大批量数据计算非常优越的算法,AES在计算大批量时性能上升并不快。 des比aes慢的多,只有66M/s。3DES更慢,只有25M/s。 没有chacha20。 不考虑chacha20的情况下,最好的算法应该是camellia128。当然,工业标杆是aes-128-cbc。 非对称算法 rsa 1024/2048/3072/4096的sign效率分别是8698/1351/453/206(个/s),verify效率分别是131847/46297/22970/13415。rsa也是随着内部状态上升效率下降的,而且下降非常快。而且verify效率远高于sign。 dsa 1024/2048的sign效率分别是9836/3280,verify的效率分别是10584/3616。 ecdsa 192/224/256/384的sign效率分别是12696/12672/21016/4383,verify效率分别是3200/5630/9994/1019。能很明显看出来,sign效率比verify高。256位的时候由于某种效应性能达峰,后续直接断崖下跌。 ecdh 192/224/256/384的效率为3642/8339/15094/1183。同样能看出这种效应。 rsa和ecc不具有互换性。rsa参数选择建议2048,ecc参数选择建议256。 对称加解密 openssl支持多种对称加密算法,可以直接对文件加解密。在使用前,我们首先列出系统上支持的算法。 openssl enc -ciphers 输出很复杂,不列举。我们直接讲我的机器上分析后的结果。 第一段是密码算法。在我这里,支持以下算法:aes, bf, blowfish, camellia, cast, chacha20, des, des3, desx, id(ea), rc2, rc4, seed。 最后一段有可能是模式。在我这里,支持以下模式:ECB,CBC,CFB,OFB,CNT。其中CFB,OFB和CTR(CNT)是可流式的,其余都是块式的。关于加密模式,可以看这篇。 在enc的manpages里明确说了,enc不支持CCM或是GCM这类的authenticated encryption。推荐是使用CMS。 例如我们使用比较流行的chacha20来加密一个文件src,里面可以随便写一句话。

Mar 8, 2018 - 2 minute read

密码学基本原理

Digest 摘要为一个函数H。对任意数据d,有h=H(s)。同时至少满足下面特性1。其余特性为额外要求。 对相同的数据d1=d2,计算得到h1=H(d1)和h2=H(d2),必然有h1=h2。但不要求h1=h2的情况下,必然有d1=d2。 根据h计算任意一个可能的d极其困难。(安全性) d服从随机分布的情况下,h的分布足够随机。(均匀性) hash系列函数 hash系列中最著名的即MD5,其后继者为SHA1,SHA2,SHA3等。但实际上这几个都是密码学hash函数。非密码hash常用于快速计算均匀散列值(例如hashtable),代表有CRC (实际上CRC主要的目地是校验,而不是散列), FNV,Murmur。这几个非密码hash函数的对比可以看这里。 hash函数需要注意长度。一般来说,长度越长越安全(越难被找到一个碰撞值)。但是过于长的值会在保存和使用上产生困难。 Rainbow table Rainbow table是一种通过预先计算来碰撞的手段。 从粗略的角度来说,你可以认为这就是一个巨大的反向hash表,保存了所有计算过的hash和对应的碰撞数据。但是通过计算可知,这样的反向表会占用巨大的存储空间。彩虹表采用巧妙的算法缩减了空间消耗。 其基础思想是,对某个碰撞数据,计算其hash,随后通过某个算法R,将这个目标hash再映射到另一个碰撞数据上去。通过这种方式,一个碰撞数据可以持续的计算出一串不同的hash。假设这个长度为n,我们最后保留最终一个hash和最初一个碰撞数据。 在检索某个hash的原始碰撞数据时,我们可以利用R将其映射为碰撞数据(但不是我们需要的那个碰撞数据),进而计算hash串并检测是否在反向表里。如果表里存在这个hash的碰撞数据,那么在生成n步的hash串的过程中,必然能在反向表里发现命中。而当发现命中后,就可以通过原始碰撞数据算出整个碰撞链,从而找到该hash的对应碰撞数据。 从算法分析的角度来说,这是一个空间换时间和时间换空间同时存在的巧妙算法。利用反向表计算原始碰撞是用空间换时间,用hash串来压缩空间消耗是用时间换空间。 另一个细节是hash链的碰撞。当hash链在某个节点相同,后续链条必然完全相同。这大大降低了hash串的效率。因此彩虹表采取了一个变形。算法R在n步中每一步都各不相同(实际一般是将n当作参数),这样使得hash碰撞只发生在一个点上。由于算法在每个步骤上各自不一,因而得名彩虹表。 KDF 密钥生成算法( KDF )是一类算法的统称,用于将一个密码/密钥变换成另一个(或多个)密码/密钥。在这个过程中,会提供很多额外特性。例如符合特定格式,防御暴力穷举攻击,保存后难于破解原始密码,等。 KDF的最知名场景,就是密码保存问题。用户的密码不应直接保存,这样在万一数据库泄漏时就会泄漏原始密码。而单纯hash会导致用户密码遭受彩虹表攻击。一般解决这个问题的方法是对密码加盐。但是盐是加在前面还是后面呢?以我个人的分析来看,似乎是没有区别的。即s+salt和salt+s都能保证安全。当然,更好的方法是用scrypt或bcrypt。他本身就有专门的函数保证密码安全保存,这可比加盐好使多了。 最佳实践 现在已经2018年了,我相信大部分读者都应该知道MD5和SHA1不安全的事了吧。这两者虽然还能完成摘要的用途,但是并没有安全保证了。如果你需要一个安全的hash算法,我推荐sha2。sha3目前并没有进入主流系统,而且执行速度还是略慢。 另外,如果有的选择的话,在sha2算法族里我推荐SHA-512/256或SHA-512/224。这两个算法有助于避免长度扩展攻击。 Encryption and Decryption 对称加密解密为一对函数,加密为E,解密为D。对任意数据d和密钥p,满足下面要求1和2。 加密为e=E(d, p),解密为d=D(e, p)。 攻击者得知E,D,e的情况下,无法反推d和p。 在条件2的基础上,攻击者能得知d和对应e的情况下,无法反推p。(已知明文攻击) 在条件2的基础上,攻击者能构造d并得知对应e的情况下,无法反推p。(选择明文攻击) 对称加密有几种可能的变形情况,例如E和D为同样的函数,一次加密第二次解密。或者由生成算法构造出密钥p和解密密钥p’。在其中密钥p可以推算变换为解密密钥p’。但这其实仍然符合上面的描述。因为解密时可以使用d=D(e, p'),而p'=G(p),因此d=D(e, G(p)),即可认为d=D'(e, p)。对于密钥p无法推算出解密密钥p’的情况,请参考下面的“非对称加密”。 DES/AES加密解密算法 加密算法中最有名的是DES和AES。关于这两个,我们不赘述。 密码模式 加解密算法一般都是以块模式运作的。即每个加密算法都有一个特定的长度,他只能处理这个长度的数据。块密码模式算法将基于某个特定的块算法,将其应用于流上。 最简单的用法是重复进行加密。取明文的前N字节加密,得到N字节密文。重复直到得到最后一块数据,数据的长度必然大于0小于N。对尾部的数据补足0。最后将所有密文联合起来,得到最终密文。这种模式叫做ECB模式。 ECB模式的好处是简单,但是ECB并不能防御内容替换攻击。攻击者可以通过某种方式获得一个数据的加密形式(选择明文)B’,然后将某个加密后的块B’替换原始块B。以此,虽然攻击者并不知道原始内容,但是可以替换其中的部分内容。 人们对ECB做了一点改进,使用上一个块的加密结果,对下一个块做干扰(具体使用XOR)。如此一来,对任意一个块的变更会导致后续块全部都无法解密。第一个块没有上一个块,也就没有加密结果。所以CBC需要一个初始向量IV来初始化干扰。而先加密上一个块的结果,再和当前数据XOR的算法,被称为CFB。CFB和CBC仅仅顺序上有区别,但是CFB可以用于流式加密,而CBC不行。因为CBC必须得到一个完整块,才能计算加密。而CFB预先算出mask,用XOR获得结果。 CFB再略变化一点,就可以构成OFB。OFB取的是XOR前的结果,因此加密序列并不受明文的影响,只受IV和key的影响。你可以想像,OFB是一个由IV和key已经决定好的,无限长的mask,逐步XOR到明文上。 但是CFB和OFB都有一些缺陷,例如明文和密文的异或对应性。在确定模式为CFB或OFB的前提下,对某些特定位置遍历所有可能空间,就能在不了解解密结果的前提下遍历所有明文可能性。这个问题被用于ss的主动探测上。 密码模式具体可以看这里。 Salsa20 Salsa20原来叫Chacha20,是一种经过特别设计的密码系统,在未经优化的CPU上拥有非常快的执行速度。 最佳实践 可能和大家想像的相反,一般没事不推荐直接使用加密函数本身,而是推荐使用AEAD算法。这里有一份2015年密码学最佳实践,按照推荐,是使用AES-GCM或Chacha20-Poly1305最好。这两种都是AEAD,具体下面有介绍。 如果一定要用加密算法,而非AEAD的话。推荐使用NaCl。它的加密算法默认选择是XSalsa20/20(Salsa20的一个变形)。 Message authentication code 消息验真,不同于摘要,要求的是拦截者无法伪造。其前提条件是发送者和验证者有一个共同的秘密p。本质上看,这个就是签署(sign)。但是一般我们讲sign都是指非对称的sign,MAC是对称式的。对称签署为两个函数,签署为S,校验为V。对任意数据d和密钥p。 对于签署获得的v=S(d, p),可以用V(d, v, p)来检验d和v是否成对。 攻击者在得知S,V,v,d的情况下,无法反推p。 签署算法经常和摘要算法合用,即对数据d先使用摘要H得到摘要,再计算签署。即v=S(H(d), p)。验证时使用V(H(d), v, p)来验证。

Jan 30, 2018 - 1 minute read

similan船宿

大致情况介绍 Similan archipelago,在Thailand,Phuket西北方一点的位置。要从Phuket坐一个多小时车,到一个叫做Khao Lak的地方。然后再坐船出海,走大概两三小时。地图上看,在Thailand的外海,离海岸50公里以上。(这应当是公海了吧) 潜店和船 我们是让朋友报的船,到了才知道,潜店是这家Khaolak Scuba Adventures,船是三天三夜的一艘Manta Queen 5。船宽5米长26米,推荐容纳20人,实际容纳22人。推荐船员5人,实际7人。推荐潜导5人,实际7人(含manager)。 这艘船,怎么说呢,家吉一看就觉得很坑爹,我觉得还好吧,毕竟这个价格。船舱里面是上下铺的床,都是软垫铺一层床单,加一个枕头和被子。床很小,大约60-80公分宽,2米长。趟下去顶天立地,横向只够翻身,高度不够坐起。船舱里有空调,但是只有晚上打开。平时只有头上的一个风扇。幸好电倒是24小时提供,足以充手机和相机。然而这一路上都没有信号。 这也不难理解。Similan离最近的陆地超过50km,而普通手机信号只能传播20km左右。再加上按照地球弧度,50km造成的高度差会高达200m左右(6700*(1-math.cos(50⁄20000.0*math.pi))*1000,不知道我有没有算错),信号塔不在山上的话,无线信号会直接被海水阻挡住。所以整个船宿过程是没有信号的。 我们说回船。一层前半部是8个船舱,中间是三个浴室兼厕所,后部是潜水装备间。二层前半部是船长室和4个船舱,后部是公共空间,一般在这里做brief或者吃饭。三层是Sun deck,带一个顶棚。我们经常在潜水间隔跑去Sun deck那里晒太阳。冬天Similan的水还是有点冷(28左右吧),晒晒太阳有助于蒸发水分补充热能减少寒冷。 这里要说说厕所。船上的厕所都是直排的,你的排泄物会直接冲到海里。所以如果有什么可能导致问题的东西(例如,纸巾),必须丢到垃圾桶里。有一次某个客人的纸巾丟到马桶里了,结果一个厕所就无法使用了。我们还只有三个厕所,每个都是厕所/浴室/面盆的合体(地方也不是一般的小)。一旦碰到早上起床,潜水前后。厕所前排长队是意料之中。所以那次厕所出问题后,基本每次高峰时刻,厕所前面都会排上一个小时左右的队。 航程 我们是晚上9点左右上船的,经过一个简短的brief就开船了。Manager是一个俄罗斯妹子,声音比较沙哑。晚上经过两个多小时的晃悠,我们到了Similan群岛附近的一个地方停泊。 睡过一晚上后,早上6点起床做brief,下水check dive,吃早饭。休息一小时顺便换个地方,再下一支,起来吃午饭再休息一小时。下午下一支,起来休息两小时再吃个晚饭。晚饭后大家聊聊天,再下一次夜潜,第一天结束。 第一天我碰到了剧烈的头痛,推测是在第二或第三潜的时候上浮过快导致。一旦产生气泡,要消解起来就要好几小时的排氮。所以夜潜的时候都在头痛,直到夜宵结束后才逐步减轻。所以大家要小心上浮速度问题,非但不要超过18m/min,最好控制在9m/min以内,甚至短距离内也不要放松。 这次潜水我全程使用高氧,一支大概要150THB,合30CNY。全程总计300CNY,我觉得挺便宜。原则上说,这让我全程舒服很多。至于头痛,只能说大概我控制的还不够好。 潜点我就不一一列举了,反正你们也没得选。大致来说,1.1左右Similan水温28左右,不需要湿衣。天气晴,偶尔有小雨。海浪一般。大部分时候是没什么感觉的,只有一次例外。当然,开船的时候晃动还是比较猛烈的。 第二天就是晕船。早上起来,船长泊在一个面向波浪,靠近岛礁的地方休息,等待等会潜水。(海浪也是有传递方向的,一般船长会选择泊在岛背面,减少波浪)结果海浪加岸边的波浪反弹把我晃晕了。早上一支结束后,难受的生不如死,就吃了一颗晕船药,放弃一支潜水,躺在船舱里睡觉。他们上来后,船长就开始换地方,我继续睡觉。等突然就有船员很开心的敲门,Dolphin!我大概也好的差不多了,跑到Sun deck那就开始观望海豚。一群海豚追逐着我们和隔壁一艘潜水船,不断盘旋和跳出水面,大概跟了半个多小时。船长还特意偏出部分航线来追海豚。可惜跑的太快了,忘记把相机拿出来,结果没照片,只能等同船的人发给我(如果他们还记得的话)。 至于晕船,我了解到一点。不是我不会晕,只是海浪还不够大。后来我就聪明了。凡是这种有晕船可能性的情况,统统先吃再说。 第三天去北边的Koh Bon那。我们早上第一支下去的时候,有个团友就看到了Manta,但是他没有叮叮。潜到一半的时候,潜导把我们集体敲起来看Manta。我们集体连气泡都不敢吐,就看着一只巨大的Manta从我们头顶飞过。旁边还有几条大鱼(当然,和Manta本身大小比起来是大大不如)。上水之后,把同船的人羡慕坏了,我们Team直接变成了Manta Team。不过第二支的时候,我们在一个山脊侧面遇到1-2节的对向流。潜导看我们踢的很辛苦,就斜切避开了。后面几个Team就直接顶流,最后Drift。所以他们上水的位置比较靠外,我们是在Bay里面上水的。他们上水的时候又看到了Manta。 好吧,这样也是蛮公平的。 另外就是回程路上,我们最后一支是在回程一半的地方,Wreck Dive。尼马Wreck我见多了,但是这么多鱼的我还是头一次见到。能见度不高,只有10左右。但是整个行程基本都是在鱼类瀑布里面游动。就看到无数鱼围着你转圈圈。上来之后我们在那里吐槽,为啥海洋中间能见度那么差?那TM都是鱼类的粪便。 上陆地后事情就乏善可陈了。在Phuket住了一晚,早上坐L家的车到了Samui,晚上在Samui吃了点东西(下船的时候正好大雨,等我们住下,雨停了)。再一个早上坐另一艘船到了Koh tao。 Koh Tao Koh Tao算得上是我和家吉的老地盘了,这次还是到Crystal。他们的宿舍修好了,就在学校隔壁。很近不说,还有空调,1000THB一天。 这次去Crystal,是考Deep Dive。这次搞明白了一个问题。在AOW的时候,我们不是有五个专长么?其实在AOW的时候,我们并不是修完了5个专长,而是每个专长只上了一节课。所以AOW修完,我们是没有专长证的。但是在AOW时附修的EAN,是专门的两支,所以有专门的证。AOW的这五节课只给了我们两个好处: 部分的专长能力。例如深潜,AOW必修课,给我们30米深度许可。 在考对应专长的时候,能少上一次课。 所以,这次的深潜专长,经过三次大深度潜水(至少一次30米以上),和一次额外辅助减压(抱气瓶),许可我潜到40米深度。但是不得不吐槽一下,在仔细查过之后,我发现这个证并不是特别有用。因为: 很多保险并不支持40米深度。例如美亚,要求你在证件许可下,30米深度内活动。所以30米以下深度潜水是无保险的(而且可能会连累你之后的潜水全都没有保险)。 40米深度并不是谁都能去的。如果你的潜导,全组潜伴并不是都有这个证,你就下不去。 EAN下40米深度的配套很不友好。EAN32的最大深度是32-33米,要下40米深度,需要用EAN28。但是EAN的标准是32或36(左右),很多地方并没有28,例如Crystal。这导致这种大深度潜水反而必须使用空气,其实非常消耗No Dec。老潜水员知道,大部分高强度潜水的时候,No Dec才是瓶颈。 30-40米深度可见生物更少。这个深度生物体积更大,出现几率变少,基本都是博人品的重复潜水。 所以,如果考专长的话。你们可以考虑一下Deep Dive是不是值得考。以下是我觉得还不错的几个证,有机会可能会考: Wreck。绑线进去的那种,汗。要求15以上,AOW。 Sidemount。15岁以上,OW。 Dry Suit。10岁以上,OW。这个在潜冷水的时候是必需品。 Rebreather。18岁以上,OW,EAN,最低25潜。这个要求挺复杂,但是主证到不用AOW(实话说EAN+25logs其实是超过AOW的)。CCR在大深度还是比较管用的,而且下去不会有气泡惊到鱼群。 其中,Sidemount,Drysuit,Rebreather都是需要考虑是不是能在潜店租到装备的。也欢迎考过上述几个证的朋友给予意见,是不是值得。起码EAN是非常值得的一个证。 另外两个非专长的课,我有计划去上的。 Rescue。要先考出EFR来。但是我挺不喜欢中红会。 GUE Fundamentals。俗称馒头课。从我看到的数据来说,PG就可以上。 最后说一下这次考证的几个细节。

Dec 17, 2017 - 1 minute read

在云存储上叠加加密文件系统

目标很简单。云存储上很多文件都挺私人的,直接放着很吓人。虽说云存储采用各种方法来保证你的安全,但是世界上没有绝对的安全。万一密码泄漏,或者更糟糕,云存储泄漏。此时你的各种文件就在网络上裸奔了。 最简单的解决方法是什么?在底层存储上套一层加密呗。不过由于是云存储,所以基于块设备的加密方案不能用,例如LUKS。否则你同步到云上的就是一个超级巨大的块文件,然后每次修改,云存储客户端都要找到差别上传。这太蛋疼了。正解是每个文件分别加密上传。但即便如此,对于超大文件进行加密后依然会影响上传效率,请提前考虑一下这个问题。 同时又要注意,云存储用的加密文件系统和普通的加密文件系统还有点差别。很多加密文件系统的daemon会认为自己是唯一一个会访问加密内容的进程,而云存储可能随时接收来自远程的修改。所以这会造成一些问题。 备选方案 我对比了四种方案,EncFS,CryFS,GoCryptFS,eCryptFS。对比的方法是用这四种分别建立一个加密目录,然后用不同的方法做写入测试,看他的各种参数。顺便说一句,如果你要看的话,其实看这份表格就好。我只是在自己的机器上复现了一下,顺便了解一下各家特点。 测试语句: time dd if=/dev/zero of=test bs=1048576 count=1024 time dd if=/dev/zero of=test bs=1024 count=1048576 time tar xf linux-4.13.12.tar.xz 其中,在裸盘上直接解压内核源码耗时7.568s,空间使用870M。 数据对比 +---------+-------+-----+-------+-----+-------+-----+--------------+ | |time1 |size1|time2 |size2|time3 |size3|comment | +---------+-------+-----+-------+-----+-------+-----+--------------+ |EncFS |13.210s|1.1G |39.039s|1.1G |26.496s|894M | | +---------+-------+-----+-------+-----+-------+-----+--------------+ |CryFS |9.327s |1.1G |21.230s|1.1G |42.918s|2.5G |删除耗时2.804s| +---------+-------+-----+-------+-----+-------+-----+--------------+ |GoCryptFS|3.515s |1.1G |28.180s|1.1G |19.874s|918M | | +---------+-------+-----+-------+-----+-------+-----+--------------+ |eCryptFS |3.132s |1.1G |10.218s|1.1G |9.448s |1.4G | | +---------+-------+-----+-------+-----+-------+-----+--------------+ 解读 首先说怎么解读。time1是连续写入性能,time2是离散写入性能,time3是小文件写入性能,size3是大量小文件膨胀系统。size1和size2没啥用。 下面先看性能。从性能上看,最优秀的是eCryptFS。这是理所当然,因为这是唯一一个内核态而且和内核整合的系统。GoCryptFS次之。EncFS要慢上好多。至于CryFS,一开始写小文件就原型毕露了。何况这是唯一一个删除大文件时间超过1s的,达到2.8s。你看我其他系统测试里都没写。 然后是膨胀率。EncFS膨胀2.75%,CryFS膨胀近三倍,GoCryptFS膨胀5.52%,eCryptFS膨胀65%。相比起来,EncFS膨胀率最小,GoCryptFS次之,CryFS最糟糕。 安全性 下面是同一个人出的三份审计报告: