alwaystest

Results 88 issues of alwaystest

# RSA非对称加密 标签(空格分隔): 非对称加密 --- 跟着[阮一峰](http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html)的博客走了一遍思路,终于搞明白了RSA加密算法的运作。 之前一直搞不清楚密钥和私钥加密解密,**误以为只有公钥加密,私钥才可以解密,私钥加密,公钥无法解密**。 理解RSA私钥公钥能否互相解密最关键的地方在RSA算法原理(二)中的最后 > (1)加密要用公钥 (n,e) > 假设鲍勃要向爱丽丝发送加密信息m,他就要用爱丽丝的公钥 (n,e) 对m进行加密。这里需要注意,m必须是整数(字符串可以取ascii值或unicode值),且m必须小于n。 > 所谓"加密",就是算出下式的c: >   m^e ≡ c (mod n) > 爱丽丝的公钥是 (3233, 17),鲍勃的m假设是65,那么可以算出下面的等式: >   65^17 ≡...

# Python 之 pip 与 pip3 标签(空格分隔): Python --- 配置 Spf13-vim 的时候发现在打开 py 文件的时候总是报错,找不到 module six。 使用 pip install six安装后依然无法找到 module 使用 pip3 install six 安装后依然无法找到 module `which pip3` 发现...

# Future接口的使用场景 标签(空格分隔): Java --- ThreadPool实际上就是一个生产者消费者的实现,CoreThread作为消费者一直从队列中阻塞式取Task来执行。当线程池内线程数量超过CorePoolSize,从队列取Task会考虑超时,超时取不到Task,线程自然结束,当线程数量不足CorePoolSize,从队列取Task的时候会一直阻塞。 RxJava的ComputationThread实际上是利用ThreadPool的阻塞CoreThread的机制,产生和CPU核心数量一致的CoreThread数量为1的ThreadPool,往这些ThreadPool的队列中生产Task。 IOThread实际上也是控制若干ThreadPool,定期清理空闲一定时间的ThreadPool。 Future和Runnable相比,一个是提供了检查任务状态和取消任务的方法,另一个是返回值不是Void。相对来说,获取任务返回值,使用观察者模式更加高效,所以更大的优势在于可以检查任务状态和取消任务。用途并不是让一个线程Sleep一段时间后调用`get`方法,如果任务没有完成,仍然需要阻塞主线程,并不高效。

# 树莓派二代 dnsmasq ipset iptables shadowsocks 网关代理 标签(空格分隔): linux 树莓派 翻墙 --- - 大部分操作需要sudo,不想打代码可以直接su,新手还是慢慢sudo吧。 - 默认root账户是锁定的,需要先`sudo passwd root` 然后 `sudo passwd -u root`解锁root帐号然后操作。 - dnsmasq 作用是dns解析,新版支持ipset,配合ipset将指定域名解析后的ip地址动态加载到ipset的list中,然后iptables根据ip匹配来转发TCP数据包到SS的代理端口,实现代理。 - dnsmasq 2.66版本以上才支持ipset,`dnsmasq -v`...

# QueuedWork中的sFinishers 标签(空格分隔): Android --- QueuedWork.waitToFinish 方法 ``` /** * Trigger queued work to be processed immediately. The queued work is processed on a separate * thread asynchronous. While doing...

# Android CI 与 KeyStore 标签(空格分隔): Android --- 之前做Android项目的CI的时候遇到过如何管理签名文件的问题,但是当时没有好的解决思路,直到最近看到这个项目的配置 https://github.com/YoKeyword/Fragmentation 签名Key的重要性 非对称加密是目前广泛应用的一种加密和签名认证方式。具体的原理这里就不多讲了。我们使用私钥对APK进行签名,在应用升级的时候,系统要求升级前后的应用包名一致,签名一致。也就是说,要求应用签名的时候,要使用同一个私钥。私钥泄漏,就可能被别人拿来伪造应用。从安全的角度来讲,应用的签名文件应该被严格管理,因为一旦泄漏,就有可能被拿到签名Key的人伪造应用,造成损害。 一般来讲,为了安全,会把应用的源码和应用的KeyStore分开保存,划分权限管理。限制正式版APK只能由有权限的Dev签名生成,开发版的应用统一使用相同的开发版KeyStore,这样,各个Dev产出的安装包可以互相覆盖升级,不会有签名冲突的问题。 但是这样的效率也太低了,要Build正式版的安装包,只能找有权限的Dev。 使用CI来解决这个问题,KeyStore存储在服务器上,对外只暴露一个Build触发器,Build流程由CI控制,而Build流程的控制现在都会与源码放在一起做统一的版本管理。这样,源码,签名Key互相隔离,Build也不会受限。这个解决方案需要有一台可以保证安全的服务器,否则KeyStore暴露在服务器上,如果服务器被黑,KeyStore依然会被泄漏。使用公共CI服务的开发者肯定不能接受这个解法。 使用公共CI服务的情况下,就可以参照 https://github.com/YoKeyword/Fragmentation 的解法,把KeyStore加密处理,和源码放在一起。在Build流程中增加一个解密步骤,解密使用的密码就不能和源码一起存放了。这部份可以使用环境变量,在CI服务上单独把解密KeyStore的密码使用环境变量存储,这样就保证了安全性。同时,下面几个签名使用的变量也使用环境变量做了隔离。 ``` keyAlias KEYSTORE_ALIAS storePassword KEYSTORE_PASSWORD keyPassword KEY_PASSWORD ``` 其实我感觉一个密码和多个密码使用环境变量保存好像并没有多大差别,只要是同一种方式,泄漏了一个密码,其他密码也可以被相同的方法拿到。所以是不是把签名使用的变量使用环境变量隔离,KeyStore文件就可以不用加密了呢? 最后,个人感觉这个解法还是不能保证万无一失,毕竟在Build的过程中还是生成了解密后的KeyStore文件,根据机械硬盘的特性,数据被标记删除后,在被覆写前还是可以还原回来的,甚至被覆写后还是有可能还原回来的。CI过程中的容器就一定能保证不会被Hack吗? 没有穿不破的盾。毕竟非对称加密也只是目前无法快速破解而已,UUID的解法也不能保证完全无冲突。在更好的方案出来之前,已知的最好方案就是最好的方案,

