双因素OTP硬件令牌
就术语而言,双因素身份验证(多因素身份验证)和两步验证(身份验证)之间有明显的区别,如。2 FA/MFA使用多个因素进行身份验证,即“您知道的东西”(密码)、“您拥有的东西”(令牌、卡片)和“您的身份”(生物特征)。两步验证基本上是使用两个密码-一个是永久的,另一个是短暂的和一次性的。
至少这是理论。实际上,更复杂的是说哪些身份验证方法属于哪个类别(“ThingyouX”)。让我以几个例子来说明:
- OTP硬件令牌被认为是“你拥有的东西”。但是它使用与服务器共享的对称秘密,以便两者能够同时生成相同的代码(如果使用TOTP)或相同的序列。这意味着秘密实际上是“你知道的东西”,因即使硬件令牌受到保护。当然,除非服务器将共享秘密存储在HSM中,并且对HSM本身进行OTP比较(某些支持)。在存储在硬件上之前,仍然存在密钥泄漏的理论可能性。那么,硬件标记是“你拥有的东西”还是“你知道的东西”呢?出于实际目的,它可以被认为是“你拥有的东西”。
- 智能手机OTP通常不像硬件令牌那样被认为是安全的,但由于现代手机的安全存储,它应该是安全的。这个秘密在注册过程中只共享一次(通常是在屏幕上扫描),所以它应该是“您拥有的东西”,就像硬件令牌一样。
- 短消息不被认为是安全的,通常作为2步验证的例子,因为它只是另一个密码。虽然这是真的,但这是因为有一个特定的SS7漏洞(允许拦截移动通信)。如果移动通信标准是安全的,SIM卡将与号码绑定,只有SIM卡持有者才能接收到消息,使之成为“您拥有的东西”。但是有了已知的漏洞,它就是“你知道的东西”,而实际上是电话号码。
- 指纹扫描器代表“你是什么”。在大多数设备中,它们的构建方式是扫描仪在传输指纹数据时对手机进行身份验证(在加密上绑定到CPU),所以您不能只截取传输的字节,然后重放它们。这就是理论;它没有公开记录它是如何实现的。但如果不是这样的话,那么“你是什么”就是“你拥有的东西”--一个代表你指纹扫描的字节序列,这可能会泄漏。这就是为什么生物特征识别只能在本地、手机上进行,而不需要任何服务器交互--你不能确保服务器正在接收传感器--扫描数据或捕获并重放数据。也就是说,生物识别因素与身份验证智能手机应用程序的正确实现有关--比如说,如果您的银行应用程序需要指纹扫描才能运行,恶意行为者不应该能够通过窃取共享凭据(用户ID、机密)并对您的服务执行API调用来绕过这一点。所以对于服务器来说,没有“你是什么东西”。它始终是“客户端应用程序已经验证的东西,如果实现得当的话”。
- 数字签名(通过智能卡或Yubikey,甚至是带有私钥安全硬件存储的智能手机)就是“你拥有的东西”--它的工作方式是签署一次挑战,由服务器发送,并验证签名是由与先前注册的公钥相关的私钥创建的。知道公钥对你毫无帮助,因为公钥密码学是如何工作的。没有共享的秘密,也没有可以截获数据流的中介。私钥仍然是“你知道的东西”,但是如果把它放在硬件中,它就变成了“你拥有的东西”,也就是真正的第二个因素。当然,除非有人发现用于生成私钥的素数的随机生成已被破坏,否则您可以从公钥中派生私钥(如
理论与实践之间没有明显的界限。“你是什么”和“你拥有的东西”最终会变成“你知道的东西”(或“某个商店的东西”)。一些理论攻击可以在一夜之间变得非常实际。
https://www.meipian.cn/3r0hloqo
我建议我们把所有的东西都称为“双因素认证”,因为更重要的是要对技术的有用性有更多的了解,而不是在术语上吹毛求疵。遗憾的是,FA并不能解决钓鱼问题,但它解决了泄露的证书,这已经足够好了,每个人都应该有某种形式的证书。即使是短信也总比没有好(显然,对于高知名度的系统来说,数字签名是最好的选择)。
我想分享一些非常简短和非常明显的东西--对于大量的数据来说,压缩工作得更好。也就是说,如果你要压缩100句话,你最好把它们批量压缩,而不是一次一句。让我举例说明:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public static void main(String[] args) throws Exception { List<String> sentences = new ArrayList<>(); for (int i = 0; i < 100; i ++) { StringBuilder sentence = new StringBuilder(); for (int j = 0; j < 100; j ++) { sentence.append(RandomStringUtils.randomAlphabetic(10)).append(" "); } sentences.add(sentence.toString()); } byte[] compressed = compress(StringUtils.join(sentences, ". ")); System.out.println(compressed.length); System.out.println(sentences.stream().collect(Collectors.summingInt(sentence -> compress(sentence).length)));} |
压缩方法是使用公用压缩来轻松地为多个压缩算法生成结果:
https://www.imdb.com/list/ls507341879/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public static byte[] compress(String str) { if (str == null || str.length() == 0) { return new byte[0]; } ByteArrayOutputStream out = new ByteArrayOutputStream(); try (CompressorOutputStream gzip = new CompressorStreamFactory() .createCompressorOutputStream(CompressorStreamFactory.GZIP, out)) { gzip.write(str.getBytes("UTF-8")); gzip.close(); return out.toByteArray(); } catch (Exception ex) { throw new RuntimeException(ex); }} |
结果如下,以字节为单位(注意存在一些随机性,因此算法不能直接比较):
| 算法 | 散装 | 个人 |
|---|---|---|
| GZIP | 6590 | 10596 |
| LZ4框架 | 9214 | 10900 |
| BZIP 2 | 6663 | 12451 |
为什么这是一个明显的结果?由于大多数压缩算法的工作方式--它们在原始数据中查找模式并创建这些模式的映射(非常粗略的描述)。
https://www.douban.com/note/810700443/
那有什么用?在基础存储支持每条记录压缩(例如数据库或搜索引擎)的大数据场景中,如果将多条记录捆绑到一个存储/索引记录中,则可以节省大量磁盘空间。
不过,这并不是一个普遍有用的建议。您应该检查特定的数据存储实现。例如,MSSQLServer支持行压缩和页压缩。Cassandra在SSTable级别上进行压缩,所以您如何构造行可能并不重要。当然,如果将数据存储在文件中,将其存储在一个文件中并对其进行压缩,则比单独压缩多个文件更有效。
磁盘空间很便宜,所以玩数据绑定和压缩可能被认为是过早的优化。但在大型数据集上运行的系统中,这是一个可以节省大量存储成本的决定。

浙公网安备 33010602011771号