安卓常見演算法
『壹』 安卓常見的一些加密((對稱加密DES,AES),非對稱加密(RSA),MD5)
DES是一種對稱加密演算法,所謂對稱加密演算法即:加密和解密使用相同密鑰的演算法。DES加密演算法出自IBM的研究,
後來被美國政府正式採用,之後開始廣泛流傳,但是近些年使用越來越少,因為DES使用56位密鑰,以現代計算能力,
24小時內即可被破解
調用過程
最近做微信小程序獲取用戶綁定的手機號信息解密,試了很多方法。最終雖然沒有完全解決,但是也達到我的極限了。有時會報錯:javax.crypto.BadPaddingException: pad block corrupted。
出現錯誤的詳細描述
每次剛進入小程序登陸獲取手機號時,會出現第一次解密失敗,再試一次就成功的問題。如果連續登出,登入,就不會再出現揭秘失敗的問題。但是如果停止操作過一會,登出後登入,又會出現第一次揭秘失敗,再試一次就成功的問題。
網上說的,官方文檔上注意點我都排除了。獲取的加密密文是在前端調取wx.login()方法後,調用我後端的微信授權介面,獲取用戶的sessionkey,openId.然後才是前端調用的獲取sessionkey加密的用戶手機號介面,所以我可以保證每次sessionkey是最新的。不會過期。
並且我通過日誌發現在sessionkey不變的情況下,第一次失敗,第二次解密成功。
加密演算法,RSA是繞不開的話題,因為RSA演算法是目前最流行的公開密鑰演算法,既能用於加密,也能用戶數字簽名。不僅在加密貨幣領域使用,在傳統互聯網領域的應用也很廣泛。從被提出到現在20多年,經歷了各種考驗,被普遍認為是目前最優秀的公鑰方案之一
非對稱加密演算法的特點就是加密秘鑰和解密秘鑰不同,秘鑰分為公鑰和私鑰,用私鑰加密的明文,只能用公鑰解密;用公鑰加密的明文,只能用私鑰解密。
一、 什麼是「素數」?
素數是這樣的整數,它除了能表示為它自己和1的乘積以外,不能表示為任何其它兩個整數的乘積
二、什麼是「互質數」(或「互素數」)?
小學數學教材對互質數是這樣定義的:「公約數只有1的兩個數,叫做互質數
(1)兩個質數一定是互質數。例如,2與7、13與19。
(2)一個質數如果不能整除另一個合數,這兩個數為互質數。例如,3與10、5與 26。
(3)1不是質數也不是合數,它和任何一個自然數在一起都是互質數。如1和9908。
(4)相鄰的兩個自然數是互質數。如 15與 16。
(5)相鄰的兩個奇數是互質數。如 49與 51。
(6)大數是質數的兩個數是互質數。如97與88。
(7)小數是質數,大數不是小數的倍數的兩個數是互質數。如 7和 16。
(8)兩個數都是合數(二數差又較大),小數所有的質因數,都不是大數的約數,這兩個數是互質數。如357與715,357=3×7×17,而3、7和17都不是715的約數,這兩個數為互質數。等等。
三、什麼是模指數運算?
指數運算誰都懂,不必說了,先說說模運算。模運算是整數運算,有一個整數m,以n為模做模運算,即m mod n。怎樣做呢?讓m去被n整除,只取所得的余數作為結果,就叫做模運算。例如,10 mod 3=1;26 mod 6=2;28 mod 2 =0等等。
模指數運算就是先做指數運算,取其結果再做模運算。如(5^3) mod 7 = (125 mod 7) = 6。
其中,符號^表示數學上的指數運算;mod表示模運算,即相除取余數。具體演算法步驟如下:
(1)選擇一對不同的、足夠大的素數p,q。
(2)計算n=p q。
(3)計算f(n)=(p-1) (q-1),同時對p, q嚴加保密,不讓任何人知道。
(4)找一個與f(n)互質的數e作為公鑰指數,且1<e<f(n)。
(5)計算私鑰指數d,使得d滿足(d*e) mod f(n) = 1
(6)公鑰KU=(e,n),私鑰KR=(d,n)。
(7)加密時,先將明文變換成0至n-1的一個整數M。若明文較長,可先分割成適當的組,然後再進行交換。設密文為C,則加密過程為:C=M^e mod n。
(8)解密過程為:M=C^d mod n。
在RSA密碼應用中,公鑰KU是被公開的,即e和n的數值可以被第三方竊聽者得到。破解RSA密碼的問題就是從已知的e和n的數值(n等於pq),想法求出d的數值,這樣就可以得到私鑰來破解密文。從上文中的公式:(d e) mod ((p-1) (q-1)) = 1,我們可以看出,密碼破解的實質問題是:從p q的數值,去求出(p-1)和(q-1)。換句話說,只要求出p和q的值,我們就能求出d的值而得到私鑰。
當p和q是一個大素數的時候,從它們的積p q去分解因子p和q,這是一個公認的數學難題。比如當p*q大到1024位時,迄今為止還沒有人能夠利用任何計算工具去完成分解因子的任務。因此,RSA從提出到現在已近二十年,經歷了各種攻擊的考驗,逐漸為人們接受,普遍認為是目前最優秀的公鑰方案之一。
缺點1:雖然RSA的安全性依賴於大數的因子分解,但並沒有從理論上證明破譯RSA的難度與大數分解難度等價。即RSA的重大缺陷是無法從理論上把握它的保密性能如何。
在android 開發的很多時候。為了保證用戶的賬戶的安全性,再保存用戶的密碼時,通常會採用MD5加密演算法,這種演算法是不可逆的,具有一定的安全性
MD5不是加密演算法, 因為如果目的是加密,必須滿足的一個條件是加密過後可以解密。但是MD5是無法從結果還原出原始數據的。
MD5隻是一種哈希演算法
『貳』 Android面試 HashMap演算法
基於hashing的原理,jdk8後採用數組+鏈表+紅黑樹的數據結構。我們通過put和get存儲和獲取對象。當我們給put()方法傳遞鍵和值時,先對鍵做一個hashCode()的計算來得到它在bucket數組中的位置來存儲Entry對象。當獲取對象時,通過get獲取到bucket的位置,再通過鍵對象的equals()方法找到正確的鍵值對,然後在返回值對象。
當數組table的size達到闕值時即++size > load factor * capacity 時,也是在putVal函數中。
擴容需要重新分配一個新數組,新數組是老數組的2倍長,然後遍歷整個老結構,把所有的元素挨個重新hash分配到新結構中去。
對key的hashCode進行hashing,與運算計算下標獲取bucket位置,如果在桶的首位上就可以找到就直接返回,否則在樹中找或者鏈表中遍歷找,如果有hash沖突,則利用equals方法去遍歷鏈表查找節點。
對key的hashCode做hash操作,與高16位做異或運算。
還有平方取中法,除留余數法,偽隨機數法。
因為數組位置的確定用的是與運算,僅僅最後四位有效,設計者將key的哈希值與高16為做異或運算使得在做&運算確定數組的插入位置時,此時的低位實際是高位與低位的結合,增加了隨機性,減少了哈希碰撞的次數。
會產生哈希碰撞,若key值相同則替換舊值,不然鏈接到鏈表後面,鏈表長度超過闕值8就轉為紅黑樹存儲。
HashCode相同,通過equals比較內容獲取值對象。
超過闕值會進行擴容操作,概括的講就是擴容後的數組大小是原數組的2倍,將原來的元素重新hashing放入到新的散列表中去。
相同點:都是存儲key-value鍵值對的
不同點:
loadFactor表示HashMap的擁擠程度,影響hash操作到同一個數組位置的概率。默認loadFactor等於0.75,當HashMap裡面容納的元素已經達到HashMap數組長度的75%時,表示HashMap太擠了,需要擴容,在HashMap的構造器中可以定製loadFactor。
JDK 1.8 以前 HashMap 的實現是 數組+鏈表,即使哈希函數取得再好,也很難達到元素百分百均勻分布。當 HashMap 中有大量的元素都存放到同一個桶中時,這個桶下有一條長長的鏈表,這個時候 HashMap 就相當於一個單鏈表,假如單鏈表有 n 個元素,遍歷的時間復雜度就是 O(n),完全失去了它的優勢。針對這種情況,JDK 1.8 中引入了 紅黑樹(查找時間復雜度為 O(logn))來優化這個問題。但是鏈表大於8的概率是非常非常低的。
選擇Integer,String這種不可變的類型,像對String的一切操作都是新建一個String對象,對新的對象進行拼接分割等,這些類已經很規范的覆寫了hashCode()以及equals()方法。作為不可變類天生是線程安全的。如果要使用自定義類做為Key,就需要重寫hashCode()以及equals()方法。紅黑樹在做比較的時候使用的是System.identityHashCode()方法,是不需要做特殊處理的。
更多內容戳這里(整理好的各種文集)
『叄』 android 全景圖像拼接演算法哪種方案最好
首先介紹一下流程:
1.選圖,兩張圖的重疊區域不能太小,我個人認為最少不少於15%,這樣才能保證有足夠的角點匹配。
2.角點檢測。這一步OpenCV提供了很多種方法,譬如Harris角點檢測,而監測出的角點用CvSeq存儲,這是一個雙向鏈表。
3.角點提純。在提純的時候,需要使用RANSAC提純。OpenCV自帶了一個函數,FindHomography,不但可以提純,還可以計算出3x3的轉換矩陣。這個轉換矩陣十分重要。
4.角點匹配。經過提純後的角點,則需要匹配。
5.圖像變換。這一步我曾經嘗試過很多辦法,最後選擇了FindHomography輸出的變換矩陣,這是一個透視變換矩陣。經過這個透視變換後的圖像,可以直接拿來做拼接。
6.圖象拼接。完成上面步驟之後,其實這一步很容易。
7.球面變換。這一步需要對坐標系進行轉換,從平面坐標到球面坐標。
『肆』 安卓常用的加密演算法中,加密後生成42位的密文的是哪種加密方法
直接通用的加密演算法好像都沒有生成42位的,你這段看起來像MD5加密後的與另一個字元串連接在一起,你嘗試對應其他欄位看看
嘗試:
1. 32+10
2. 5+32+5
3. 10+32
我看比較 像以上三種情況
『伍』 Android開發 HashMap如何排序
HashMap排序是數據結構與演算法中常見的一種排序演算法。本文即以Android平台為例來實現該演算法。
具體代碼如下: public static void main(String[] args) { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("lisi", 5); map.put("lisi1", 1); map.put("lisi2", 3); map.put("lisi3", 9); List<Map.Entry<String, Integer>> infoIds = new ArrayList<Map.Entry<String, Integer>>( map.entrySet()); System.out.println("--------------排序前--------------"); for (int i = 0; i < infoIds.size(); i++) { String id = infoIds.get(i).toString(); System.out.println(id); } // 排序 Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return ( o1.getValue()-o2.getValue()); } }); System.out.println("--------------排序後--------------"); for (int i = 0; i < infoIds.size(); i++) { Entry<String,Integer> ent=infoIds.get(i); System.out.println(ent.getKey()+"="+ent.getValue()); }}
『陸』 android聯系人排序用了什麼演算法
今天用了整整一下午去搗鼓這塊,為什麼模擬器上可以按拼音排序,中英文混排,及按字母搜索聯系人,但到了開發板(平台是根據android2.2改過的)上就怎麼不行了呢,雖然現在還沒有解決,但也是知道了問題所在,離解決之路也就不遠了
好吧,現在就解釋下android2.2是怎麼按拼音排序的。
首先我們來看下android.2自帶通訊錄的資料庫文件contacts2.db的raw_contacts表。用sqlitedbviewer工具打開後可以看到有這么一個欄位:sort_key(sort_key_alt與之相似,只不過是英文環境下有個按given name還是first name排序的問題)。
正常狀況下,我們新建一個聯系人的話,如果是英文,則sort_key與display_name欄位顯示相同,如果輸入姓名是中文,如「你好」,sort_key則會顯示「ni 你 hao 好」,這樣開發者既可以根據此欄位按拼音排序,中英文混排,以及按拼音搜索聯系人拉。
現在就說下,android是如何將中文名的聯系人轉化為拼音存到sort_key裡面的:
view plain to clipboardprint?
if (displayNameStyle == FullNameStyle.CHINESE ||
displayNameStyle == FullNameStyle.CJK) {
sortKeyPrimary = sortKeyAlternative =
ContactLocaleUtils.getIntanc).getSortKe(displayNamePrimary, displayNameStyle);}
if (displayNameStyle == FullNameStyle.CHINESE ||
displayNameStyle == FullNameStyle.CJK) { sortKeyPrimary =
sortKeyAlternative =
ContactLocaleUtils.getIntanc).getSortKe(displayNamePrimary,
displayNameStyle);}
這段代碼是運行在contactsprovi2.Java的updateRawContactDisplayName()方法裡面,這段代碼我們用到了ContactLocaleUtils.java這個類,所以我們進入它以後最顯眼的就是ChineseContactUtils這個ContactLocaleUtils的子類,它重寫了ContactLocaleUtils的getSortKey()方法,如下:
view plain to clipboardprint?
public String getSortKey(String displayName) {
ArrayList tokens = HanziToPinyin.getInstance().get(displayName);
if (tokens != null && tokens.size() > 0) {
StringBuilder sb = new StringBuilder();
for (Token token : tokens) {
// Put Chinese character's pinyin, then proceed with the
// character itself.
if (Token.PINYIN == token.type) {
if (sb.length() > 0) {
sb.append(' ');
}
sb.append(token.target);
sb.append(' ');
sb.append(token.source);
} else {
if (sb.length() > 0) {
sb.append(' ');
}
sb.append(token.source);
}
}
return sb.toString();
}
return super.getSortKey(displayName);
}
public
String getSortKey(String displayName) {
ArrayList tokens =
HanziToPinyin.getInstance().get(displayName); if (tokens !=
null && tokens.size() > 0) { StringBuilder
sb = new StringBuilder(); for (Token token : tokens) {
// Put Chinese character's pinyin, then proceed
with the // character itself.
if (Token.PINYIN == token.type) { if
(sb.length() > 0) { sb.append(' ');
} sb.append(token.target);
sb.append(' ');
sb.append(token.source); } else {
if (sb.length() > 0) {
sb.append(' '); }
sb.append(token.source); } }
return sb.toString(); } return
super.getSortKey(displayName); }
首先我們看 ArrayList tokens = HanziToPinyin.getInstance().get(displayName);,因為其他的無非就是插入格式的問題,我們暫時不用看。
android如何將漢字轉為拼音的?這就用到了HanziToPinyin這個類,好吧,我們先看下HanziToPinyin的getInstance()方法:
view plain to clipboardprint?
public static HanziToPinyin getInstance() {
synchronized(HanziToPinyin.class) {
if (sInstance != null) {
return sInstance;
}
// Check if zh_CN collation data is available
final Locale locale[] = Collator.getAvailableLocales();
for (int i = 0; i < locale.length; i++) {
if (locale[i].equals(Locale.CHINA)) {
sInstance = new HanziToPinyin(true);
return sInstance;
}
}
Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled");
sInstance = new HanziToPinyin(false);
return sInstance;
}
}
public static HanziToPinyin getInstance() {
synchronized(HanziToPinyin.class) { if (sInstance != null) {
return sInstance; } // Check
if zh_CN collation data is available final Locale locale[]
= Collator.getAvailableLocales(); for (int i = 0; i <
locale.length; i++) { if
(locale[i].equals(Locale.CHINA)) { sInstance = new
HanziToPinyin(true); return sInstance;
} } Log.w(TAG, "There is no Chinese
collator, HanziToPinyin is disabled"); sInstance = new
HanziToPinyin(false); return sInstance; } }
現在說下我的開發板為什麼不能轉拼音;就是因為final Locale locale[] = Collator.getAvailableLocales()的Locale沒有一項equals(Locale.CHINA),所以到時候解決了這項,聯系人的按拼音排序也就解決了,如果大家不想用系統自帶的,自己可以下載個pinyin4j.jar包自己實現吧。
好吧,繼續:
看方法名也只到,這個方法返回一個HanziToPinyin實例,我仔細研究了HanziToPinyin的構造方法,無論純如的布爾值是false還是true都不影響,返回的都一樣,只不過這個方法的Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled");可以提示是否支持漢字轉拼音,如果不能,android就會將displayname原封不動的插入sort_key裡面,如果能,就是剛才我說的 如「你好」,sort_key則會顯示「ni 你 hao 好」,這種形式,具體的如何轉拼音就是get()方法拉,直接插代碼:
view plain to clipboardprint?
public ArrayList get(final String input) {
ArrayList tokens = new ArrayList();
if (!mHasChinaCollator || TextUtils.isEmpty(input)) {
// return empty tokens.
return tokens;
}
final int inputLength = input.length();
final StringBuilder sb = new StringBuilder();
int tokenType = Token.LATIN;
// Go through the input, create a new token when
// a. Token type changed
// b. Get the Pinyin of current charater.
// c. current character is space.
for (int i = 0; i < inputLength; i++) {
final char character = input.charAt(i);
if (character == ' ') {
if (sb.length() > 0) {
addToken(sb, tokens, tokenType);
}
} else if (character < 256) {
if (tokenType != Token.LATIN && sb.length() > 0) {
addToken(sb, tokens, tokenType);
}
tokenType = Token.LATIN;
sb.append(character);
} else if (character < FIRST_UNIHAN) {
if (tokenType != Token.UNKNOWN && sb.length() > 0) {
addToken(sb, tokens, tokenType);
}
tokenType = Token.UNKNOWN;
sb.append(character);
} else {
Token t = getToken(character);
if (t.type == Token.PINYIN) {
if (sb.length() > 0) {
addToken(sb, tokens, tokenType);
}
tokens.add(t);
tokenType = Token.PINYIN;
} else {
if (tokenType != t.type && sb.length() > 0) {
addToken(sb, tokens, tokenType);
}
tokenType = t.type;
sb.append(character);
}
}
}
if (sb.length() > 0) {
addToken(sb, tokens, tokenType);
}
return tokens;
}
『柒』 Android基礎『V1V2V3簽名』
基礎概念
簽名:在 APK 中寫入一個「指紋」。指紋寫入以後,APK 中有任何修改,都會導致這個指紋無效,Android 系統在安裝 APK 進行簽名校驗時就會不通過,從而保證了安全性。
摘要演算法: 使用一段簡單的看上去隨機的不可逆向的固定長度的字元串來表示一個文件的唯一性。 常見的摘要演算法如MD5(128個比特位)、SHA-1演算法(160/192/256個比特位)。
公鑰密碼體制:也稱非對稱演算法,特點是 公鑰是公開的 ,私鑰是保密的。常見的如:RSA。
展開討論一下RSA:
Android中的簽名方案
V1 :基於jarsigner(JDK自帶工具,使用keystore文件進行簽名) 或 apksigner(Android專門提供的,使用pk8、x509.pem進行簽名)。keystore和pk8/x509.pem可以相互轉換。
簽名原理:首先keystore文件包含一個MD5和一個SHA1摘要。 這也是很多開放平台需要我們上傳的摘要數據 。
簽名APK後會在META-INF文件夾下生產CERT.RSA、CERT.SF、MANIFEST.MF三個文件。
在apk中,/META-INF文件夾中保存著apk的簽名信息,一般至少包含三個文件,[CERT].RSA,[CERT].SF和MANIFEIST.MF文件。這三個文件就是對apk的簽名信息。
MANIFEST.MF中包含對apk中除了/META-INF文件夾外所有文件的簽名值,簽名方法是先SHA1()(或其他hash方法)在base64()。存儲形式是:Name加[SHA1]-Digest。
[CERT].SF是對MANIFEST.MF文件整體簽名以及其中各個條目的簽名。一般地,如果是使用工具簽名,還多包括一項。就是對MANIFEST.MF頭部信息的簽名,關於這一點前面源碼分析中已經提到。
[CERT].RSA包含用私鑰對[CERT].SF的簽名以及包含公鑰信息的數字證書。
是否存在簽名偽造可能:
修改(含增刪改)了apk中的文件,則:校驗時計算出的文件的摘要值與MANIFEST.MF文件中的條目不匹配,失敗。
修改apk中的文件+MANIFEST.MF,則:MANIFEST.MF修改過的條目的摘要與[CERT].SF對應的條目不匹配,失敗。
修改apk中的文件+MANIFEST.MF+[CERT].SF,則:計算出的[CERT].SF簽名與[CERT].RSA中記錄的簽名值不匹配,失敗。
修改apk中的文件+MANIFEST.MF+[CERT].SF+[CERT].RSA,則:由於證書不可偽造,[CERT].RSA無法偽造。
V2 :7.0新增的
簽名後的包會被分為四部分
1. Contents of ZIP entries(from offset 0 until the start of APK Signing Block)
2. APK Signing Block
3. ZIP Central Directory
4. ZIP End of Central Directory
新應用簽名方案的簽名信息會被保存在區塊2(APK Signing Block) 中, 而區塊1( Contents of ZIP entries )、區塊3( ZIP Central Directory )、區塊4( ZIP End of Central Directory )是受保護的, 在簽名後任何對區塊1、3、4的修改都逃不過新的應用簽名方案的檢查 。
V3 :9.0新增的
格式大體和 v2 類似,在 v2 插入的簽名塊(Apk Signature Block v2)中,又添加了一個新快(Attr塊) 。
在這個新塊中,會記錄我們之前的簽名信息以及新的簽名信息,以 密鑰轉輪的方案,來做簽名的替換和升級。這意味著,只要舊簽名證書在手,我們就可以通過它在新的 APK 文件中,更改簽名 。
v3 簽名新增的新塊(attr)存儲了所有的簽名信息,由更小的 Level 塊,以 鏈表 的形式存儲。
其中每個節點都包含用於為之前版本的應用簽名的簽名證書,最舊的簽名證書對應根節點,系統會讓每個節點中的證書為列表中下一個證書簽名,從而為每個新密鑰提供證據來證明它應該像舊密鑰一樣可信。
這個過程有點類似 CA 證書的證明過程,已安裝的 App 的舊簽名,確保覆蓋安裝的 APK 的新簽名正確,將信任傳遞下去。
注意: 簽名方式只支持升級不支持降級,如安裝了V2的包,不能覆蓋替換為V1的包。
參考
Android App簽名(證書)校驗過程源碼分析
新一代開源Android渠道包生成工具Walle
Android 簽名機制 v1、v2、v3
『捌』 android加密演算法有哪些
android中用的到加密:
Https編程 :應該是使用帶安全的網路協議處理。除非你本地需要加密
2.數據簽名:混淆代碼和防二次打包的APK加密技術
3.對稱加密:可以先將數據通過某種加密方式加密發送到伺服器端,然後伺服器端再解密 ,項目中除了登陸,支付等介面採用rsa非對稱加密,之外的採用aes對稱加密
4.非對稱加密====支付寶
數字摘要是指通過演算法將長數據變為短數據,通常用來標識數據的唯一性,是否被修改,常用的加密演算法有md5和sha1兩種,如Android的App簽名也是用的這兩種演算法。
由於以上兩種生成數字摘要的演算法都是不可逆的,對於可逆的加密演算法中,按照密鑰的數量和加密規則一半分為對稱加密和非對稱加密兩類:
對稱加密:
密鑰可以自己指定,只有一把密鑰,如果密鑰泄漏數據就會暴漏;
常用的對稱加密演算法有DES和AES兩種;
特點是加密速度快,但是缺點是安全性低,因為只要密鑰暴漏,數據就可以被解密。
非對稱加密的特點:
常見的非對稱加密演算法是RSA;
他有兩把密鑰,且是由程序生成的,不能自己指定;
特點是加密速度比較慢,但是安全性比較高;
加密和解密的規則是:公鑰加密只能私鑰解密,私鑰加密只能公鑰解密;
『玖』 Android APK hash值演算法
無符號右移16位然後做異或運算
hash值計算公式:
對於key的hashCode做hash操作,無符號右移16位然後做異或運算。還有平方取中法,偽隨機數法和取余數法。這三種效率都比較低。而無符號右移16位異或運算效率是最高的。集合中的初始化容量(必須是二的n次冪)//默認的初始容量是16--1<<4相當於1*2的4次方---1*16staticfinalintDEFAULT_INITIAL_CAPACITY=1<<4;1212staticfinalinthash(Objectkey){inth;/*
如果key等於null:可以看到當key等於null的時候也是有哈希值的,返回的是0.
如果key不等於null:首先計算出key的hashCode賦值給h,然後與h無符號右移16位後的二進制進行按位異或得到最後的hash值。