Android应用安全之脆弱的加密
程序员希望通过加密来提升程序的安全性性,但却缺乏专业的密码学背景知识,使得应用对数据的保护非常薄弱。本文将介绍可能出现在Android应用中的一些脆弱的加密方式,以及对应的攻击方法。
造成脆弱加密的主要原因
Android应用中造成弱加密的原因多种多样,OWASP Mobile Top 10 给出了几个原因:
使用了脆弱的加密算法 使用了强健的加密算法,但加密的实现存在漏洞。
使用弱密码算法实现加解密
我们先来看看如果如果一个应用使用弱加密算法会遭受怎样的攻击。
例如使用MD5作为Hash算法,MD5已经认为不安全了。如果应用使用了MD5这样的脆弱算法,而攻击者又能读取到Hash,攻击者就有相当大的机会能破解加密。假设应用使用MD5生成了这样一段Hash:
8f6b983ad06881847a180f1398910891
攻击者可以使用john之类的工具或在线的彩虹表破解服务:
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjAAAACFCAIAAADKC1XXAAAOhElEQVR4nO2dv4vryAHH579QE3C5pdO5VOlSpQO34NLXufRfcIhHCpcuTUgh9u0FH6/xdSLXCFKcAuHwNS/iHhwqBSEgSDMpZMn6MSOP3+5K8urz4cPDK49mJHs9350ZPUt8SVJERMTeFY/uJ0RExH4lkBARcRASSIiIOAgJpN58AoAx0XufM3wJpN58enqSADAOCCQTCaTeJJAAxgOBZCKB1JsEEsB4IJBMJJB6k0ACGA8EkokEkpFCXHmVrhZoegmkxHfnD5YQ1sNiF6bZtjTcORMhxOqYSJmEu+VsIoSYzNfeKZVSxp4j3KD5Wx8d1vNzwWMk2+svqryUvMKl1WJ36yE/JKk6Tk3r6o3nU/Acx4uLH1tKytRfW+eygSuqWG545WwMGlKeZuWtUVWlfm2N3xp1ydaGqu/Ci+qEN4JAMpFAUiuuodzlpibyQIr28+m580yOKyvr5pLjSjheJKWUMvYcexskUkqZ+JvpdBtqAin1N5azj1IppUxPu6Ubppr6k+MqL5n4m+lsdzL6TBWtRvv5bHOMpZQy8hbW4hBrjlN9dsqN2YtxXM2EuPSP+pJSpqFbKVsQ7efVkgqMGlKeZvmtUVWlfG3N3xp1Sd0xNw/vhXXCW0EgmUggqS2nSzNpsi1fEVpl80AK3Et/UPT4pcAJt1OrkT3KQArcck8ZbqdrP9XUX8bfiKwvu0q+e3xYXAYgqb8Waz9VH6e6dfUhJb5rT+zNZlnqH1sOPto7q9Wy2ZfGnnOlgzVtSHma1cNQVVUmf23N3xp1SVVD6sN7WZ3wZhBIJhJIRhYJpHuqdcuf/yjEH/70l1qxPJDiw2JW/ZM29pw809wg9pysp6kQe47YeMe1bZXmx8p9kZThdmrvI1X95YrSyFtM8jxKgm02BSSsh2JqJw13iwdLiImzO+xKHVzRUNbdqY9T3br6kJIwOCW1yrUHHx8WCy+uHkh+2tnYTH9Gpg0pTvMf5bdGU5XqtTV/a9QlVQ2p3oWX1glvBoFkIoGktRZCzQfKH1Vb2gNJyuS4fsg6OXuTTXmV/gwPXWu6PQbbLBTyTjX2HCFmbpBIKePjejp1gzSfmZFSShl5y4mVDz2a9WcE7mw2EbONnwXCYWktsj+k02jvZKswyXFlObtTIrNpIaEIpOxY1cepa117SI3+UVky9df2NlT0pam/FvN90bTqjMwbUp2mepSp6NOrr635W6Mr2WxIfXgvqxPeDALJRAJJazmQamnUkknmK0nnQEpDd5Z3FulpN8+600v3ErjCmiz3pyQvMMvXkC7jkWhvZ31tMZqZr4/HnS3cQFN/icTfTGdu/XqBKDuA+LAotRNup9pAUh+nsvX2QypXrikZbueboDkmzNd31J1rVA+Sqw29KJCy47m8tuZvjaKksiHl4b2wTngzCCQTCSS1tYyprQy9ZiA1plNqFy1EnlOagpLR3p5uw1qvqF5R2gjHizX1Vwi303OexYG3227XS9t+yAZD6nZUk0Xq41S23n5I+j73XDLaO/nUXa0vTf11fcTUOKMbGtLMid0QSKXXtlLc+K05lzQ45vPhvbBOeDMIJBMJpDZNrk0oSj7eeKGdYSCl/rp8rcB5ASD2HLEpthYjpBKx51jN8NAFkr2PZLidWXP34AenOEmVI6Rob2tX+9XH+QaBVFphqyznyPP0Zqkq1RmZN2RyUYOiKuVrW8H8rclLKhtSHt4L64Q3g0AykUAy0iRp9GVa15DS0J2vj8UludlMV7nXS0PXPi+EXCZhYs8R1mJfrO1k82P+xprvTqmUMgn3i2zmRll/tJ9b6/MoIwlce3GIZXxYiPNkTxLuF5YQaz+VyXFlldaqRHHZ93R9jGW2cG8tD4nmOJWtq085pzaT1lKyMWtVSU+pOaMbGlKd5tVAUr22N7w1ypLqE9a8Cy+qE94KAslEAkmrbiKu5Vo7TSZdu6ghOq7z/8m4bVzUIKWUyflagUuB7Cq7wzJbF3D982p/vlRQqkld/+Xys8l8tc8WkPKdxWS+9sLDxsr+tE9P+2XtKrvLEdWuX2gcp6Z19caMWv/YUlIxxqhGheaMzBtSneb1EZLitb3lrVGX1DSkeBdeVie8EQSSiQSSVsNAqk3rmc/y8dVBAOOBQDKRQNJaX6ioXtfw2Jo9JrFEIAGMBwLJRAKpNwkkgPFAIJlIIPUmgQQwHggkEwmk3iSQAMYDgWQigdSbT09Pnuc9AUDn9PLR673PGb4EUm/+/Mvn5+fn7j8VAPD8/PzzL5977wSwJoHUj99898PHjx/7nkUAGC/Pz8/ffPdD710BliWQevOJNSSA/nhiDm14Eki9SSAB9AiBNEAJJCNv+tZUw11eFkilL7AJ3NL/2eVLYACMaAbSX3/7X/bUf3/7V7FRSnnTB79R/svv5wb/8/e++7HhSyC1WbsN0qPme4OUN6foLJBizyndnxoAjFAGUhFFzfK1jc1ixRbV5/3L7wSSgQTSFa9mjC60Oguk0LU2wbXiAGPCtu3yn4m2bTfLtAdSoSwFjGykTsuDqgSSkQSS2pYvsmt+m6ryQanMtW/7zsi+wPu4nk/OX94clR5nRYr7fpa+eDs+LBo33AEYN77vlz+tvu83y1wNpFr5xzxspD6imrvkEkhGEkhXbBkh6YLqBYEknN0pye58bVmLfZSeH7uhlDI5rqzseRl5i/z+p6Fr2YvlPLvbweUeBADjphgkKYdH8vVGSAW6Mo/uJwLJUAKpzatrSC1lbp6yiz1HLA5x8Ti/TXc+OVe9/Vx+75/kuBLFbeuSw6p+CzuAcVIMkpTDI/m1a0jFs+YPHt1PBJKhBJJWXaIo5+ua5b8qkPIbv6keV28Mp7pNnJSR5zTvUA4wTmzb1g2PpNkISVYXhIp9mwVaHjy6nwgkQwkkI9svZ1A+9fqBVBkhRXtbFUh7mwUlgAzf93XDI2m2hlR7LBsXLJQrrO0lCaTbJZDUml/UUN5FU5v5GlJbIMnkuLJmbpBIKePjepqtIZ12s+kmv4N5tHf4f0gARtw6ZVem2EUyQnpVCaTrtqwJmSXWKwWSlOlpv6xfZSeTYLt4sIQQk9lyFyav94EFeM98xQhJ97hcrbIYgWQogdRmLVraJ+KuztHV5KuDAHrk6wIp27f8WFnskUD6KgkktS3ZU768+9ZpvbIEEkCPlAPpbz/92kGL0U+/9t6zDVwCqTcJJIAe4ctVByiB1I/ffPfD8/Nz3x9JgPHC/ZAGKIHUmz//8vnjx49d3B0TAKp8//33/zz9u/dOAGsSSH06wj/QPsNd0fsvzBs5wo/eXUggYaf23cHCDXz48KH3XxgclQQSdmrW0/W9fADX+fDhA4GEHUsgYacSSPcCgYTdSyBhp95hIAXyWyG/dTvZa0AQSNi9BBJ26t0GksgDpvxjy0addxNRBBJ2L4GEnXpvgRRUI8fVbDQZD93ZmIlAwu4lkLBT7yqQdHlzNYeU6XVnEEjYvQQSdupdBZJUzMX96DWm6UrBE1azKrxpCDUsCCTsXgIJO/UuAyks/ftjfNleCZhaAjXL3FkmEUjYvQQSdur9B5LXCB55bVUpkN8KuXMJJMR2CSTs1LsMJMWUXcuFc5or7naNG84PGwIJu5dAwk69y0Aqj5Da1oQCTUTdJQQSdi+BhJ16/4HUsj50xytGTQgk7F4CCTv1LgPJ9L+76hLrLsOJQMLuJZCwU+8ykK6PkGRjI4GEeLMEEnbqCALp7r80KINAwu4lkLBT7yqQmgn0dYMeRkiIRhJI2Kl3FUijhkDC7iWQsFMJpHuBQMLuJZCwU4t7Y8Nd0PsvDI5KAgk7lTS6L3r/hcFRSSAhIuIgJJAQEXEQEkiIiDgIvySp+JKkiIiIvUsgISLiICSQEBFxEBJIiIg4CAkkREQchAQSIiIOQgIJEREHIYGEiIiDkEBCRMRBSCAhIuIgJJAQEXEQEkiIiDgICSRERByEBBIiIg5CAgkREQchgYSIiIOQQEJExEFIICEi4iDkFuaIiNi/X5JUSAAAgF4hkAAAYBAQSAAAMAgIJAAAGAQEEgAADAICCQAABgGBBAAAg4BAAgCAQUAgAQDAICCQAABgEBBIAAAwCAgkAAAYBAQSAAAMgtsCSQhFyfJGZQHds+2FAQBgVFwJJHGNolhL+XJttcrNm3ud0wUAgKFiOkLKIqH8r66MbqNJaOnSi0ACAHj3GAWSMlSUZZoxU8uw9phhhAQAMFqMpuzKPzafah/i1IKqVnmzuauPm0cFAADvANMRUvuQ5WogNYspqzIcIRFIAADvj9um7HRbWpJGmVUmEDkAAKOioxFSM6WaVbUMjxgSAQC8e15/hFTbqAySZrHms+27k08AAO+MVxsh6YY+texRbqxVpXvQrAcAAN4Nr/PVQe3hIVVX6+mm7Jp1Np8CAID3x+t8U0PLvrqnlI91ZQAA4N3Dl6sCAMAgIJAAAGAQEEgAADAICCQAABgEBBIAAAwCAgkAAAYBgQQAAIPg7QIpcIUbvEG9AADwLiGQAABgEFwNpMAVq523nj9YQkzm2yAKdqv5RAjrYXmIilJJuFvOJkKIyXx9jLLdChwvVpaRUsok2C4eLCGsh8U2SPIWN8eTt55Pil0BAODdYxJIs5UXJlJKedrZYrbyTomUMvE309Uxi5BoP5+5fiKllEm4nc/3kWyMkJRlwu1stjlmceW7s9k2zHacLHcBSQQAMCpMAumSK+UfYs85j1/C7XTtp7K2vRpIyjLhdup4Ub4x9dfTbchcHwDAOHmNQCpPz13m6Kq5oiwTuJU5ufMeBBIAwBh5pRHSppkgjRFSs0x1hJQcV4yQAABGy2sEUr4UlEopZRr7W/cQSxl7jr07FfUoy4Tb2XStWEMikAAARserBJKUSbhfzSdCCDGZLd1jlEop02A7nwghrOUh1pXRXGVHIAEAjA6+qQEAAAYBgQQAAIOAQAIAgEFAIAEAwCDIAun/IlDIiUyr7jkAAAAASUVORK5CYII=" alt="" />
如上图,hash被成功破解。
除此之外,有的开发者也会使用编码来保护敏感信息。编码不是加密,可以很容易就解码还原出明文。例如我们在反编译了一个应用之后发现了如下的一段Base64编码字符:
SGVsbG8gV29ybGQu
找一个提供在线base64解码的网站就能还原出明文:
aaarticlea/png;base64,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" alt="" />
强密码算法的不安全实现
另一种情况是使用了较强的加密,但使用方法不够安全,例如使用了AES这样的对称加密算法,尽管该算法足够强壮,但当其实现不当的时候也一样容易受到攻击。
1.AES加密使用javax.crypto.Cipher初始化时如果使用了ECB模式,将会使相同的明文在不同时候会产生相同的密文,容易遭到字典攻击,安全性不够高。
public void initAES()
{
try {
this.cipher = javax.crypto.Cipher.getInstance("AES/ECB/PKCS5Padding");
Exception v0_3 = new javax.crypto.spec.SecretKeySpec(this.keyBytes, "AES");
this.cipher.init(1, v0_3);
this.decipher = javax.crypto.Cipher.getInstance("AES/ECB/PKCS5Padding");
this.decipher.init(2, v0_3);
com.easemob.util.EMLog.d("encrypt", "initital for AES");
} catch (Exception v0_5) {
v0_5.printStackTrace();
}
return;
}
ECB加密的缺点在于同样的明文组会得到同样的密文组,相对于ECB模式来说,CBC模式则较安全,攻击者不易发起主动攻击,同时,CBC(密码分组链接)适合于传输长度较长的报文,依据的是SSL、IPSEC的标准。
攻击示例:http://www.freebuf.com/news/special/56506.html
2.使用SecureRandom时使用方法setSeed设置种子将会造成生成的随机数不随机。
通常我们都能意识到应该使用SecureRandom类来产生密钥,用来对本地的敏感信息进行加密,实际上这种做法是欠妥的。
在这种方法中,不将密钥作为一个字符串直接存储在APK文件中,而是通过另外一个字符串来生成密钥–有点类似于通过用户口令生成加密密钥。这种必要的混淆手段可以使攻击者不容易破解加密信息,但是对于一个有经验的攻击者而言,这种策略很容易被绕过,因此我们不推荐这种方法。
事实上,Android现有的安全机制中已经为这种数据提供了很好的保护,敏感数据应该标记上MODE_PRIVATE,然后存储在内部存储中,请注意,千万不能存储在SD卡中,因为访问控制没法强制在外部存储上起作用。
结合设备加密措施,这种方法可以杜绝绝大部分攻击。
除此之外,像我们上面描述的那样使用SecureRandom类还存在另外一个问题。从Android4.2开始,SecureRandom的默认实现是OpenSSL,开发者无法覆盖SecureRandom的内部状态信息,例如下面这段代码:
SecureRandom secureRandom = new SecureRandom();
byte[] b = new byte[]{(byte)1};
secureRandom.setSeed(b);
//在Android4.2上,下面这行代码总是返回同一个数字。
System.out.println(secureRandom.nextInt());
(【译者注】这段代码可以看到通过程序覆盖了random对象中的种子,造成每次生成的随机数序列都是一样的)
在以前的Android版本中,SecureRandom是基于Bouncy Castle实现的,它允许像上面代码这样的操作,每个SecureRandom类的实例产生伪随机数时使用的种子是从/dev/urandom获取的。(【译者注】/dev/urandom是类Unix系统中根据当前计算机混乱状态,如内存使用,CPU占用率等信息计算出来的随机数,读者可以在Linux下试试cat /dev/urandom,它会不停地输出乱码,一般用“熵”这个专业术语形容计算机的混乱状态)。那些试图使用产生随机数的开发者通常是通过替换现有的种子来产生随机数序列的(参考相关实现文档),如果种子固定,那么产生的随机数列就是可预测的,这一点是不安全的。现在通过OpenSSL实现,使得这种错误的行为不再可能出现。
不幸的是,那些依赖老的SecureRandom类的应用程序会发现每次程序启动时产生的随机数都不一样了(事实上,这就应该是随机数发生器的期望行为)。想要通过这种方法对加密密钥混淆已经不可行了。
(【译者注】原作者的意思是有些应用对敏感信息做加密,加密的话需要密钥,但是密钥如果直接存起来觉得很不放心,于是通过产生随机数的方式来对密钥混淆一下,那么每次程序启动时都要用相同的密钥去解密数据,于是通过一个固定的信息,比如一个密码,或者记住某个随机数字,通常很多人用当前时间,然后通过这个固定的信息作为种子产生随机数,用这个随机数做密钥,相当于对这个固定信息做了一次混淆操作。实际上这种方法还是不安全,安全性就变成了如何保证这个种子的安全性,治标不治本。下面的部分作者的意思是应该直接将密钥打上MODE_PRIVATE的标记存起来,通过系统的访问控制机制保证密钥的安全性。)
正确的方法
一种更加合理的解决方案很简单,就是当应用程序第一次启动时产生一个随机的AES算法的密钥:
public static SecretKey generateKey() throws NoSuchAlgorithmException {
// 生成一个256位密钥
final int outputKeyLength = 256; SecureRandom secureRandom = new SecureRandom();
// Do *not* seed secureRandom! Automatically seeded from system entropy.
//不要给secureRandom一个固定的种子!通过系统熵值产生随机的种子
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(outputKeyLength, secureRandom);
SecretKey key = keyGenerator.generateKey();
return key;
注意这种方法的安全性依赖于如何保证密钥的安全性,这可以依赖于Android系统的内部存储的安全性。将密钥直接存放在文件中,标记为MODE_PRIVATE存在内部存储器。(【译者注】我们很多人的Android手机都被Root过的,好多应用也会取得Root权限,Root权限用户是可以做任何事情的。。。这怎么办呢?)
更加安全的方法
如果你的应用还需要额外的加密操作,那么一个推荐的方法是每次进入你的应用时需要输入一个口令或者PIN码。然后将这个口令传给 PBKDF2(PBKDF2,基于口令的密钥导出函数版本2,是RSA安全公司提出的密钥导出算法,通常用来根据口令取得密钥,通过一种叫做密钥拉伸的专业技术),Android在SecretKeyFactory类中提供了一个叫做PBKDF2WithHmacSHA1的实现:
public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
//PBKDF2算法执行轮数,这个数字越大,计算时间越长,你应该让这个数字
//足够大,以至于这个算法执行时间超过100毫秒以保证安全性
final int iterations = 1000; // 产生一个256位的密钥
final int outputKeyLength = 256; SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey;
}
加密盐应该是一个通过SecureRandom产生的随机字符串,和加密密文一起存放在内部存储器中。使用加密盐很重要,它可以有效防止字典攻击。
(【译者注】看PBKDF2WithHmacSHA1这个名字也可以知道该算法是基于SHA1算法的,经常攻击这种单向函数方法就是字典攻击,预先计算好大量的明文对应的密文,就像是明文对应密文的字典,然后再进行逐一对比,如果明文字符串在加密前和一个随机字符串做个连接操作,那么那些预先计算的字典就没用了。)
检查你的应用是不是正确的使用SecureRandom
如本文以及Jelly Bean的新安全特性所述,Android4.2的SecureRandom默认实现发生了变化,用它产生固定密钥已经行不通了。
如果你也用了这种错误方法的话,我们建议现在就更新你的应用,防止当用户升级到Android4.2或以上版本后发生一些莫名其妙的错误。
参考链接:
http://bobao.360.cn/learning/detail/174.html
http://www.cnblogs.com/maverick-fu/p/4341808.html
http://www.importnew.com/3456.html
Android应用安全之脆弱的加密的更多相关文章
- android环境下两种md5加密方式
在平时开发过程中,MD5加密是一个比较常用的算法,最常见的使用场景就是在帐号注册时,用户输入的密码经md5加密后,传输至服务器保存起来.虽然md5加密经常用,但是md5的加密原理我还真说不上来,对md ...
- Android数据存储之SQLCipher数据库加密
前言: 最近研究了Android Sqlite数据库(文章地址:Android数据存储之Sqlite的介绍及使用)以及ContentProvider程序间数据共享(Android探索之ContentP ...
- android加固系列—6.仿爱加密等第三方加固平台之动态加载dex防止apk被反编译
[版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5402599.html ] 此方案的目的是隐藏源码防止直接性的反编译查看源码,原理是加密编译好的 ...
- Android Apk的反编译和加密
这几天在上海出差,忙里偷闲学习了一下Apk的反编译工具的基本使用.下面就简单介绍一下如何将我们从网上下载的Apk文件进行反编译得到我们想要获得的资源文件和源码. Android的应用程序APK文件说到 ...
- Android: JAVA和C# 3DES加密解密
最近 一个项目.net 要调用JAVA的WEB SERVICE,数据采用3DES加密,涉及到两种语言3DES一致性的问题,下面分享一下,这里的KEY采用Base64编码,便用分发,因为Java的Byt ...
- Android客户端与服务器端通过DES加密认证
转载地址:http://blog.csdn.net/spring21st/article/details/6730283 由于Android应用没有像web开发中的session机制,所以采用PHPS ...
- Android面试收集录 网络与加密
1.创建Socket对象需要至少指定哪些信息? IP(或域名)和端口号 Socket socket=new Socket("www.baidu.com",80); 2.如何使用So ...
- Android中常用的几种加密
1.数字摘要 是指通过算法将长数据变为短数据,通常用来标识数据的唯一性,是否被修改,常用的加密算法有md5和sha1两种,如Android的App签名也是用的这两种算法. md5具有不可逆性,也可用来 ...
- Android接口安全 - RSA+AES混合加密方案
转载请注明出处: http://blog.csdn.net/aa464971/article/details/51034462 本文以Androidclient加密提交数据到Java服务端后进行解密为 ...
随机推荐
- 关于Mysql数据库的知识总结
2017年6月8日,天气阴.心情晴. 连续做梦两个晚上了,昨晚竟然梦见一个很长时间不联系的初中同学了,早上上班的路上聊了聊.女孩现在出差在贵州,风景秀美的地方.我说“你现在生活很滋润”.女孩说“那是你 ...
- php 去除所有空格 包括中文空格圆角空格
有的中文的半角,圆角空格或者段落符显示为空白的.可以用正则来处理 preg_replace("/(\s|\ \;| |\xc2\xa0)/","" ...
- php 实现简单加入购物车(1)
这个购物车相对来说比较简单,用于短暂存储,并没有存储到数据库,购物车对于爱网购的人来说简直是熟悉的不能再熟悉了,在写购物车之前,我们首先要构思一下,我们需要先从数据库中调出一张表格,这里我 ...
- Python Python-MySQLdb中的DictCursor使用方法简介
Python-MySQLdb中的DictCursor使用方法简介 by:授客 QQ:1033553122 DictCursor的这个功能是继承于CursorDictRowsMixIn,这个Mi ...
- 表id关联数据获取至页面,制作下拉框多选进行数据多项获取(字段处理)
这周完成了一张表单,重点碰到以下问题: 1.freemaker获取年份的type值取year,类型直接为Long,传至后台和获取数据不需要转换: 2.freemaker获取日期type值为date, ...
- java持有对象【2】ArrayList容器续解
此为JDK API1.6.0对ArrayList的解释. ArrayList 使用java泛型创建类很复杂,但是应用预定义的泛型很简单.例如,要想定义用来保存Apple对象的ArrayList,可以声 ...
- ListView 添加 HeaderView常见错误
1.addHeaderView异常: 最近在做通讯录开发时使用ListView,发现一个奇怪的问题:当添加一个ImageView 作为HeaderView时,发现ImageView长宽始终是1:1的大 ...
- JAVA将list转化为xml文件
pojo类: public class TreeNode { private int id; private String nodeId; private String parentId; priva ...
- LeetCode题解之Binary Number with Alternating Bits
1.题目描述 2.问题分析 将数值转换为二进制,然后将前面的 0 去掉,再遍历一边二进制字符串,对每个字符和其后部的字符进行比较. 3.代码 bool hasAlternatingBits(int n ...
- Debian 常用命令
换源 用中科大的比较快 deb http://mirrors.ustc.edu.cn/debian jessie main contrib non-free deb-src http://mirror ...