• java c++通用DES/AES对称加密算法(包含源代码)

    java c++通用DES加密算法(包含源代码),本来觉得DES、AES这种流行加密算法,使用起来应该很简单。但研究后发现有两个变数:1分块的方式。加密是逐块进行的。2.padding的方式。当数据的位数不及块的大小时,需要填充。<h2>一说明</h2> 本来觉得DES、AES这种流行加密算法,使用起来应该很简单。但研究后发现有两个变数: <ul> <li>分块的方式。加密是逐块进行的。分块方法有:CBC、ECB、CFB……</li> <li>padding的方式。当数据的位数不及块的大小时,需要填充。填充方式有:NoPadding、PKCS5Padding……</li> </ul> 如果加解密端采用不同的分块方式或padding方式,即使都是采用DES/AES算法,同样无法解密成功。上次需要C端和Java端进行密文传输,就跪在这一点上(那时候没时间研究)。<br /> 参考文章:<a href="http://my.oschina.net/u/267094/blog/174035" rel="external nofollow" target="_blank">Java AES算法和openssl配对</a> ,主要通过其了解openssl里比较高级的EVP系列API(其默认padding和java一样都是PKCS5Padding),节约了搜索时间。<br /> 贴代码了,以下代码测试通过了。Java和C++均可以正确解密对方的密文。<br /> 约定:分块和padding采用Java默认的 ECB + PKCS5Padding。 <h2>二 DES加解密</h2> <h3>Java端DES加解密</h3> <pre> <code class="language-java">import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; public class DESUtil { /** 默认算法格式 **/ static String default_transformation = "DES/ECB/PKCS5Padding"; /** * 根据key获取加密器 * * @param keyData * key 8byte * @return 加密器 * @throws Exception * 异常 */ private static Cipher getEncryptCipher(byte[] keyData) throws Exception { if (keyData.length != 8) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "DES"); // 指定分块ECB模式,填充PKCS5Padding模式 Cipher encryptCipher = Cipher.getInstance(default_transformation); // 初始化加密的容器 encryptCipher.init(Cipher.ENCRYPT_MODE, key); return encryptCipher; } /** * 根据key获取解码器 * * @return 解码器 * @throws Exception * 异常 */ private static Cipher getDecryptCipher(byte[] keyData) throws Exception { if (keyData.length != 8) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "DES"); Cipher decryptCipher = Cipher.getInstance(default_transformation); // 初始化解密的容器 decryptCipher.init(Cipher.DECRYPT_MODE, key); return decryptCipher; } /** * DES加密 * * @param data * 待加密数据 * @param keyData * key值 * @return 加密后的数据 * @throws Exception * 异常 */ public static byte[] encrypt(byte[] data, byte[] keyData) throws Exception { return getEncryptCipher(keyData).doFinal(data); } /** * DES解密 * * @param data * 加密后的数据 * * @param keyData * key值 * @return 解密数据 * @throws Exception * 异常 */ public static byte[] decrypt(byte[] data, byte[] keyData) throws Exception { return getDecryptCipher(keyData).doFinal(data); } /** * 测试 * * @param args */ public static void main(String[] args) { try { byte[] data = "测试123456".getBytes(); byte[] keyData = "12345678".getBytes(); System.out.println("原文:" + new String(data)); byte[] enData = encrypt(data, keyData); System.out.println("加密后:" + new String(enData)); byte[] deData = decrypt(enData, keyData); System.out.println("解密后:" + new String(deData)); } catch (Exception e) { e.printStackTrace(); } } } </code></pre> <strong><span style="color:#27ae60">说明:Java必须指定填充模式和padding模式。DES/ECB/PKCS5Padding,好与C++同步</span></strong><br /> 测试执行结果: <pre> <code class="language-html">原文:测试123456 加密后:�a���O���?I�]�Y 解密后:测试123456</code></pre> <h3>C++端DES加解密</h3> c++DES加密代码 <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string desEncrypt(const std::string& source, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_EncryptInit_ex(&ctx, EVP_des_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[source.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_EncryptUpdate(&ctx, result, &len1, (const unsigned char*)source.data(), source.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_EncryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("hellodes", 8);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("src.txt", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string source(buf, bytes); // 二进制数据     // 加密     std::string enc = desEncrypt(source, key);     std::cout << "desEncrypt:" << source.length() << "->" << enc.length() << std::endl;     // 输出到文件     fp =  fopen("enc.bin", "wb");     fwrite(enc.data(), 1, enc.length(), fp);     fclose(fp); }</code></pre> c++DES解密 <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string desDecrypt(const std::string& ciphertext, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_DecryptInit_ex(&ctx, EVP_des_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[ciphertext.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_DecryptUpdate(&ctx, result, &len1, (const unsigned char*)ciphertext.data(), ciphertext.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_DecryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("hellodes", 8);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("enc.bin", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string data(buf, bytes); // 二进制数据     // 加密     std::string dec = desDecrypt(data, key);     std::cout << "desDecrypt:" << data.length() << "->" << dec.length() << std::endl;     // 输出到文件     fp =  fopen("dec.txt", "wb");     fwrite(dec.data(), 1, dec.length(), fp);     fclose(fp); }</code></pre> <br /> 说明:DES、AES加密算法都是针对数据块,Java加解密函数参数使用byte数组。C++用std::string,那是因为这是C++中使用byte数组的最简单方式(std::string可以存储二进制数据,很多人没想到吧),缺点是拷贝内存的次数可能会略多些。如果想要优化拷贝效率,可以使用自己封装的Buffer类来代替std::string。 <h2>三 AES加解密</h2> <h3>Java端AES加解密</h3> <pre> <code class="language-java">import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; /** * DES加解密算法工具类 * * @author xqlee * */ public class AESUtil { /** 默认算法格式 **/ static String default_transformation = "AES/ECB/PKCS5Padding"; /** * 根据key获取加密器 * * @param keyData * key 8byte * @return 加密器 * @throws Exception * 异常 */ private static Cipher getEncryptCipher(byte[] keyData) throws Exception { if (keyData.length != 16) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "AES"); // 指定分块ECB模式,填充PKCS5Padding模式 Cipher encryptCipher = Cipher.getInstance(default_transformation); // 初始化加密的容器 encryptCipher.init(Cipher.ENCRYPT_MODE, key); return encryptCipher; } /** * 根据key获取解码器 * * @return 解码器 * @throws Exception * 异常 */ private static Cipher getDecryptCipher(byte[] keyData) throws Exception { if (keyData.length != 16) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "AES"); Cipher decryptCipher = Cipher.getInstance(default_transformation); // 初始化解密的容器 decryptCipher.init(Cipher.DECRYPT_MODE, key); return decryptCipher; } /** * AES加密 * * @param data * 待加密数据 * @param keyData * key值 * @return 加密后的数据 * @throws Exception * 异常 */ public static byte[] encrypt(byte[] data, byte[] keyData) throws Exception { return getEncryptCipher(keyData).doFinal(data); } /** * AES解密 * * @param data * 加密后的数据 * * @param keyData * key值 * @return 解密数据 * @throws Exception * 异常 */ public static byte[] decrypt(byte[] data, byte[] keyData) throws Exception { return getDecryptCipher(keyData).doFinal(data); } /** * 测试 * * @param args */ public static void main(String[] args) { try { byte[] data = "测试123456".getBytes(); byte[] keyData = "1234567887654321".getBytes(); System.out.println("原文:" + new String(data)); byte[] enData = encrypt(data, keyData); System.out.println("加密后:" + new String(enData)); byte[] deData = decrypt(enData, keyData); System.out.println("解密后:" + new String(deData)); } catch (Exception e) { e.printStackTrace(); } } } </code></pre> <h3>C++端AES加解密</h3> 加密: <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string aesEncrypt(const std::string& source, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[source.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_EncryptUpdate(&ctx, result, &len1, (const unsigned char*)source.data(), source.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_EncryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("helloaeshelloaes", 16);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("src.txt", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string source(buf, bytes); // 二进制数据     // 加密     std::string enc = aesEncrypt(source, key);     std::cout << "aesEncrypt:" << source.length() << "->" << enc.length() << std::endl;     // 输出到文件     fp =  fopen("enc.bin", "wb");     fwrite(enc.data(), 1, enc.length(), fp);     fclose(fp); }</code></pre> 解密: <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string aesDecrypt(const std::string& ciphertext, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_DecryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[ciphertext.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_DecryptUpdate(&ctx, result, &len1, (const unsigned char*)ciphertext.data(), ciphertext.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_DecryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("helloaeshelloaes", 16);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("enc.bin", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string data(buf, bytes); // 二进制数据     // 加密     std::string dec = aesDecrypt(data, key);     std::cout << "aesDecrypt:" << data.length() << "->" << dec.length() << std::endl;     // 输出到文件     fp =  fopen("dec.txt", "wb");     fwrite(dec.data(), 1, dec.length(), fp);     fclose(fp); }</code></pre>
  • Android_开发_申请网络访问权限

    Android_开发_申请网络访问权限步骤一:配置允许HTTP明文访问xml文件在res的xml目录添加以下网络配置文件允许HTTP协议的明文访问(Android 9.0后默认不允许HTTP明文协议访问 )代码如下:<?xml versioAndroid_开发_申请网络访问权限步骤一:配置允许HTTP明文访问xml文件在res的xml目录添加以下网络配置文件允许HTTP协议的明文访问(Android 9.0后默认不允许HTTP明文协议访问 )代码如下:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <!--允许访问http协议--> <base-config cleartextTrafficPermitted="true" /> </network-security-config> 步骤二:引入步骤一中的配置文件在AndroidManifest.xml配置文件中的application节点中引入网络配置文件<application android:networkSecurityConfig="@xml/network_config" //其他略 ... > //其它略 ... </application>步骤三:申请用户网络权限在AndroidManifest.xml配置文件中的跟节点manifest下引入网络访问和获取网络状态权限<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.leftso.box"> <!-- 网络视频需要打开网络访问权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> //其他配置 略... </manifest>由此Android app申请网络访问权限配置代码完毕。
  • 小左工具箱(Android)APP 发布|下载

    小左工具箱(Android)APP 发布|下载小左工具箱简介 小左工具箱是开发者用来实现一些有趣的工具和编程学习,目前已经实现了抖音无水印解析工具、CPU性能评分查询工具、小米运动刷步数工具。关于机型适配 软件目前没有做太多机型适配,开发中小左工具箱(Android)APP 发布|下载小左工具箱简介 小左工具箱是开发者用来实现一些有趣的工具和编程学习,目前已经实现了抖音无水印解析工具、CPU性能评分查询工具、小米运动刷步数工具。关于机型适配 软件目前没有做太多机型适配,开发中主要以Pixel 3 XL/Pixel 5机型开发,如果你的设备出现了一些显示性兼容问题,欢迎留言反馈。关于权限 由于抖音解析等工具需要访问网络,所以申请了网络权限。为了存储抖音解析的视频到公共Download目录,申请了存储的读写权限,需要同意才能正常使用哟。软件界面  首页  工具页面关于更新由于软件处于起步阶段问题可能会修复很快,为了你使用的工具更完善目前软件是进行强制更新的,尽情谅解。关于下载​​​​​​​leftso-box-1.0.0.apk(访问密码: 9987)
  • retrofit2使用详解之入门

    前言       在本教程中,我们将了解Retrofit 的基础知识以和创建一个android HTTP client请求REST API前言       在本教程中,我们将了解Retrofit 的基础知识以和创建一个android HTTP client请求REST API。 1. Retrofit是什么?Retrofit是一个类型安全的REST客户端,适用于android和Java开发应用。Retrofit可将HTTP 网络接口转换为Java接口。Retrofit android 版使用非常简单。它本质上允许我们将API调用视为简单的Java方法调用,因此我们只定义要访问的URL和请求/响应参数的类型作为Java类。整个网络调用+ JSON / XML解析完全由Retrofit处理(例如Gson用于JSON解析)。它允许向远程Web服务器发出同步或异步HTTP请求。2. Retrofit 安装 我们的项目中要使用Retrofit 2,我们将在构建文件中包含以下依赖项。在本教程中,我们将以JSON格式发送和接收数据,因此我们也添加了converter-gson依赖项。maven 方式:$title(pom.xml) <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>retrofit</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>converter-gson</artifactId> <version>2.6.1</version> </dependency> gradle 方式:$title(build.gradle) dependencies { compile 'com.squareup.retrofit2:retrofit:2.6.1' compile 'com.squareup.retrofit2:converter-gson:2.6.1' } 在Android应用程序中,我们必须启用Internet权限,因为Retrofit会对Internet上某个服务器上运行的API执行HTTP请求。$title(AndroidManifest.xml) <uses-permission android:name="android.permission.INTERNET"></uses-permission>3. REST API建模3.1. REST API 接口 使用Retrofit的下一步是对REST API建模,我们将会在应用程序中使用它。下面举例说明有一个这样的API可以免费使用HTTP GET https://reqres.in/api/users/2 Response: { "data": { "id": 2, "email": "janet.weaver@reqres.in", "first_name": "Janet", "last_name": "Weaver", "avatar": "https://s3.amazonaws.com/uifaces /faces/twitter/josephstein/128.jpg" } }3.2. 业务数据模型假设我们只需要消费id,姓名和电子邮件字段,而不想使用头像字段。字段数量不匹配,Gson转换器并不会报错,他会解析我们模型中指定的字段。(国内的fastjson也一样效果)$title(UserApiResponse.java) public class UserApiResponse { private User data; //Setters and getters public String toString() { return "UserApiResponse [data=" + data + "]"; } }$title(User.java) public class User { private long id; private String first_name; private String last_name; private String email; //Setters and getters @Override public String toString() { return "User [id=" + id + ", " + "first_name=" + first_name + ", " + "last_name=" + last_name + ", " + "email=" + email + "]"; } }3.3. 业务接口 现在,我们可以使用Retrofit注解来创建具有所需映射信息和请求/响应类的服务接口。$title(UserService.java) import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Path; public interface UserService { @GET("/api/users/{id}") public Call<UserApiResponse> getUser(@Path("id") long id); }我们可以使用适当的改造注释为每个HTTP方法:@GET,@POST,@PUT,@DELETE,@PATCH或@HEAD。在方法注释中,我们应该指定REST资源的相对端点URL。在这种情况下,它是 - "/api/users/{id}"。在方法声明中,我们必须将服务器所期望的数据返回到一个类型化的Retrofit Call< >类中。在方法参数中,我们可以传递路径和查询参数,并在PUT / POST请求中请求正文。4. Retrofit 2 实际使用 现在是时候使用create Retrofit REST客户端并进行实际的API调用。在这个例子中,我们使用流畅的API与Retrofit.Builder和OkHttpClient来创建Retrofit实例。我们提供API和转换器类型的基本URL。$title(UserServiceClient.java) import okhttp3.OkHttpClient; import retrofit2.Call; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; $title(UserServiceClient.java) public class UserServiceClient { public static void main(String[] args) { OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://reqres.in/") .addConverterFactory(GsonConverterFactory.create()) .client(httpClient.build()) .build(); UserService service = retrofit.create(UserService.class); // Calling '/api/users/2' Call<UserApiResponse> callSync = service.getUser(2); try { Response<UserApiResponse> response = callSync.execute(); UserApiResponse apiResponse = response.body(); System.out.println(apiResponse); } catch (Exception ex) { ex.printStackTrace(); } } } 运行上面的程序,观察控制台中打印的输出。$title(out) UserApiResponse [data=User [ id=2, first_name=Janet, last_name=Weaver, email=janet.weaver@reqres.in]] 在上面的例子中,我们已经进行了同步请求。我们将在接下来的教程中会讲解异步请求。总结在本教程中,我们了解了Retrofit 2并为REST客户端构建了一个使用JSON有效负载的hello world应用程序。我们还了解了Retrofit库的基础知识。
  • Retrofit 2 如何解析sitemap xml接口/文件

           学习使用Retrofit 2在Android应用程序中解析sitemap (sitemap),使用简单的xml转换器依赖项进行xml解析       学习使用Retrofit 2在Android应用程序中解析sitemap (sitemap),使用简单的xml转换器依赖项进行xml解析。       在此示例中,我们将阅读并解析此博客的sitemap 。下面给出了一个示例条目:$title(Sitemap) <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://leftso.com/retrofit2/retrofit-sync-async-calls/</loc> <lastmod>2019-08-25T22:22:39+00:00</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> ... ... </urlset>1.依赖性 为了能够在android中解析sitemap ,我们至少需要两个依赖项,即retrofit和converter-simplexml。$title(build.gradle) dependencies { compile 'com.squareup.retrofit2:retrofit:2.6.1' compile 'com.squareup.retrofit2:converter-simplexml:2.6.1' }$title(pom.xml) <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>retrofit</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>converter-simplexml</artifactId> <version>2.6.1</version> </dependency>2.sitemap 模型 首先创建用于使用sitemap 条目项的模型。$title(SitemapResponse.java) import java.util.ArrayList; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; @Root(name = "urlset") public class SitemapResponse { @ElementList(name = "url", inline = true) private ArrayList<SitemapEntry> url; @Override public String toString() { return "SitemapResponse [urlset=" + url + "]"; } }$title(SitemapEntry.java) import org.simpleframework.xml.Element; import org.simpleframework.xml.Root; @Root(name="url") public class SitemapEntry { @Element(name="loc") private String loc; @Element(name="lastmod") private String lastmod; @Element(name="changefreq") private String changefreq; @Element(name="priority") private float priority; @Override public String toString() { return "SitemapEntry [loc=" + loc + ", lastmod=" + lastmod + ", changefreq=" + changefreq + ", priority=" + priority + "]"; } }3.sitemap 服务接口 创建服务接口,将通过改造来调用以执行HTTP请求。请注意API URL是sitemap.xml。$title(SitemapService.java) import retrofit2.Call; import retrofit2.http.GET; public interface SitemapService { @GET("sitemap.xml") Call<SitemapResponse> getFeed(); }4.读取sitemap 示例 让我们创建一个改造实例并执行sitemap 请求。给定示例使用异步请求示例。$title(SitemapServiceDemo.java) import java.io.IOException; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.simplexml.SimpleXmlConverterFactory; public class SitemapServiceDemo { private static final String BASE_URL = "https://leftso.com/"; private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl(BASE_URL) .addConverterFactory(SimpleXmlConverterFactory.create()); private static HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); public static void main(String[] args) throws IOException { httpClient.addInterceptor(loggingInterceptor); builder.client(httpClient.build()); Retrofit retrofit = builder.build(); SitemapService SitemapService = retrofit.create(SitemapService.class); Call<SitemapResponse> callAsync = SitemapService.getFeed(); callAsync.enqueue(new Callback<SitemapResponse>() { @Override public void onResponse(Call<SitemapResponse> call, Response<SitemapResponse> response) { if (response.isSuccessful()) { SitemapResponse apiResponse = response.body(); // API response System.out.println(apiResponse); } else { System.out.println("Request Error :: " + response.errorBody()); } } @Override public void onFailure(Call<SitemapResponse> call, Throwable t) { if (call.isCanceled()) { System.out.println("Call was cancelled forcefully"); } else { System.out.println("Network Error :: " + t.getLocalizedMessage()); } } }); } } 程序输出。$title(Console) SitemapResponse [urlset= [SitemapEntry [loc=https://leftso.com/ retrofit2/retrofit-sync-async-calls/, lastmod=2019-08-25T22:22:39+00:00, changefreq=monthly, priority=0.8]. ... ... ...
  • 安卓百度云不限速app下载_百度网盘不限速内部精简安卓版v11.6.66 免费下载

    百度云网盘百度网盘介绍       百度网盘(原百度云)是百度推出的一项云存储服务,已覆盖主流PC和手机操作系统,包含Web版、Windows版、Mac版、Android版、iPhone版和Windows Phone版百度云网盘百度网盘介绍       百度网盘(原百度云)是百度推出的一项云存储服务,已覆盖主流PC和手机操作系统,包含Web版、Windows版、Mac版、Android版、iPhone版和Windows Phone版。        用户将可以轻松将自己的文件上传到网盘上,并可跨终端随时随地查看和分享。2016年,百度网盘总用户数突破4亿。2016年10月11日,百度云改名为百度网盘,此后会更加专注发展个人存储、备份功能。针对安装的一款百度云盘不限速版本app。欢迎大家下尝试。下载地址: 百度网盘不限速内部精简安卓版v11.6.66.apk
  • 百度蜘蛛如何识别

    一、查看UA信息如果UA信息不对,可以直接判断该蜘蛛为非百度搜索的蜘蛛。目前UA分为移动、PC、和小程序三个应用场景,分别如下:【移动UA】Mozilla/5.0(Linux;u;Android 4.2.2;zh-cn;) AppleWeb一、查看UA信息如果UA信息不对,可以直接判断该蜘蛛为非百度搜索的蜘蛛。目前UA分为移动、PC、和小程序三个应用场景,分别如下:【移动UA】Mozilla/5.0(Linux;u;Android 4.2.2;zh-cn;) AppleWebKit/534.46 (KHTML,like Gecko)Version/5.1 Mobile Safari/10600.6.3 (compatible; Baiduspider/2.0;+http://www.baidu.com/search/spider.html)Mozilla/5.0 (iPhone;CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko)Version/9.0 Mobile/13B143 Safari/601.1 (compatible; Baiduspider-render/2.0;+http://www.baidu.com/search/spider.html) 【PC UA】Mozilla/5.0(compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)Mozilla/5.0(compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)【小程序UA】Mozilla/5.0 (iPhone;CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko)Version/9.0 Mobile/13B143 Safari/601.1 (compatible; Baiduspider-render/2.0;Smartapp; +http://www.baidu.com/search/spider.html)二、双向DNS解析认证第一步:DNS反查IP开发者可以对日志中访问服务器的IP地址进行反向DNS查找,判断某只spider是否来自百度搜索引擎,Baiduspider的hostname以*.baidu.com或*.baidu.jp 的格式命名,非*.baidu.com或*.baidu.jp即为冒充。在Linux/Windows/OS三种平台下,验证方法分别如下:1) 在Linux平台下,可以使用host IP命令反解IP来判断该抓取是否来自Baiduspider。2) 在Windows平台或者IBM OS/2平台下,可以使用nslookup IP命令反解IP:打开命令处理器,输入nslookup xxx.xxx.xxx.xxx(IP地址)就能解析IP,判断该抓取是否来自Baiduspider。3) 在macOS平台下,可以使用dig命令反解IP:打开命令处理器输入dig -x xxx.xxx.xxx.xxx(IP地址)就能解析IP,判断该抓取是否来自Baiduspider。第二步:对域名运行正向DNS查找对第一步中通过命令检索到的域名运行正向DNS查找,验证该域名与日志中访问服务器的原始IP地址是否一致,IP地址一致可确认spider来自百度搜索引擎,IP地址不一致即为冒充。【示例】> host 111.206.198.69  69.198.206.111. in-addr.arpa domain name pointer baiduspider-111-206-198-69.crawl.baidu.com.  >hostbaiduspider-111-206-198-69.crawl.baidu.com  baiduspider-111-206-198-69.crawl.baidu.com has address 111.206.198.69
  • 抖音去水印视频解析在线提取免费工具

    抖音无水印视频提取在线工具入口【温馨提示】抖音去水印视频解析在线提取工具入口: 抖音无水印在线解析工具抖音去水印视频解析在线提取工具功能支持抖音段视频APP视频在线去水印解析下载抖音去水印视频解析在线提取工具使用说明步骤一: 打开抖音APP抖音无水印视频提取在线工具入口【温馨提示】抖音去水印视频解析在线提取工具入口: 抖音无水印在线解析工具抖音去水印视频解析在线提取工具功能支持抖音段视频APP视频在线去水印解析下载抖音去水印视频解析在线提取工具使用说明步骤一: 打开抖音APP,点开某个视频,注意这里需要点击视频类型资源,图片相册类型的请使用抖音图片去水印工具。步骤二: 点击视频右下角的分享按钮,在弹出的底部菜单中,向左滑动找到链接分享。这时候分享类容就复制到了手机的剪切板了。复制链接  步骤三: 打开上面的抖音无水印在线解析工具将剪切板复制的内容粘贴到输入框中。输入两位验证码不区分大小写,点击“无水印解析”按钮即可。之前由于没有验证码被疯狂刷然后抖音开始封ip了。迫不得已加了2位验证码,感谢各位理解。抖音去水印视频解析解析后的视频android手机可以直接点右下角的三个点之间下载。PC也可以参考。        PC视频下载-步骤一               标题  苹果自带的Safari浏览器及微信、QQ等软件内部不能下载,请使用浏览器进行下载,或者下载专用工具下载
  • Zerotier账号注册_Zerotier免费稳定内网穿透工具

    Zerotier 是什么​我们的使命是直接连接世界各地的设备,并实现分散计算的新时代Zerotier 是什么​我们的使命是直接连接世界各地的设备,并实现分散计算的新时代。我们的软件自动处理跨物理网络边界的网络复杂性,处理移动性以及统一云和边缘,使您腾出时间来建设项目和运营业务。我们的网络虚拟化技术将企业软件定义的网络功能提供给每个设备,服务和应用程序,无论其位于边缘还是云中。借助ZeroTier,您可以将整个星球像一个数据中心或云区域一样对待。它足以满足具有复杂网络需求的大型企业的需求,但又足够容易,成千上万的普通人使用它来做一些简单的事情,例如在线玩游戏或从移动设备连接到家用PC。我们的软件和SDK可帮助开发人员构建易于创建和使用的分布式和分散式应用程序。我们致力于解决分散式应用程序开发背后的艰巨技术问题,因此您可以交付可提供积极的低摩擦用户体验的应用程序,同时避免因大量参与云计算而产生的成本,责任和安全/隐私影响。ZeroTier位于加利福尼亚州尔湾市,由Adam Ierymenko于2015年创立。说这么多都不重要,重要的是它的内网穿透免费版完全够用,免费版能接入100个设备。本文主要讲解Zerotier入门操作,账号注册及登录管理Zerotier 内网穿透后网络模型图 ​Zerotier提供了大量的客户端支持,在需要接入的设备上必须安装Zerotier提供的客户端。提示:目前Zerotier支持的系统有:Microsoft Windows 7+(32/64位)/MacOS 10.7+/Apple iOS 10+/Android 4.0.3+/Linux (DEB/RPM)/FreeBSD/Synology NAS/QNAP NAS/WD MyCloud NAS/Community OpenWRT Port(例如docker) 开源地址:ZeroTier One on GitHubZerotier 账号注册1.首先打开网页:my.www.zerotier.com​2.点击Log In to Zero Tier​上图中找到这个不容易看见的注册按钮,点进入下一步:​看到上面的页面后,填写注册信息,其中email需要认真填写,因为点击注册后会发送一封注册验证邮件。需要点击邮件进行通过注册验证。下面是点击注册后的页面:​这个时候去登录你注册时候填写的邮箱,在邮箱中找到zerotier发送的注册验证邮件,里面有个连接点击进去完成验证。接下来是登录,登录成功后,在Account(账户)栏目可以看到下面的信息:​可以看到,默认情况是Free(免费版本),并说明了免费版支持100个设备连接。​上图是网络管理的页面,下一章将会讲解zerotier网络创建及配置相关操作。
  • AES 使用JavaScript加密然后用Java解密

    引言AES代表高级加密系统,它是一种对称加密算法引言AES代表高级加密系统,它是一种对称加密算法。很多时候我们需要在客户端加密一些明文,例如密码,并将其发送到服务器,然后服务器将其解密以进一步处理.AES加密和解密更容易在Android客户端和Java服务器等相同的平台上实现,但有时在跨平台环境(如Javascript客户端和Java Server,如Spring mvc框架)中解密AES加密密码变得非常具有挑战性,因为如果任何系统默认值不匹配解密将失败。    在本文中,我们将使用spring mvc和angular js客户端创建一个应用程序。我们将有一个带有用户名和密码的表单输入的登录页面。在将密码发送到服务器之前,密码将使用CryptoJS在JavaScript中加密,并且相同的加密密码将在java中解密,并且会进行比较以匹配密码。我们将在javascript中生成salt和IV,然后生成从密码,salt和密钥大小中使用PBKDF2函数的密钥。之后,我们将使用密钥和IV对明文进行加密,并且这些密钥将在Java中进行解密。因此,基本上我们将开发一种可与Java进行可互操作的AES加密的机制,的JavaScript。    在继续进行之前,让我们明确一点,该机制仅在数据的有线传输期间(最有可能)增加了一种额外的安全性,但并未提供充分的证明安全性。如果您不使用SSL,则攻击者可以执行中间人攻击并通过为用户提供不同的密钥来窃取数据。项目结构我们这里有个spring  boot和angular js webapp项目。项目结构如下:​JavaScript中的Aes加密    对于JavaScript中的AES加密,我们已经导入了两个js文件 - crypto.js并且pbkdf2.js我们有AesUtil.js用于执行加密和解密的通用代码。这里this.keySize是4字节块的密钥大小。因此,要使用128位密钥,我们将位数除以32得到用于CryptoJS的密钥大小。 AesUtil.js:var AesUtil = function(keySize, iterationCount) { this.keySize = keySize / 32; this.iterationCount = iterationCount; }; AesUtil.prototype.generateKey = function(salt, passPhrase) { var key = CryptoJS.PBKDF2( passPhrase, CryptoJS.enc.Hex.parse(salt), { keySize: this.keySize, iterations: this.iterationCount }); return key; } AesUtil.prototype.encrypt = function(salt, iv, passPhrase, plainText) { var key = this.generateKey(salt, passPhrase); var encrypted = CryptoJS.AES.encrypt( plainText, key, { iv: CryptoJS.enc.Hex.parse(iv) }); return encrypted.ciphertext.toString(CryptoJS.enc.Base64); } AesUtil.prototype.decrypt = function(salt, iv, passPhrase, cipherText) { var key = this.generateKey(salt, passPhrase); var cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext: CryptoJS.enc.Base64.parse(cipherText) }); var decrypted = CryptoJS.AES.decrypt( cipherParams, key, { iv: CryptoJS.enc.Hex.parse(iv) }); return decrypted.toString(CryptoJS.enc.Utf8); }密码加密在JavaScript中    该方法logMeIn()将在点击提交按钮后被调用。此方法将使用定义的通用代码AesUtil.js对密码进行加密并使POST请求验证密码。发送的密码将采用以下格式:iv::salt::ciphertext在服务器端,java将解密密码并在响应中发送解密密码显示在警告框中。var app = angular.module('demoApp', []); app.controller('loginController', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) { $scope.logMeIn = function(){ if(!$scope.userName || !$scope.password){ $scope.showMessage("Missing required fields.", false); return; } var iv = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex); var salt = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex); var aesUtil = new AesUtil(128, 1000); var ciphertext = aesUtil.encrypt(salt, iv, $('#key').text(), $scope.password); var aesPassword = (iv + "::" + salt + "::" + ciphertext); var password = btoa(aesPassword); var data = { userName: $scope.userName, password: password } $http.post('/login',data).then(function (response){ if(response.status === 200){ alert("Password is " + response.data.password); }else { alert("Error occurred"); } }) }; }]);Java中的AES解密首先让我们实现将拦截登录请求的控制器类。在这里,我们对密钥进行了硬编码。此密钥将由服务器唯一地生成并发送给客户端以用于每个登录请求。客户端将使用相同的密钥,而加密和服务器将使用相同的密钥进行解密。确保密钥长度为16,因为我们使用的是128位加密。请记住我们从客户端发送的加密文本的格式iv::salt::ciphertext。文本以相同的格式解密。我们已经有IV,盐和密文。import com.example.demo.model.Credentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.UUID; @Controller public class WelcomeController { private static final Logger LOGGER = LoggerFactory.getLogger(WelcomeController.class); @RequestMapping(value={"/login"},method = RequestMethod.GET) public String loginPage(HttpServletRequest request){ LOGGER.info("Received request for login page with id - " + request.getSession().getId()); String randomKey = UUID.randomUUID().toString(); //String uniqueKey = randomKey.substring(randomKey.length()-17, randomKey.length() -1); String uniqueKey = "1234567891234567"; request.getSession().setAttribute("key", uniqueKey); return "index"; } @RequestMapping(value={"/login"},method = RequestMethod.POST) public @ResponseBody ResponseEntity login(@RequestBody Credentials credentials, HttpServletRequest request) { String decryptedPassword = new String(java.util.Base64.getDecoder().decode(credentials.getPassword())); AesUtil aesUtil = new AesUtil(128, 1000); Map map = new HashMap<>(); if (decryptedPassword != null && decryptedPassword.split("::").length == 3) { LOGGER.info("Password decrypted successfully for username - " + credentials.getUserName()); String password = aesUtil.decrypt(decryptedPassword.split("::")[1], decryptedPassword.split("::")[0], "1234567891234567", decryptedPassword.split("::")[2]); map.put("password", password); } return new ResponseEntity<>(map, HttpStatus.OK); } } 以下是用于AES加密和解密的java util类。您可以按照java中的AES加密和解密获得关于以下实现的更多详细说明。import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; public class AesUtil { private final int keySize; private final int iterationCount; private final Cipher cipher; public AesUtil(int keySize, int iterationCount) { this.keySize = keySize; this.iterationCount = iterationCount; try { cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw fail(e); } } public String decrypt(String salt, String iv, String passphrase, String ciphertext) { try { SecretKey key = generateKey(salt, passphrase); byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, base64(ciphertext)); return new String(decrypted, "UTF-8"); } catch (UnsupportedEncodingException e) { return null; }catch (Exception e){ return null; } } private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) { try { cipher.init(encryptMode, key, new IvParameterSpec(hex(iv))); return cipher.doFinal(bytes); } catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { return null; } } private SecretKey generateKey(String salt, String passphrase) { try { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), iterationCount, keySize); SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); return key; } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { return null; } } public static byte[] base64(String str) { return Base64.decodeBase64(str); } public static byte[] hex(String str) { try { return Hex.decodeHex(str.toCharArray()); } catch (DecoderException e) { throw new IllegalStateException(e); } } private IllegalStateException fail(Exception e) { return null; } }测试AES加密和解密     DemoApplication.java作为Java应用程序运行,然后打到http:// localhost:8080。一旦出现登录页面,您可以输入用户名和密码,然后单击提交按钮,您可以在警报中看到解密的密码。​总结在这篇文章中,我们讨论了使用Java和Javascript进行可互操作的AES加密。我们使用Crypto.js库在javascript中执行此加密。提示:项目源码下载aes-encryption-javascript-java-master.zip