It has been a very popular self-signed certificate for HTTPS decryption,Then there are a lot of people realize crack of App by modifying Apple's internal purchase receipt。In fact Verified Purchase should be connected to the server App,Server to communicate with Apple's servers,The results are then sent to the App - but a lot of developers (including individual developers and corporate developers) do not bother to go to a special server maintenance,So communicate directly with the App and Apple's servers,This provides an opportunity for middle attacks。
Middle attack,That is when A and B are in communication,C to A pretend to be B,A to B pretend to be,Such communication process from A to <—> B become A <–> C <–> B, At this point A and B both thought the other was credible,Content of the communication can be as early as C do not know how much the change。
Normally we use the HTTPS encrypted transmission has been well against man in the middle attack,But for this particular case,To trust a certificate user initiative "unsafe" (his signature) were decrypt HTTPS,HTTPS encryption on the client side that has become untrusted。
In this situation,We need to implement their own data protection。
Security and integrity
Data protection,The main two points,"Security" and "integrity",The former protect data from prying eyes by a third party,The latter ensure that your data is not tampered in the process of communication,Of course,Generally encryption also to some extent to ensure the integrity of the data,After all, if it is tampered with,Probably will not be able to decrypt the。
But only rely on encryption,It provides an opportunity to give the man in the middle attacks。so,We want to under the premise of security in HTTPS,Integrity verification code to add to itself。
signature
The so-called "signature",And the reality of different signatures,Here is the signature by some special algorithms,The extracted feature data,Once the algorithm ensures that the data is changed,Even if it is a symbol,Then extracted feature is completely different,Such,As long as we include this feature when sending data,After receiving the re-verify it,You can ensure that data is not tampered with during transmission。
Re-signing
One problem is that after the change if the middleman in the data re-sign,We assume that the selected feature extraction algorithm is leaked,Middleman using the same algorithm after changing the data re-sign (ie feature extraction),The client will still think that the data is complete - so we have to agree on a "salt" value in the client and server,You can also be understood as a password。
It can not get you out to recover the data from the eigenvalues in (say the extracted features,Not encrypted,This process isirreversibleof),But after the two sides agreed password when signing this "password" or an additional front in the data,Once this data is changed middleman,Even if he can use the same algorithm to re-sign,Because we do not know the password set in advance,He signed out the result was different,So that the client knows that the data was doctored up。
Replay attack
Since you can not modify the data,So hackers can crawl into force of the original datagram,Send back again,So that the server or the client to verify the signatures and encryption,Data completely correct,But in fact it is the transmission of data from another version of the client - to deal with this situation,Before going on the basis of the data structure,Add a concept - "timestamp",Usually we use utc timestamp,In fact, from GMT January 1, 1970 to the present total number of seconds - of course you can also use other energy down to the second (or even millisecond) time format - the time stamp is also appended to the data in together signing,Avoid timestamp been tampered with,The client and server is communicating,Check whether a timestamp is within an allowable range,Such as 1 second,Within 30 seconds or the like,If the interval is too long,Instant signature verification by,This data can not trust the,Such,Avoiding replay attacks。
Code
There are many signature algorithm,Such as the common MD5、SHA1, etc., etc.,These algorithms can be used to directly use the signature,Here I used the RSA certificate signing,In fact, with longer and more complex passwords。
We data to be transmitted in the time stamp and generates a string with,The string is then extracting features SHA256,Then feature with RSA certificate private key signature;
Wait until the client receives the data,Generating a data string and the time stamp will be used in the same manner,Feature extraction carried out SHA256,Then use the public key signature verification。
Such public and private key pair,Benefit is,Unlike the convention as likely to reveal the password - after all, write the password in the program,Easy to find - the public key can circulate freely,Its role is merely to verify signaturesCan notSign the data,Without worrying about leaks。
Generate the key
Open any of your favorite terminal,Enter the command openssl ,Then enter the command genrsa -out private.estab 1024 To generate a private key,The higher the number, the more secure behind,But you have to weigh the cost of time signatures,usually,1024 enough。
Finally, enter the command RSA -in private.estab -pubout -out public.estab Generate public key,The public key is you want to put clients that are distributed to end-users of the key。(Use the command exit To exit openssl)
Actually,Generated key file is actually a plain text documents,The key is binary in nature,But they are saved base64 encoded into text。
Use the command cat private.estab To check your private key:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDKoeRzRVf8WoRSDYYqUzThpYCr90jfdFwTSXHJ526K8C6TEwdT UA+CFPQPRUg9jrYgFcown+J2myzO8BRLynD+XHb9ilLb49Mqk2CvDt/yK32lgHv3 QVx14Dpb6h8isjncSF965fxBxlHGbvPwnHkJ9etRIYdYV3QpYohFszH3wQIDAQAB gjIJ/dmBAkEA0QarqdWXZYbse1XIrQgBYTdVH9fNyLs1e1sBmNxlo4QMm/Le5a5L XenorEjnpjw5YpEJFDS4ijUI3dSzylC+QQJARqcD6TGbUUioobWB4L9GD7SPVFxZ AoGAFhKqkw/ztK6biWClw8iKkyX3LURjsMu5F/TBK3BFb2cYe7bv7lhjSBVGPL+c TfBU0IvvGXrhLXBb4jLu0w67Xhggwwfc86vlZ8eLcrmYVat7N6amiBmYsw20GVi LhF7zbYPIPGbHw+crP13THiYIYkHKJWsQDr8SXoNQ96TQsInTXUAmF2gzs/AwdQg UFmePbo1G2BXqMA43JxqbIQwOLZ03zdw6GHj6EVlx369IAECQQD4K2R3K8ah50Yz c3+EgcxRoO4bNuCFDA8VO/InP1ONMFuXLt1MbCj0ru1yFCyamc63NEUDAQJBALt7 PjGgsKCRuj6NnOcGDSbDWIitKZhnwfqYkAApfsiBQkYGO0LLaDIeAWG2KoCB9/6e lAQZnYPpOcCubWyDq4ECQQCrRDf0gVjPtipnPPS/sGN8m1Ds4znDDChhRlw74MI5 FydvHFumChPe1Dj2I/BWeG1gA4ymXV1tE9phskV3XZfa -----END RSA PRIVATE KEY----- |
Use the command cat public.estab To view the public key:
1 2 3 4 5 6 |
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKoeRzRVf8WoRSDYYqUzThpYCr 90jfdFwTSXHJ526K8C6TEwdTUA+CFPQPRUg9jrYgFcown+J2myzO8BRLynD+XHb9 ilLb49Mqk2CvDt/yK32lgHv3QVx14Dpb6h8isjncSF965fxBxlHGbvPwnHkJ9etR IYdYV3QpYohFszH3wQIDAQAB -----END PUBLIC KEY----- |
Python
For ease of use,We directly to private copy of the code above,Use a variable to hold the private key:
1 2 3 4 5 6 7 8 |
#私钥文件 priKey = '''-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDKoeRzRVf8WoRSDYYqUzThpYCr90jfdFwTSXHJ526K8C6TEwdT UA+CFPQPRUg9jrYgFcown+J2myzO8BRLynD+XHb9ilLb49Mqk2CvDt/yK32lgHv3 …… lAQZnYPpOcCubWyDq4ECQQCrRDf0gVjPtipnPPS/sGN8m1Ds4znDDChhRlw74MI5 FydvHFumChPe1Dj2I/BWeG1gA4ymXV1tE9phskV3XZfa -----END RSA PRIVATE KEY-----''' |
Then signed code:
1 2 3 4 5 6 |
def sign(data): key = RSA.importKey(priKey) h = SHA256.new(data.encode('utf8')) signer = PKCS1_v1_5.new(key) signature = signer.sign(h) return base64.b64encode(signature).decode('utf8') |
Here sign() Just pass in the string directly,It will convert the string you pass to UTF-8 encoded binary data SHA256 digest,Then sign Summary,Eventually converting the signature result to the output base64 encoded string。
Swift
Here we also,Save the public key to a variable,Note base64 encoded copy only part,Do not the beginning and end of -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- :
1 |
private var publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKoeRzRVf8WoRSDYYqUzThpYCr90jfdFwTSXHJ526K8C6TEwdTUA+CFPQPRUg9jrYgFcown+J2myzO8BRLynD+XHb9ilLb49Mqk2CvDt/yK32lgHv3QVx14Dpb6h8isjncSF965fxBxlHGbvPwnHkJ9etRIYdYV3QpYohFszH3wQIDAQAB" |
Key above is outputted line by line,Here we are seamlessly stitched together,Forming a long string。
Remember a reference framework import CommonCrypto
Then we write a function to generate a binary public key:
1 2 3 4 5 6 7 |
private func getPublicSecKey() -> SecKey? { let keyBase64 = Data(base64Encoded: publicKey, options: .ignoreUnknownCharacters)! as CFData let sec = SecKeyCreateWithData(keyBase64, [kSecAttrType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPublic] as NSDictionary, nil) return sec } |
Ultimately signature verification data:
1 2 3 4 5 6 7 |
func sign(content:String, sign:String) ->Bool { let sha256Data = sha256(data: content.data(using: .utf8)!) let encryptedData = Data(base64Encoded: sign) let pubSecKey = getPublicSecKey() let verified = SecKeyVerifySignature(pubSecKey!, .rsaSignatureDigestPKCS1v15SHA256, sha256Data as CFData, encryptedData! as CFData, nil) return verified } |
Simply pass the string to be signed,And then pass the base64-encoded signature,Function will automatically string SHA256 digest,Then sign into binary data recovery,Finally, the built-in algorithm system,Use your public key,Digest and signature verification,Verified by,return true 。
postscript
Using different code exchange is a very difficult thing in different platforms,Simple encryption algorithm and the way often come to different results on different platforms,The same language,In the same platform,It is the easiest,But the difference is very complex language,We must pay attention to this issue specific implementation。After tried numerous ways,I eventually realized using RSA signature cross-language interoperability platform,Hopefully this article useful to you。
References
Original article written by LogStudio:R0uter's Blog » Swift Python Json data exchange signature
Reproduced Please keep the source and description link:https://www.logcg.com/archives/3318.html