# FileProvider冲突 标签(空格分隔): Android --- Android N以上为了提高文件共享的安全性,引入了FileProvider,基于ContentProvider来实现。 在集成某个SDK的时候,发现里面针对FileProvider的写法是这样的: ``` ... ... ``` 问题就在于provider的name是直接使用了Support V4包下的对应的实现类。 当另一个Lib也有同样的实现方式的时候,在MergeAndroidManifest的过程中就会提示冲突。 一种解决办法是使用`tools:replace`之类的声明去做替换,除非Dev明确知道自己在做什么,否则很容易因为缺少对应的path声明而导致出错。 使用`tools:replace`声明的原理在这里有说 https://developer.android.com/studio/build/manifest-merge 原理就是告诉MergeTool遇到冲突的时候选择哪一个。 另一种办法,看到有的文章说新建一个FileProvider,继承自`android.support.v4.content.FileProvider`就好了,里面什么都不需要做就好。然后在Manifest里面把name指定给新建的FileProvider。看完之后其实挺懵的,为什么新建一个就能解决冲突,什么冲突都能解决吗? 其实解决的原理是这样的,两个provider的声明中,name都是`android.support.v4.content.FileProvider`,就相当于在一个AndroidManifest中声明了两次同一个Activity。因为FileProvider实际上是ContentProvider,也是四大组件之一嘛,同一个组件声明两次,两次声明中要是一模一样倒还好说,直接Merge就好了,不会出错,但是一旦两个声明中某个属性不同,那MergeTool就不知道怎么选了,那就报错,我处理不了,你行你上。 换个名字,实际上是声明了两个不同的组件,不存在Merge的问题。 但是对于ContendProvider,声明了两个`authorities`相同的provider,能行吗?不行。 可能有人遇到过安装两个App的时候,因为Provider的authorities相同而导致第二个应用不能安装的。原因就是一旦允许安装,那就没有办法根据uri找出来到底应该从哪个Provider中获取数据了。 fileProvider生成的uri的格式是这样的 ``` content://{authorities}/xxxxx ``` 如果两个FileProvider的authorities声明成一样的,就没有办法区分应该找哪个FileProvider去获取文件了。 两个App的时候是这样。一个App中声明了两个一样的authorities的provider呢?...

# Java 泛型 标签(空格分隔): Java --- 逆变和协变记不住,始终分不清,记录一下个人理解,方便回忆。 Java的泛型是不变的。 按照继承的理解来看 ```List list = new ArrayList();``` 没有问题,父类的特性,子类也有。 推测以下代码应该是合法的 ```List list = new ArrayList ();``` 但是这样会导致一个问题 ``` List tmp = new ArrayList ();...

# XYPlot 与 AAPT2 标签(空格分隔): Android --- XYPlot旧版不支持AAPT2的原因是AAPT2把AAPT没有转换的资源ID也转换了。导致XYPlot中获取资源对应值的方法失效。 ### AAPT ### AAPT2

# Go交叉编译 标签(空格分隔): Go --- 更新了一版Frp,因为升级不兼容旧版本的缘故,对之前的Frps的Dockerfile进行了升级。主要变动是把之前Bundle的Frps修改为Build时编译。 因为Frp是用Go写的,顺便了解了一下Go的包管理。去中心化很有意思。 作者提供了Dockerfile,改起来很快。 因为原版的Dockerfile直接使用Golang镜像作为Base,最终生成的镜像比较大。Go的跨平台做的很方便,按照之前Frps的用法,只需要下载好对应平台的可执行文件就好了,不像Java还要要求JRE。那么使用Golang镜像作为Base,提供的Go编译环境实际上已经没有用了。 之前看到过分阶段构建的概念,发现Docker也实现了。就用分阶段构建的方式修改了一下Dockerfile。 坑在Alpine默认没有带`make`和`bash`。又想偷懒,直接用`golang:1.10`作为base编译了,然后发现在Alpine作为Base的Production镜像上无法启动。 原因是 > 采用了不同libc实现的debian系和alpine系存在不兼容的情况(golang:1.10基于debian) 解决方案有两种 1. 使用Alpine编译,在编译前先`apk --add make bash`,由于是分阶段构建,这部份的Clean操作就忽略掉了先。 2. 还是使用golang:1.10编译,需要使用静态构建。就是把之前用到动态链接库的地方直接静态编译进可执行文件中去。`CGO_ENABLED=0`标志使用静态构建。 方法2的优点是可以使用更新的Base镜像,比如scratch。 中途还补充了一下[Dockerfile: ENTRYPOINT和CMD的区别](https://zhuanlan.zhihu.com/p/30555962)的概念。 # Href - multi-stage-image-build-in-docker https://tonybai.com/2017/11/11/multi-stage-image-build-in-docker/...