• 关于

    java中的r t

    的搜索结果

问题

JAVA中如何在一个位置长度字符串中,取某固定字符后固定位数的字符?

蛮大人123 2019-12-01 19:45:15 1306 浏览量 回答数 1

回答

对于少量数据:30w行以内的,excel就可以用中小数据:100w行左右,用SQLite 就可以中等或者中大规模数据10T内(5亿条左右):mysql oracle大规模数PB量级: hadoop另外还可以用采样等方式减少数据量,然后用R或者python里面的包来处理。数据挖掘很少用到java,一般是最后模型参数跑出来了以后,用java上到应用层。建模和模型评估还是用python和R比较多。SAS和SPSS也可以用,当然比较贵就是了

tbula 2019-12-02 03:20:00 0 浏览量 回答数 0

问题

跳表-尝试实现get()和set()方法

montos 2020-03-26 21:20:30 0 浏览量 回答数 1

阿里云高校特惠,助力学生创业梦!0元体验,快速入门云计算!

学生动手场景应用,快速了解并掌握云服务器的各种新奇玩法!

回答

一、Lambda表达式 Lambda表达式可以说是Java 8最大的卖点,她将函数式编程引入了Java。Lambda允许把函数作为一个方法的参数,或者把代码看成数据。 一个Lambda表达式可以由用逗号分隔的参数列表、–>符号与函数体三部分表示。例如: Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) ); 1 Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) ); 为了使现有函数更好的支持Lambda表达式,Java 8引入了函数式接口的概念。函数式接口就是只有一个方法的普通接口。java.lang.Runnable与java.util.concurrent.Callable是函数式接口最典型的例子。为此,Java 8增加了一种特殊的注解@FunctionalInterface: 1 @FunctionalInterface2 public interface Functional {3 void method();4 }二、接口的默认方法与静态方法 我们可以在接口中定义默认方法,使用default关键字,并提供默认的实现。所有实现这个接口的类都会接受默认方法的实现,除非子类提供的自己的实现。例如: 1 public interface DefaultFunctionInterface {2 default String defaultFunction() {3 return "default function";4 }5 }我们还可以在接口中定义静态方法,使用static关键字,也可以提供实现。例如: 1 public interface StaticFunctionInterface {2 static String staticFunction() {3 return "static function";4 }5 }接口的默认方法和静态方法的引入,其实可以认为引入了C++中抽象类的理念,以后我们再也不用在每个实现类中都写重复的代码了。 三、方法引用 通常与Lambda表达式联合使用,可以直接引用已有Java类或对象的方法。一般有四种不同的方法引用: 构造器引用。语法是Class::new,或者更一般的Class< T >::new,要求构造器方法是没有参数; 静态方法引用。语法是Class::static_method,要求接受一个Class类型的参数; 特定类的任意对象方法引用。它的语法是Class::method。要求方法是没有参数的; 特定对象的方法引用,它的语法是instance::method。要求方法接受一个参数,与3不同的地方在于,3是在列表元素上分别调用方法,而4是在某个对象上调用方法,将列表元素作为参数传入; 四、重复注解 在Java 5中使用注解有一个限制,即相同的注解在同一位置只能声明一次。Java 8引入重复注解,这样相同的注解在同一地方也可以声明多次。重复注解机制本身需要用@Repeatable注解。Java 8在编译器层做了优化,相同注解会以集合的方式保存,因此底层的原理并没有变化。 五、扩展注解的支持 Java 8扩展了注解的上下文,几乎可以为任何东西添加注解,包括局部变量、泛型类、父类与接口的实现,连方法的异常也能添加注解。 六、Optional Java 8引入Optional类来防止空指针异常,Optional类最先是由Google的Guava项目引入的。Optional类实际上是个容器:它可以保存类型T的值,或者保存null。使用Optional类我们就不用显式进行空指针检查了。 七、Stream Stream API是把真正的函数式编程风格引入到Java中。其实简单来说可以把Stream理解为MapReduce,当然Google的MapReduce的灵感也是来自函数式编程。她其实是一连串支持连续、并行聚集操作的元素。从语法上看,也很像linux的管道、或者链式编程,代码写起来简洁明了,非常酷帅! 八、Date/Time API (JSR 310) Java 8新的Date-Time API (JSR 310)受Joda-Time的影响,提供了新的java.time包,可以用来替代 java.util.Date和java.util.Calendar。一般会用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration这些类,对于时间日期的改进还是非常不错的。 九、JavaScript引擎Nashorn Nashorn允许在JVM上开发运行JavaScript应用,允许Java与JavaScript相互调用。 十、Base64 在Java 8中,Base64编码成为了Java类库的标准。Base64类同时还提供了对URL、MIME友好的编码器与解码器。 除了这十大新特性之外,还有另外的一些新特性: 更好的类型推测机制:Java 8在类型推测方面有了很大的提高,这就使代码更整洁,不需要太多的强制类型转换了。 编译器优化:Java 8将方法的参数名加入了字节码中,这样在运行时通过反射就能获取到参数名,只需要在编译时使用-parameters参数。 并行(parallel)数组:支持对数组进行并行处理,主要是parallelSort()方法,它可以在多核机器上极大提高数组排序的速度。 并发(Concurrency):在新增Stream机制与Lambda的基础之上,加入了一些新方法来支持聚集操作。 Nashorn引擎jjs:基于Nashorn引擎的命令行工具。它接受一些JavaScript源代码为参数,并且执行这些源代码。 类依赖分析器jdeps:可以显示Java类的包级别或类级别的依赖。 JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)。

auto_answer 2019-12-02 01:55:13 0 浏览量 回答数 0

问题

CentOS中的Android开发笔记1

悠索工作室 2019-12-01 21:14:58 2582 浏览量 回答数 1

问题

android tabhost 跨点击出错. 400 请求出错 

kun坤 2020-05-25 20:34:55 11 浏览量 回答数 1

问题

android tabhost 跨点击出错(代码已贴出)?报错

爱吃鱼的程序员 2020-06-22 14:48:08 0 浏览量 回答数 1

回答

由于java.security.SecureRandom在linux上依赖于/dev/random (linux随机数生成机制参见这里),因此在出现问题的服务器上运行测试程序后运行测试脚本,结果如下:[java] view plain copy haitao-yao@haitaoyao-laptop:/data/develop/java/jre/lib/security$ jps && lsof /dev/random7399 Jps7382 TestRandomCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEjava 7382 haitao-yao 4r CHR 1,8 0t0 4402 /dev/random因此断定是由于随机数生成策略的问题。 google一下发现jetty的这个bug(Jetty HashSessionIdManager hangs on startup),也有人在jdk的bug database中提出过这个问题(参见这里),简单介绍一下:java.security.SecureRandom依赖与/dev/random 生成随机数,可能由于系统interrupt不足,导致在jdk在使用/dev/random时卡死。jetty无法启动,最后导致整个namenode启动卡死。 解决方案在sun的bug database中也已经有人给出,即在java程序启动参数中添加:-Djava.security.egd=file:/dev/urandom,使用/dev/urandom生成随机数。 /dev/random和/dev/urandom的差异分析请参见这里 , 不再多说。 总结:hadoop通过http协议提供html页面暴露系统内部状态,这在分布式系统的设计中是个非常好的feature,但是由于集成了jetty,而集成的jetty在hadoop中可配置性又不强,才暴露了这个问题。非常不理解为什么hadoop不使用独立的线程去启动内部的jetty,毕竟这并不是namenode的主要功能,因为这样的附属功能影响了系统的核心功能,未免有些得不偿失。

蛮大人123 2019-12-02 02:07:08 0 浏览量 回答数 0

问题

从Docker容器中读取Maven Quarkus项目上资源文件夹中的txt文件

montos 2020-03-22 10:03:51 2 浏览量 回答数 1

回答

通过以下示例为您介绍UDT的执行过程。 --示例数据。 @table1 := select * from values ('100000000000000000000') as t(x); @table2 := select * from values (100L) as t(y); --代码逻辑。 --new创建对象。 @a := select new java.math.BigInteger(x) x from @table1; --静态方法调用。 @b := select java.math.BigInteger.valueOf(y) y from @table2; --实例方法调用。 select /*+mapjoin(b)*/ x.add(y).toString() from @a a join @b b; --输出结果如下所示。 100000000000000000100 该UDT共有三个Stage:M1、R2和J3。如果您熟悉MapReduce原理即可知道,由于Join的存在需要做数据Reshuffle,所以会出现多个Stage。通常,不同的Stage是在不同的进程、不同的物理机器上运行的。 M1只执行new java.math.BigInteger(x)操作。 J3在不同阶段执行了java.math.BigInteger.valueOf(y)和x.add(y).toString()操作。这几个操作不仅分阶段执行,而且在不同的进程、不同的物理机器上执行。UDT把这个过程封装起来,将这个过程变得看起来和在同一个JVM中执行的效果几乎一样。 从上述示例中,您可以看到子查询的结果允许UDT类型的列。例如上面变量a的x列是java.math.BigInteger类型,而不是内置类型。UDT类型的数据可以被带到下一个Operator中,再调用其它方法,甚至可以参与数据Shuffle。

LiuWH 2020-03-19 22:50:31 0 浏览量 回答数 0

问题

保存新对象时,反应性存储库引发异常

几许相思几点泪 2019-12-24 20:51:36 229 浏览量 回答数 1

回答

基本上,函数式编程的概念之一是pure functions确定性的,并且没有所谓的副作用immutability。Streamapi中的所有中间操作都是不可变的,并返回新的Stream。 作为中提到Oracle的文件,所有的中间业务的一样filter,map和等返回新流。例如map方法文件如下: Stream<R> map(Function<? super T,? extends R> mapper) 返回一个流,该流包含将给定函数应用于此流的元素的结果。这是一个中间操作。 类型参数:R-新流的元素类型参数: 映射器-应用于每个元素的无干扰,无状态函数 返回: 新流 有关更多信息,您可以看一下Java中的Stream实现(例如map,返回new的方法StatelessOp) public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) { Objects.requireNonNull(mapper); return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) { return new Sink.ChainedReference<P_OUT, R>(sink) { @Override public void accept(P_OUT u) { downstream.accept(mapper.apply(u)); } }; } }; } 回答来源:Stack Overflow

montos 2020-03-26 15:31:35 0 浏览量 回答数 0

问题

Java中的PDF加密格式不匹配

养狐狸的猫 2019-12-01 20:00:28 1 浏览量 回答数 0

回答

RSA算法介绍及JAVA实现,其实java和c++差不多,参考一下吧 <一>基础 RSA算法非常简单,概述如下: 找两素数p和q 取n=p*q 取t=(p-1)*(q-1) 取任何一个数e,要求满足e<t并且e与t互素(就是最大公因数为1) 取d*e%t==1 这样最终得到三个数: n d e 设消息为数M (M <n) 设c=(M**d)%n就得到了加密后的消息c 设m=(c**e)%n则 m == M,从而完成对c的解密。 注:**表示次方,上面两式中的d和e可以互换。 在对称加密中: n d两个数构成公钥,可以告诉别人; n e两个数构成私钥,e自己保留,不让任何人知道。 给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。 别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。 rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解 从而在已知n d的情况下无法获得e;同样在已知n e的情况下无法 求得d。 <二>实践 接下来我们来一个实践,看看实际的操作: 找两个素数: p=47 q=59 这样 n=p*q=2773 t=(p-1)*(q-1)=2668 取e=63,满足e<t并且e和t互素 用perl简单穷举可以获得满主 e*d%t ==1的数d: C:\Temp>perl -e "foreach $i (1..9999){ print($i),last if $i*63%2668==1 }" 847 即d=847 最终我们获得关键的 n=2773 d=847 e=63 取消息M=244我们看看 加密: c=M**d%n = 244**847%2773 用perl的大数计算来算一下: C:\Temp>perl -Mbigint -e "print 244**847%2773" 465 即用d对M加密后获得加密信息c=465 解密: 我们可以用e来对加密后的c进行解密,还原M: m=c**e%n=465**63%2773 : C:\Temp>perl -Mbigint -e "print 465**63%2773" 244 即用e对c解密后获得m=244 , 该值和原始信息M相等。 <三>字符串加密 把上面的过程集成一下我们就能实现一个对字符串加密解密的示例了。 每次取字符串中的一个字符的ascii值作为M进行计算,其输出为加密后16进制 的数的字符串形式,按3字节表示,如01F 代码如下: #!/usr/bin/perl -w #RSA 计算过程学习程序编写的测试程序 #watercloud 2003-8-12 # use strict; use Math::BigInt; my %RSA_CORE = (n=>2773,e=>63,d=>847); #p=47,q=59 my $N=new Math::BigInt($RSA_CORE{n}); my $E=new Math::BigInt($RSA_CORE{e}); my $D=new Math::BigInt($RSA_CORE{d}); print "N=$N D=$D E=$E\n"; sub RSA_ENCRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$cmess); for($i=0;$i < length($$r_mess);$i++) { $c=ord(substr($$r_mess,$i,1)); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($D,$N); $c=sprintf "%03X",$C; $cmess.=$c; } return \$cmess; } sub RSA_DECRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$dmess); for($i=0;$i < length($$r_mess);$i+=3) { $c=substr($$r_mess,$i,3); $c=hex($c); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($E,$N); $c=chr($C); $dmess.=$c; } return \$dmess; } my $mess="RSA 娃哈哈哈~~~"; $mess=$ARGV[0] if @ARGV >= 1; print "原始串:",$mess,"\n"; my $r_cmess = RSA_ENCRYPT(\$mess); print "加密串:",$$r_cmess,"\n"; my $r_dmess = RSA_DECRYPT($r_cmess); print "解密串:",$$r_dmess,"\n"; #EOF 测试一下: C:\Temp>perl rsa-test.pl N=2773 D=847 E=63 原始串:RSA 娃哈哈哈~~~ 加密串:5CB6CD6BC58A7709470AA74A0AA74A0AA74A6C70A46C70A46C70A4 解密串:RSA 娃哈哈哈~~~ C:\Temp>perl rsa-test.pl 安全焦点(xfocus) N=2773 D=847 E=63 原始串:安全焦点(xfocus) 加密串:3393EC12F0A466E0AA9510D025D7BA0712DC3379F47D51C325D67B 解密串:安全焦点(xfocus) <四>提高 前面已经提到,rsa的安全来源于n足够大,我们测试中使用的n是非常小的,根本不能保障安全性, 我们可以通过RSAKit、RSATool之类的工具获得足够大的N 及D E。 通过工具,我们获得1024位的N及D E来测试一下: n=0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90B66EC3A85F5005D BDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF1538D4C2013433B383B 47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941D2ED173CCA50E114705D7E2 BC511951 d=0x10001 e=0xE760A3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C2995 4C5D86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF2 C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A592D2B 1965 设原始信息 M=0x11111111111122222222222233333333333 完成这么大数字的计算依赖于大数运算库,用perl来运算非常简单: A) 用d对M进行加密如下: c=M**d%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x11111111111122222222222233 333333333, 0x10001, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5F CD15F90B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F0 17F9CCF1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD6 0438941D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 即用d对M加密后信息为: c=0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 B) 用e对c进行解密如下: m=c**e%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x17b287be418c69ecd7c39227ab 681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd45692b007f3a2f7c5f5aa1d99ef3 866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b3028f9461a3b1533ec0cb4764414 65f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91f1834580c3f6d90898, 0xE760A 3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C29954C5D 86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF 2C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A 592D2B1965, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90 B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF 1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941 D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x11111111111122222222222233333333333 (我的P4 1.6G的机器上计算了约5秒钟) 得到用e解密后的m=0x11111111111122222222222233333333333 == M C) RSA通常的实现 RSA简洁幽雅,但计算速度比较慢,通常加密中并不是直接使用RSA 来对所有的信息进行加密, 最常见的情况是随机产生一个对称加密的密钥,然后使用对称加密算法对信息加密,之后用 RSA对刚才的加密密钥进行加密。 最后需要说明的是,当前小于1024位的N已经被证明是不安全的 自己使用中不要使用小于1024位的RSA,最好使用2048位的。 ---------------------------------------------------------- 一个简单的RSA算法实现JAVA源代码: filename:RSA.java /* * Created on Mar 3, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ import java.math.BigInteger; import java.io.InputStream; import java.io.OutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.FileWriter; import java.io.FileReader; import java.io.BufferedReader; import java.util.StringTokenizer; /** * @author Steve * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class RSA { /** * BigInteger.ZERO */ private static final BigInteger ZERO = BigInteger.ZERO; /** * BigInteger.ONE */ private static final BigInteger ONE = BigInteger.ONE; /** * Pseudo BigInteger.TWO */ private static final BigInteger TWO = new BigInteger("2"); private BigInteger myKey; private BigInteger myMod; private int blockSize; public RSA (BigInteger key, BigInteger n, int b) { myKey = key; myMod = n; blockSize = b; } public void encodeFile (String filename) { byte[] bytes = new byte[blockSize / 8 + 1]; byte[] temp; int tempLen; InputStream is = null; FileWriter writer = null; try { is = new FileInputStream(filename); writer = new FileWriter(filename + ".enc"); } catch (FileNotFoundException e1){ System.out.println("File not found: " + filename); } catch (IOException e1){ System.out.println("File not found: " + filename + ".enc"); } /** * Write encoded message to 'filename'.enc */ try { while ((tempLen = is.read(bytes, 1, blockSize / 8)) > 0) { for (int i = tempLen + 1; i < bytes.length; ++i) { bytes[i] = 0; } writer.write(encodeDecode(new BigInteger(bytes)) + " "); } } catch (IOException e1) { System.out

寒凝雪 2019-12-02 01:26:21 0 浏览量 回答数 0

回答

该问题在以下文章中涉及:JDK-8161253-LogManager $ Cleaner()可以防止登录其他关闭挂钩。 每张票: 作为创建自定义关机钩子的一种解决方法,您可以创建一个自定义处理程序并将其安装在根记录器上。LogManager $ Cleaner的第一步是关闭记录器上所有已安装的处理程序。清理程序调用自定义处理程序的关闭后,您可以执行以下操作之一: 让清洁程序在处理程序中运行关闭代码。 使用Thread API查找您的自定义关机钩子,然后将其加入。 这是解决方案1: import java.util.logging.Handler; import java.util.logging.LogRecord; import java.util.logging.Logger; public class Test { private static Logger LOGGER = Logger.getLogger(Test.class.getCanonicalName()); public static void main(String[] args) { System.out.println("main()"); LOGGER.info("main()"); new Test(); } private Test() { LOGGER.info("Test()"); System.out.println("Test()"); addShutdownHandler(); } private void addShutdownHandler() { Logger root = Logger.getLogger(""); Handler[] handlers = root.getHandlers(); for(Handler h : handlers) { if (h.getClass() == ShutdownHandler.class) { return; } } for(Handler h : handlers) { root.removeHandler(h); } root.addHandler(new ShutdownHandler()); for(Handler h : handlers) { root.addHandler(h); } } public void shutdown() throws Exception { LOGGER.info("shutdown()"); System.out.println("shutdown()"); stop(); destroy(); } public void stop() throws Exception { LOGGER.info("stop()"); System.out.println("stop()"); } public void destroy() { LOGGER.info("destroy()"); System.out.println("destroy()"); } class ShutdownHandler extends Handler { ShutdownHandler() { } @Override public void close() { final Thread t = Thread.currentThread(); final String old = t.getName(); t.setName("app-shutdown-hook"); try { shutdown(); System.out.println("Bye! ‍♂️"); } catch (Exception e) { e.printStackTrace(); } finally { t.setName(old); } } @Override public void flush() { } @Override public void publish(LogRecord r) { isLoggable(r); } } } 解决方案2变得棘手,因为我们无法确保从关闭挂钩中启动了另一个关闭挂钩。如果要使用Thread :: join,这意味着需要额外的编码。因此,要解决此问题,我们仅使用Future API: import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.logging.ErrorManager; import java.util.logging.Handler; import java.util.logging.LogRecord; import java.util.logging.Logger; public class Test { private static Logger LOGGER = Logger.getLogger(Test.class.getCanonicalName()); public static void main(String[] args) { System.out.println("main()"); LOGGER.info("main()"); new Test(); } private Test() { LOGGER.info("Test()"); System.out.println("Test()"); addShutdownHandler(); } private void addShutdownHandler() { Logger root = Logger.getLogger(""); Handler[] handlers = root.getHandlers(); for(Handler h : handlers) { if (h.getClass() == CleanerJoin.class) { return; } } for(Handler h : handlers) { root.removeHandler(h); } root.addHandler(new CleanerJoin()); for(Handler h : handlers) { root.addHandler(h); } } public void shutdown() throws Exception { LOGGER.info("shutdown()"); System.out.println("shutdown()"); stop(); destroy(); } public void stop() throws Exception { LOGGER.info("stop()"); System.out.println("stop()"); } public void destroy() { LOGGER.info("destroy()"); System.out.println("destroy()"); } class ShutdownTask implements Callable<Void> { ShutdownTask() { } @Override public Void call() throws Exception { shutdown(); System.out.println("Bye! ‍♂️"); return null; } } class CleanerJoin extends Handler { private final FutureTask<Void> sdt = new FutureTask<>(new ShutdownTask()); CleanerJoin() { Runtime.getRuntime().addShutdownHook(new Thread(sdt, "app-shutdown-hook")); } @Override public void close() { boolean interrupted = false; try { for(;;) { try { //Could use LogManager to lookup timeout values and use a timed join. sdt.get(); break; } catch (ExecutionException e) { reportError("Shutdown hook failed.", e, ErrorManager.CLOSE_FAILURE); break; } catch (InterruptedException retry) { interrupted = true; } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } @Override public void flush() { } @Override public void publish(LogRecord r) { isLoggable(r); } } } 回答来源:Stack Overflow

montos 2020-03-25 21:04:34 0 浏览量 回答数 0

回答

对于每一次HTTP或者HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用AccessKeyID和AccessKeySecret对称加密验证实现。其中AccessKeyID是访问者身份,AccessKeySecret是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。 1. 指定请求参数 在代码中指定请求参数,参数中需要包含公共请求头和接口必备的参数信息。 说明 请求参数中不允许出现以Signature为key的参数。 示例代码如下: String accessKeyId = "testId"; String accessSecret = "testSecret"; java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区 java.util.Map<String, String> paras = new java.util.HashMap<String, String>(); 指定参数: paras.put("SignatureMethod", "HMAC-SHA1"); paras.put("SignatureNonce", java.util.UUID.randomUUID().toString()); paras.put("AccessKeyId", accessKeyId); paras.put("SignatureVersion", "1.0"); paras.put("Timestamp", df.format(new java.util.Date())); paras.put("Format", "XML"); paras.put("Action", "BindAxb"); paras.put("Version", "2017-05-25"); paras.put("RegionId", "cn-hangzhou"); paras.put("PoolKey", "FC123456"); paras.put("PhoneNoA", "1700000000"); paras.put("PhoneNoB", "1700000000"); paras.put("Expiration", "2017-05-25 00:00:00"); paras.put("OutId", "123"); 去除签名关键字Key: if (paras.containsKey("Signature")) paras.remove("Signature"); 2. 根据参数Key排序(顺序) 参考代码如下: java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(); sortParas.putAll(paras); 3. 构造待签名的请求串 首先介绍下面会用到的特殊URL编码这个是POP特殊的一种规则,即在一般的URLEncode后再增加三种字符替换:加号 (+)替换成 %20、星号 (*)替换成 %2A、 %7E 替换回波浪号 (~)参考代码如下: public static String specialUrlEncode(String value) throws Exception { return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } 构造待签名的请求串: 把排序后的参数顺序拼接成如下格式: specialUrlEncode(参数Key) + "=" + specialUrlEncode(参数值) 参考代码如下: java.util.Iterator it = sortParas.keySet().iterator(); StringBuilder sortQueryStringTmp = new StringBuilder(); while (it.hasNext()) { String key = it.next(); sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key))); } String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 打印上面的 sortQueryString。结果如下: AccessKeyId=testId&Action=BindAxb&Format=XML&OutId=123&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=45e25e9b-0a6f-4070-8c85-2956eda1b466&SignatureVersion=1.0&PoolKey=FC123456&PhoneNoA=170000000&PhoneNoB=17100000000&Expiration=2017-07-12T02%3A42%3A19Z&Timestamp=2017-07-12T02%3A42%3A19Z&Version=2017-05-25` 对应的未URL编码的值(方便用户对比): AccessKeyId=testId&Action=SendSms&Format=XML&OutId=123&PhoneNumbers=15300000001&RegionId=cn-hangzhou&SignName=阿里云短信测试专用&SignatureMethod=HMAC-SHA1&SignatureNonce=45e25e9b-0a6f-4070-8c85-2956eda1b466&SignatureVersion=1.0&TemplateCode=SMS_71390007&TemplateParam={"customer":"test"}&Timestamp=2017-07-12T02:42:19Z&Version=2017-05-25 按POP的签名规则拼接成最终的待签名串。 规则如下: HTTPMethod + “&” + specialUrlEncode(“/”) + ”&” + specialUrlEncode(sortedQueryString) 参考代码如下: StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET").append("&"); stringToSign.append(specialUrlEncode("/")).append("&"); stringToSign.append(specialUrlEncode(sortedQueryString)); 这就完成了待签名的请求字符串。打印结果如下: GET&%2F&AccessKeyId%3DtestId&Action%BindAxb&Format%3DXML&OutId%3D123&PhoneNoA%3D17000000000&RegionId%3Dcn-hangzhou&PhoneNob%3D171000000000&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D45e25e9b-0a6f-4070-8c85-2956eda1b466&SignatureVersion%3D1.0&PoolKey%3DFC123456&Expiration%3D2017-07-12T02%253A42%253A19Z&Timestamp%3D2017-07-12T02%253A42%253A19Z&Version%3D2017-05-25` 4. 签名 签名采用HmacSHA1算法 + Base64,编码采用UTF-8。参考代码如下: String sign = sign(accessSecret + "&", stringToSign.toString()); public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } 参数说明: accessSecret:你的AccessKeyId对应的秘钥AccessSecret,特别说明:POP要求需要后面多加一个“&”字符,即accessSecret + “&”。 stringToSign:即第三步生成的待签名请求串。 签名后的结果打印如下: zJDF+Lrzhj/ThnlvIToysFRq6t4= 5. 增加签名结果到请求参数中,发送请求 说明 签名也要做特殊URL编码。 String Signature = specialUrlEncode(sign);// zJDF%2BLrzhj%2FThnlvIToysFRq6t4%3D 最终完整的GET请求HTTP为: https://dyplsapi.aliyuncs.com/?AccessKeyId=TMP.AQF0OBbrimInaGb2KfSQv1P8Pkn-Lb42nzU2BhznSVfLMid2PONQYrmMCKlmAAAwLAIUUY77CZGRTjNEl8Sjkf3JHa1epjACFCjQhIMENak7MzJ0tE_aDe0x6Jln&Action=BindAxb&Expiration=2019-09-05%2012%3A00%3A00&Format=JSON&PhoneNoA=15951955192&PhoneNoB=13500000000&SecureTransport=true&SignatureMethod=HMAC-SHA1&SignatureNonce=f47d2107663beeedb84284697babfaaf&SignatureVersion=1.0&SourceIp=42.120.75.150&Timestamp=2019-03-01T07%3A24%3A36Z&Version=2017-05-25&Signature=jrS5Hh4NDSsLIod2809ofkuk%2F98%3D JAVA示例 完整的Java签名Demo代码: 说明 以短信服务SendSms接口为列进行说明,业务参数请自行替换成隐私保护绑定接口参数即可。 public class SignDemo { public static void main(String[] args) throws Exception { String accessKeyId = "testId"; String accessSecret = "testSecret"; java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区 java.util.Map<String, String> paras = new java.util.HashMap<String, String>(); // 1. 系统参数 paras.put("SignatureMethod", "HMAC-SHA1"); paras.put("SignatureNonce", java.util.UUID.randomUUID().toString()); paras.put("AccessKeyId", accessKeyId); paras.put("SignatureVersion", "1.0"); paras.put("Timestamp", df.format(new java.util.Date())); paras.put("Format", "XML"); // 2. 业务API参数 paras.put("Action", "SendSms"); paras.put("Version", "2017-05-25"); paras.put("RegionId", "cn-hangzhou"); paras.put("PhoneNumbers", "15300000001"); paras.put("SignName", "阿里云短信测试专用"); paras.put("TemplateParam", "{"customer":"test"}"); paras.put("TemplateCode", "SMS_71390007"); paras.put("OutId", "123"); // 3. 去除签名关键字Key if (paras.containsKey("Signature")) paras.remove("Signature"); // 4. 参数KEY排序 java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(); sortParas.putAll(paras); // 5. 构造待签名的字符串 java.util.Iterator it = sortParas.keySet().iterator(); StringBuilder sortQueryStringTmp = new StringBuilder(); while (it.hasNext()) { String key = it.next(); sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key))); } String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET").append("&"); stringToSign.append(specialUrlEncode("/")).append("&"); stringToSign.append(specialUrlEncode(sortedQueryString)); String sign = sign(accessSecret + "&", stringToSign.toString()); // 6. 签名最后也要做特殊URL编码 String signature = specialUrlEncode(sign); System.out.println(paras.get("SignatureNonce")); System.out.println("\r\n=========\r\n"); System.out.println(paras.get("Timestamp")); System.out.println("\r\n=========\r\n"); System.out.println(sortedQueryString); System.out.println("\r\n=========\r\n"); System.out.println(stringToSign.toString()); System.out.println("\r\n=========\r\n"); System.out.println(sign); System.out.println("\r\n=========\r\n"); System.out.println(signature); System.out.println("\r\n=========\r\n"); // 最终打印出合法GET请求的URL System.out.println("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp); } public static String specialUrlEncode(String value) throws Exception { return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } }

保持可爱mmm 2020-03-27 00:23:46 0 浏览量 回答数 0

回答

一、运行环境的配置 ◆ JDK的配置 从java.sun.com 网站上下载JDK,注意是要Linux平台的。 这里我下的是jdk-6u20-linux-i586.bin,不是RPM的包。 在终端用root身份操作,将jdk-6u20-linux-i586.bin文件复制到/opt 下面,复制时使用命令 #cp XX /opt/ 提权操作,使用命令 #chmod a+x jdk-6u20-linux-i586.bin 然后 #./jdk-6u20-linux-i586.bin。按空格阅读用户协议,最后输入”yes”来继续安装。 设置环境变量 在最后面加入 如果只有当前用户使用JDK, vi /etc/profile set java environment JAVA_HOME=/opt/jdk1.6.0_20 CLASSPATH=.JAVA_HOME/lib.tools.jar PATH=$JAVA_HOME/binPATH export JAVA_HOME CLASSPATH PATH 保存退出。 要使JDK在所有的用户中使用,可以这样: vi /etc/profile.d/java.sh 在新的java.sh中输入以下内容: set java environment JAVA_HOME=/opt/jdk1.6.0_20 CLASSPATH=.JAVA_HOME/lib/tools.jar PATH=$JAVA_HOME/binPATH export JAVA_HOME CLASSPATH PATH 保存退出,然后给java.sh分配权限:#chmod 755 /etc/profile.d/java.sh 检查环境变量是否配置成功 echo $JAVA_HOME echo $CLASSPATH echo $PATH 检查JDK是否安装成功。 java –version 如果看到JVM版本及相关信息,即安装成功! ◆ TOMCAT的配置 下载Tomcat 从网站http://tomcat.apache.org/ 下载Tomcat,如apache-tomcat-5.5.29.tar.gz 解压文件 使用解压命令# tar zxvf apache-tomcat-5.5.29.tar.gz 为了方便,将生成的文件修改为tomcat-5.5.29 mv apache-tomcat-5.5.29 tomcat-5.5.29 将文件拷贝到/opt/文件夹下 #cp –R tomcat-5.5.29 /opt/ 设置环境变量 #vi /etc/profile/ 在文件末尾加入 #set tomcat environment export JAVA_HOME=/opt/jdk1.6.0_20 export CLASSPATH=$JAVA_HOME/lib/dt.jarJAVA_HOME/lib/tools.jar:. export CATALINA_HOME=/opt/ tomcat-5.5.29 export PATH=$JAVA_HOME/binPATH 使用命令#source /etc/profile 让修改后的文件立即生效。 启动和关闭tomcat #cd /opt/ tomcat-5.5.29/bin 启动tomcat服务 #./startup.sh 打开浏览器 http://localhost:8080,看是否安装成功。 关闭tomcat服务 #./shutdwon.sh ◆ Mysql据库.sql文件导入导出 1. sql文件导出: 先用cmd到mysql的bin目录下: 如: 1) E:\program files\MySQL\MySQL Server 5.0\bin>下 2) E:\program files\MySQL\MySQL Server 5.0\bin>mysqldump -u root -p userurl>links.sql 3) Enter password:123456 4) 会自动在E:\program files\MySQL\MySQL Server 5.0\bin>---------目录下生成links.sql文件 sql文件导入: C:\mysql\bin>mysql -u 用户名 -p 数据库名 < c:/test.sql (source " c:\adsense.sql" ) 中间的空格是一个空格位。 例如: var\lib\mysql>mysql -u root -p info < c:/myro.sql Enter password: **** 稍等一会,就可以导入数据表。 二、操作中遇到的问题 ◆ 数据库方面 在将.sql文件执行导入到info数据库的时候可能会报出如下错误: ERROR 1045 (28000):Access denied for user 'root'@'localhost' (using password:YES) 解决办法: # service mysqld stop # mysqld_safe --user=mysql --skip-grant-tables --skip-networking & # mysql -u root mysql mysql> UPDATE user SET Password=PASSWORD('123') where USER='root'; mysql> FLUSH PRIVILEGES; mysql> quit # service mysqld start # mysql -uroot -p Enter password: <输入新设的密码123> mysql> ② 在将.sql文件导入到info数据库时可能会报如下错误: ERROR 1005 (HY000) at line 25: Can't create table './info/category.frm' (errno: 121) 此错误的原因是自己以前测试时建过info数据库,当时删除时是通过手动直接删除/var/lib/mysql中info数据库。这样做以为是没多大问题,实际上没有删除完全。 解决办法: 再次创建一个info数据库,然后通过命令行执行删除drop database info; ③ 登陆mysql数据库时可能会报如下错误: ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) 解决办法: 启动mysql的守护进程,执行service mysqld start就行了 ④ mysql数据库表名大小写敏感问题: 解决办法: 用root登录,修改/etc/my.cnf 在[mysqld]下加一行:lower_case_table_names=1 重启数据库 ⑤ 数据库乱码问题: 解决办法: ⅰ、 MYSQL创建数据库时候直接指定编码和排序规则: UTF8:create database `info`default character set utf8 collate utf8_general_ci; ⅱ、 改变系统默认字符集,改变如下: etc/my.cnf中[mysqld]字段后加入如下语句default-character-set=gb2312 ◆ tomcat方面 ① tomcat的server.xml配置问题: 当appBase指向info项目时tomcat无法正常启动。 解决办法: 将sever.xml中的配置修改如下: <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"> <Context path="" docBase="/opt/tomcat-5.5.29/project/info" debug="0" reloadable="true" ></Context> ....... ② Tomcat中连接池的配置问题: <Context> <!-- Default set of monitored resources --> <WatchedResource>WEB-INF/web.xml</WatchedResource> <!-- Uncomment this to disable session persistence across Tomcat restarts --> <!-- <Manager pathname="" /> --> <Resource auth="Container" name="jdbc/DBD" type="javax.sql.DataSource" password="" driverClassName="org.gjt.mm.mysql.Driver" maxIdle="2" maxWait="5000" username="root url="jdbc:mysql://localhost:3306/info?useUnicode=true&amp;characterSetResults=UTF-8" maxActive="8" removeAbandoned="true" removeAbandonedTimeout="10" logAbandoned="true" /> 三、环境配置存放目录明细 ① jdk : 放在/opt/jdk1.6.0_20目录下 ② tomcat:放在/opt/tomcat-5.5.29目录下 ③ mysql: /var/lib/mysql -- 数据库目录 /usr/bin/mysql -- mysqladmin mysqldump等命令 /etc/rc.d/init.d -- 启动脚本文件mysql的目录 /usr/share/mysql -- mysql.server命令及配置文件 四、启动、关闭服务的命令 ① 启动mysql服务: service mysqld start 关闭mysql服务: service mysqld stop ② 启动tomcat服务:先进入/opt/tomcat-5.5.29/bin 执行 ./startup.sh 关闭tomcat服务:先进入/opt/tomcat-5.5.29/bin 执行 ./shutdown.sh

hiekay 2019-12-02 01:39:26 0 浏览量 回答数 0

回答

对于每一次HTTP或者HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用AccessKeyID和AccessKeySecret对称加密验证实现。其中AccessKeyID是访问者身份,AccessKeySecret是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。 1. 指定请求参数 在代码中指定请求参数,参数中需要包含公共请求头和接口必备的参数信息。 说明 请求参数中不允许出现以Signature为key的参数。 示例代码如下: String accessKeyId = "yourAccessId"; String accessSecret = "yourAccessSecret"; java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区 java.util.Map<String, String> paras = new java.util.HashMap<String, String>(); 指定参数: paras.put("SignatureMethod", "HMAC-SHA1"); paras.put("SignatureNonce", java.util.UUID.randomUUID().toString()); paras.put("AccessKeyId", accessKeyId); paras.put("SignatureVersion", "1.0"); paras.put("Timestamp", df.format(new java.util.Date())); paras.put("Format", "JSON"); paras.put("RegionId", "cn-shanghai"); # API 版本 paras.put("Version", "2019-06-25"); # API ACTION paras.put("Action", "SegmentImage"); # 下面是业务参数 paras.put("Url", "http://vigen-invi-cdn.alibaba.com/aliyun-doc/pop/images/segment-image-src.jpg"); 去除签名关键字Key: if (paras.containsKey("Signature")) { paras.remove("Signature"); } 根据参数Key排序(顺序) 参考代码如下: java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(); .sortParas.putAll(paras); 构造待签名的请求串 首先介绍下面会用到的特殊URL编码这个是POP特殊的一种规则,即在一般的URLEncode后再增加三种字符替换:加号 (+)替换成 %20、星号 (*)替换成 %2A、 %7E 替换回波浪号 (~)参考代码如下: public static String specialUrlEncode(String value) throws Exception { return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } 构造待签名的请求串: 把排序后的参数顺序拼接成如下格式: "&" + specialUrlEncode(参数Key) + "=" + specialUrlEncode(参数值) 参考代码如下: java.util.Iterator<String> it = sortParas.keySet().iterator(); StringBuilder sortQueryStringTmp = new StringBuilder(); while (it.hasNext()) { String key = it.next(); sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key))); } String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 打印上面的 sortQueryString。结果如下: AccessKeyId=yourAccessId&Action=SegmentImage&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=3ed0a494-421e-4979-ab1e-f0e28072795a&SignatureVersion=1.0&Timestamp=2019-10-13T01%3A28%3A40Z&Url=http%3A%2F%2Fvigen-invi-cdn.alibaba.com%2Faliyun-doc%2Fpop%2Fimages%2Fsegment-image-src.jpg&Version=2019-06-25 对应的未URL编码的值(方便用户对比): AccessKeyId=yourAccessId&Action=SegmentImage&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=3ed0a494-421e-4979-ab1e-f0e28072795a&SignatureVersion=1.0&Timestamp=2019-10-13T01:28:40Z&Url=http://vigen-invi-cdn.alibaba.com/aliyun-doc/pop/images/segment-image-src.jpg&Version=2019-06-25 按POP的签名规则拼接成最终的待签名串。规则如下: HTTPMethod + “&” + specialUrlEncode(“/”) + ”&” + specialUrlEncode(sortedQueryString) 参考代码如下: StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET").append("&"); stringToSign.append(specialUrlEncode("/")).append("&"); stringToSign.append(specialUrlEncode(sortedQueryString)); 这就完成了待签名的请求字符串。打印结果如下: POST&%2F&AccessKeyId%3DyourAccessId%26Action%3DSegmentImage%26Format%3DJSON%26RegionId%3Dcn-shanghai%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D39720f7f-373c-4b7c-9ec8-520fdc51741f%26SignatureVersion%3D1.0%26Timestamp%3D2019-10-13T02%253A15%253A41Z%26Url%3Dhttp%253A%252F%252Fvigen-invi-cdn.alibaba.com%252Faliyun-doc%252Fpop%252Fimages%252Fsegment-image-src.jpg%26Version%3D2019-06-25 签名 签名采用HmacSHA1算法 + Base64,编码采用UTF-8。参考代码如下: String sign = sign(accessSecret + "&", stringToSign.toString()); public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } 参数说明: accessSecret:你的AccessKeyId对应的秘钥AccessSecret,特别说明:POP要求需要后面多加一个“&”字符,即accessSecret + “&” stringToSign:即第三步生成的待签名请求串 签名后的结果打印如下: sEl89yBxH69oSz52bM0S7rLc0vM= 增加签名结果到请求参数中,发送请求 说明 签名也要做特殊URL编码。 String Signature = specialUrlEncode(sign);// sEl89yBxH69oSz52bM0S7rLc0vM%3D 最终完整的POST请求HTTP为: http://ivpd.cn-shanghai.aliyuncs.com/?Signature=sEl89yBxH69oSz52bM0S7rLc0vM%3D&AccessKeyId=yourAccessId&Action=SegmentImage&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=39720f7f-373c-4b7c-9ec8-520fdc51741f&SignatureVersion=1.0&Timestamp=2019-10-13T02%3A15%3A41Z&Url=http%3A%2F%2Fvigen-invi-cdn.alibaba.com%2Faliyun-doc%2Fpop%2Fimages%2Fsegment-image-src.jpg&Version=2019-06-25 最后发起请求示例: ](http://public-vigen-invi-zb.oss-cn-zhangjiakou.aliyuncs.com/aliyun-doc/pop/images/HTTP-REST-DOC.jpg JAVA示例 完整的Java签名Demo代码: package com.aliyun.aic.demo; import java.util.HashMap; import java.util.Map; public class SignDemo { static final String API_HTTP_METHOD = "POST"; static final String API_VERSION = "2019-06-25"; static final java.text.SimpleDateFormat DF = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); public static void main(String[] args) throws Exception { String accessKeyId = "yourAccessId"; String accessSecret = "yourAccessSecret"; DF.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区 Map<String, String> params = new HashMap<>();//业务参数名字是大驼峰 params.put("Url", "http://vigen-invi-cdn.alibaba.com/aliyun-doc/pop/images/segment-image-src.jpg"); String action = "SegmentImage"; execute(action, accessKeyId, accessSecret, params); } public static void execute(String action, String accessKeyId, String accessSecret, Map<String, String> bizParams) throws Exception { java.util.Map<String, String> paras = new java.util.HashMap<String, String>(); // 1. 系统参数 paras.put("SignatureMethod", "HMAC-SHA1"); paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());//防止重放攻击 paras.put("AccessKeyId", accessKeyId); paras.put("SignatureVersion", "1.0"); paras.put("Timestamp", DF.format(new java.util.Date())); paras.put("Format", "JSON"); // 2. 业务API参数 paras.put("RegionId", "cn-shanghai"); paras.put("Version", API_VERSION); paras.put("Action", action); if (bizParams != null && !bizParams.isEmpty()) { paras.putAll(bizParams); } // 3. 去除签名关键字Key if (paras.containsKey("Signature")) { paras.remove("Signature"); } // 4. 参数KEY排序 java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(); sortParas.putAll(paras); // 5. 构造待签名的字符串 java.util.Iterator<String> it = sortParas.keySet().iterator(); StringBuilder sortQueryStringTmp = new StringBuilder(); while (it.hasNext()) { String key = it.next(); sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key))); } String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(API_HTTP_METHOD).append("&"); stringToSign.append(specialUrlEncode("/")).append("&"); stringToSign.append(specialUrlEncode(sortedQueryString)); String sign = sign(accessSecret + "&", stringToSign.toString()); // 6. 签名最后也要做特殊URL编码 String signature = specialUrlEncode(sign); System.out.println(paras.get("SignatureNonce")); System.out.println("\r\n=========\r\n"); System.out.println(paras.get("Timestamp")); System.out.println("\r\n=========\r\n"); System.out.println(sortedQueryString); System.out.println("\r\n=========\r\n"); System.out.println(stringToSign.toString()); System.out.println("\r\n=========\r\n"); System.out.println(sign); System.out.println("\r\n=========\r\n"); System.out.println(signature); System.out.println("\r\n=========\r\n"); // 最终打印出合法请求的URL System.out.println("http://ivpd.cn-shanghai.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp); } public static String specialUrlEncode(String value) throws Exception { return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } }

保持可爱mmm 2020-03-27 10:13:56 0 浏览量 回答数 0

问题

关于一个Activity跳转到另外一个Activity失败的问题

爵霸 2019-12-01 20:07:47 2092 浏览量 回答数 2

回答

对于每一次HTTP或者HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用AccessKeyID和AccessKeySecret对称加密验证实现。其中AccessKeyID是访问者身份,AccessKeySecret是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。 1. 指定请求参数 在代码中指定请求参数,参数中需要包含公共请求头和接口必备的参数信息。 说明 请求参数中不允许出现以Signature为key的参数。 示例代码如下: String accessKeyId = "testId"; String accessSecret = "testSecret"; java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区 java.util.Map<String, String> paras = new java.util.HashMap<String, String>(); 指定参数: paras.put("SignatureMethod", "HMAC-SHA1"); paras.put("SignatureNonce", java.util.UUID.randomUUID().toString()); paras.put("AccessKeyId", accessKeyId); paras.put("SignatureVersion", "1.0"); paras.put("Timestamp", df.format(new java.util.Date())); paras.put("Format", "XML"); paras.put("Action", "SendSms"); paras.put("Version", "2017-05-25"); paras.put("RegionId", "cn-hangzhou"); paras.put("PhoneNumbers", "15300000001"); paras.put("SignName", "阿里云短信测试专用"); paras.put("TemplateParam", "{"customer":"test"}"); paras.put("TemplateCode", "SMS_71390007"); paras.put("OutId", "123"); 去除签名关键字Key: if (paras.containsKey("Signature")) paras.remove("Signature"); 根据参数Key排序(顺序) 参考代码如下: java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(); .sortParas.putAll(paras); 构造待签名的请求串 首先介绍下面会用到的特殊URL编码这个是POP特殊的一种规则,即在一般的URLEncode后再增加三种字符替换:加号 (+)替换成 %20、星号 (*)替换成 %2A、 %7E 替换回波浪号 (~)参考代码如下: public static String specialUrlEncode(String value) throws Exception { return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } 构造待签名的请求串: 把排序后的参数顺序拼接成如下格式: * specialUrlEncode(参数Key) + "=" + specialUrlEncode(参数值) 参考代码如下: java.util.Iterator<String> it = sortParas.keySet().iterator(); StringBuilder sortQueryStringTmp = new StringBuilder(); while (it.hasNext()) { String key = it.next(); sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key))); } String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 打印上面的 sortQueryString。结果如下: AccessKeyId=testId&Action=SendSms&Format=XML&OutId=123&PhoneNumbers=15300000001&RegionId=cn-hangzhou&SignName=%E9%98%BF%E9%87%8C%E4%BA%91%E7%9F%AD%E4%BF%A1%E6%B5%8B%E8%AF%95%E4%B8%93%E7%94%A8&SignatureMethod=HMAC-SHA1&SignatureNonce=45e25e9b-0a6f-4070-8c85-2956eda1b466&SignatureVersion=1.0&TemplateCode=SMS_71390007&TemplateParam=%7B%22customer%22%3A%22test%22%7D&Timestamp=2017-07-12T02%3A42%3A19Z&Version=2017-05-25 对应的未URL编码的值(方便用户对比): AccessKeyId=testId&Action=SendSms&Format=XML&OutId=123&PhoneNumbers=15300000001&RegionId=cn-hangzhou&SignName=阿里云短信测试专用&SignatureMethod=HMAC-SHA1&SignatureNonce=45e25e9b-0a6f-4070-8c85-2956eda1b466&SignatureVersion=1.0&TemplateCode=SMS_71390007&TemplateParam={"customer":"test"}&Timestamp=2017-07-12T02:42:19Z&Version=2017-05-25 按POP的签名规则拼接成最终的待签名串。 规则如下: * HTTPMethod + “&” + specialUrlEncode(“/”) + ”&” + specialUrlEncode(sortedQueryString) 参考代码如下: StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET").append("&"); stringToSign.append(specialUrlEncode("/")).append("&"); stringToSign.append(specialUrlEncode(sortedQueryString)); 这就完成了待签名的请求字符串。打印结果如下: GET&%2F&AccessKeyId%3DtestId%26Action%3DSendSms%26Format%3DXML%26OutId%3D123%26PhoneNumbers%3D15300000001%26RegionId%3Dcn-hangzhou%26SignName%3D%25E9%2598%25BF%25E9%2587%258C%25E4%25BA%2591%25E7%259F%25AD%25E4%25BF%25A1%25E6%25B5%258B%25E8%25AF%2595%25E4%25B8%2593%25E7%2594%25A8%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D45e25e9b-0a6f-4070-8c85-2956eda1b466%26SignatureVersion%3D1.0%26TemplateCode%3DSMS_71390007%26TemplateParam%3D%257B%2522customer%2522%253A%2522test%2522%257D%26Timestamp%3D2017-07-12T02%253A42%253A19Z%26Version%3D2017-05-25 签名 签名采用HmacSHA1算法 + Base64,编码采用UTF-8。参考代码如下: String sign = sign(accessSecret + "&", stringToSign.toString()); public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } 参数说明: accessSecret:你的AccessKeyId对应的秘钥AccessSecret,特别说明:POP要求需要后面多加一个“&”字符,即accessSecret + “&” stringToSign:即第三步生成的待签名请求串 签名后的结果打印如下: zJDF+Lrzhj/ThnlvIToysFRq6t4= 增加签名结果到请求参数中,发送请求 说明 签名也要做特殊URL编码。 String Signature = specialUrlEncode(sign);// zJDF%2BLrzhj%2FThnlvIToysFRq6t4%3D 最终完整的GET请求HTTP为: http://dysmsapi.aliyuncs.com/?Signature=zJDF%2BLrzhj%2FThnlvIToysFRq6t4%3D&AccessKeyId=testId&Action=SendSms&Format=XML&OutId=123&PhoneNumbers=15300000001&RegionId=cn-hangzhou&SignName=%E9%98%BF%E9%87%8C%E4%BA%91%E7%9F%AD%E4%BF%A1%E6%B5%8B%E8%AF%95%E4%B8%93%E7%94%A8&SignatureMethod=HMAC-SHA1&SignatureNonce=45e25e9b-0a6f-4070-8c85-2956eda1b466&SignatureVersion=1.0&TemplateCode=SMS_71390007&TemplateParam=%7B%22customer%22%3A%22test%22%7D&Timestamp=2017-07-12T02%3A42%3A19Z&Version=2017-05-25 JAVA示例 完整的Java签名Demo代码: public class SignDemo { public static void main(String[] args) throws Exception { String accessKeyId = "testId"; String accessSecret = "testSecret"; java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区 java.util.Map<String, String> paras = new java.util.HashMap<String, String>(); // 1. 系统参数 paras.put("SignatureMethod", "HMAC-SHA1"); paras.put("SignatureNonce", java.util.UUID.randomUUID().toString()); paras.put("AccessKeyId", accessKeyId); paras.put("SignatureVersion", "1.0"); paras.put("Timestamp", df.format(new java.util.Date())); paras.put("Format", "XML"); // 2. 业务API参数 paras.put("Action", "SendSms"); paras.put("Version", "2017-05-25"); paras.put("RegionId", "cn-hangzhou"); paras.put("PhoneNumbers", "15300000001"); paras.put("SignName", "阿里云短信测试专用"); paras.put("TemplateParam", "{"customer":"test"}"); paras.put("TemplateCode", "SMS_71390007"); paras.put("OutId", "123"); // 3. 去除签名关键字Key if (paras.containsKey("Signature")) paras.remove("Signature"); // 4. 参数KEY排序 java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(); sortParas.putAll(paras); // 5. 构造待签名的字符串 java.util.Iterator it = sortParas.keySet().iterator(); StringBuilder sortQueryStringTmp = new StringBuilder(); while (it.hasNext()) { String key = it.next(); sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key))); } String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET").append("&"); stringToSign.append(specialUrlEncode("/")).append("&"); stringToSign.append(specialUrlEncode(sortedQueryString)); String sign = sign(accessSecret + "&", stringToSign.toString()); // 6. 签名最后也要做特殊URL编码 String signature = specialUrlEncode(sign); System.out.println(paras.get("SignatureNonce")); System.out.println("\r\n=========\r\n"); System.out.println(paras.get("Timestamp")); System.out.println("\r\n=========\r\n"); System.out.println(sortedQueryString); System.out.println("\r\n=========\r\n"); System.out.println(stringToSign.toString()); System.out.println("\r\n=========\r\n"); System.out.println(sign); System.out.println("\r\n=========\r\n"); System.out.println(signature); System.out.println("\r\n=========\r\n"); // 最终打印出合法GET请求的URL System.out.println("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp); } public static String specialUrlEncode(String value) throws Exception { return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } } `

保持可爱mmm 2020-03-27 00:48:46 0 浏览量 回答数 0

回答

tring()); public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } 参数说明: accessSecret:您的AccessKeyId对应的秘钥AccessSecret,特别说明:POP要求需要后面多加一个“&”字符,即accessSecret + “&”。 stringToSign:即第三步生成的待签名请求串。 签名后的结果打印如下: aMfgrx8DLS7vLfpeR1c2rrKLr0Q= 步骤五:增加签名结果到请求参数中,发送请求 说明 签名也要做特殊URL编码。 String Signature = specialUrlEncode(sign);// aMfgrx8DLS7vLfpeR1c2rrKLr0Q%3D 最终完整的GET请求HTTP为: http://dyvmsapi.aliyuncs.com/?Signature=aMfgrx8DLS7vLfpeR1c2rrKLr0Q%3D&AccessKeyId=testId&Action=SingleCallByTts&CalledNumber=13000000000&CalledShowNumber=057112345678&Format=XML&OutId=123&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=f7d2d4ef-6d5f-4da4-86ed-88e001a66abb&SignatureVersion=1.0&Timestamp=2017-09-28T14%3A31%3A56Z&TtsCode=TTS_0000000&TtsParam=%7B%22code%22%3A%221234%22%2C%22product%22%3A%22test%22%7D&Version=2017-05-25 JAVA示例 完整的Java签名Demo代码: public class VmsSignDemo { public static void main(String[] args) throws Exception { String accessKeyId = "testId"; String accessSecret = "testSecret"; java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区 java.util.Map<String, String> paras = new java.util.HashMap<String, String>(); // 1. 系统参数 paras.put("SignatureMethod", "HMAC-SHA1"); paras.put("SignatureNonce", java.util.UUID.randomUUID().toString()); paras.put("AccessKeyId", accessKeyId); paras.put("SignatureVersion", "1.0"); paras.put("Timestamp", df.format(new java.util.Date())); paras.put("Format", "XML"); // 2. 业务API参数 paras.put("Action", "SingleCallByTts"); paras.put("Version", "2017-05-25"); paras.put("RegionId", "cn-hangzhou"); paras.put("CalledShowNumber", "057112345678"); paras.put("CalledNumber", "13000000000"); paras.put("TtsParam", "{"code":"1234","product":"test"}"); paras.put("TtsCode", "TTS_0000000"); paras.put("OutId", "123"); // 3. 去除签名关键字Key if (paras.containsKey("Signature")) paras.remove("Signature"); // 4. 参数KEY排序 java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(); sortParas.putAll(paras); // 5. 构造待签名的字符串 java.util.Iterator it = sortParas.keySet().iterator(); StringBuilder sortQueryStringTmp = new StringBuilder(); while (it.hasNext()) { String key = it.next(); sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key))); } String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET").append("&"); stringToSign.append(specialUrlEncode("/")).append("&"); stringToSign.append(specialUrlEncode(sortedQueryString)); String sign = sign(accessSecret + "&", stringToSign.toString()); // 6. 签名最后也要做特殊URL编码 String signature = specialUrlEncode(sign); System.out.println(paras.get("SignatureNonce")); System.out.println("\r\n=========\r\n"); System.out.println(paras.get("Timestamp")); System.out.println("\r\n=========\r\n"); System.out.println(sortedQueryString); System.out.println("\r\n=========\r\n"); System.out.println(stringToSign.toString()); System.out.println("\r\n=========\r\n"); System.out.println(sign); System.out.println("\r\n=========\r\n"); System.out.println(signature); System.out.println("\r\n=========\r\n"); // 最终打印出合法GET请求的URL System.out.println("http://dyvmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp); } public static String specialUrlEncode(String value) throws Exception { return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } public static String sign(String accessSecret, String stringToSign) throws Exception { javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1"); mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(signData); } } `

保持可爱mmm 2020-03-27 00:41:11 0 浏览量 回答数 0

回答

在函数计算服务使用 Java 编程,需要定义一个 Java 函数作为入口。Java 运行环境根据是否支持 HTTP 触发器分为 普通函数入口 和 HTTP 触发器函数入口 两种函数入口,为函数设置 HTTP 触发器后的函数入口形式会不同,这是为了方便处理发来的 HTTP request 请求并允许用户返回自定义 HTTP header。其中 普通函数入口 又分为 处理函数入口 和 initializer入口。 本文对 普通函数入口 和 HTTP 触发器函数入口 进行详细介绍: 普通函数入口 处理函数入口 StreamRequestHandler PojoRequestHandler initializer 入口 HTTP 触发器函数入口 Java 代码打包 普通函数入口 处理函数入口 用户在使用 Java 编程时,必须要实现函数计算提供的接口类,对于普通函数入口目前有 2 个预定义接口可选择: StreamRequestHandler以流的方式接受调用输入event和返回执行结果,用户需要从inputStream中读取调用函数时的输入,处理完成后把函数执行结果写入到outputStream中来返回。 PojoRequestHandler通过泛型的方式,用户可以自定义输入和输出的类型,但是它们必须是POJO类型。 StreamRequestHandler 一个最简单的处理函数定义如下: package example; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.StreamRequestHandler; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class HelloFC implements StreamRequestHandler { @Override public void handleRequest( InputStream inputStream, OutputStream outputStream, Context context) throws IOException { outputStream.write(new String("hello world").getBytes()); } } 1. 包名/类名 包名和类名可以是任意的,但是需要与创建函数时的 “Handler” 字段相对应:上面的例子包名是 “example”,类名是 “HelloFC”,那么创建函数时指定的 Handler 为 example.HelloFC::handleRequest,”Handler” 的格式为 {package}.{class}::{method}。 实现的接口 用户的代码中必须要实现函数计算预定义的接口。上面的例子中实现了StreamRequestHandler,其中的 inputStream 参数是调用函数时传入的数据,outputStream 用于返回函数的执行结果。 context参数 context 参数中包含一些函数的运行时信息(例如 request id/临时 AK 等)。其类型是 com.aliyun.fc.runtime.Context。 返回值 实现StreamRequestHandler接口的函数通过outputStream参数返回执行结果 引入接口库 其中用到的com.aliyun.fc.runtime这个包的依赖可以通过下面的 pom.xml 引用: com.aliyun.fc.runtime fc-java-core 1.3.0 通过 maven 仓库 可以获取fc-java-core最新的版本号。 在创建函数之前,用户需要将代码及其依赖的 fc-java-core 打包成 jar。关于如何打包,请参见 Java 代码打包。 打包成 jar 后就可以使用 Fun 或者控制台上传代码,以 Fun 为例: 在项目根目录创建一个 template.yml 的文件: ROSTemplateFormatVersion: '2015-09-01' Transform: 'Aliyun::Serverless-2018-04-03' Resources: FunDemo: Type: 'Aliyun::Serverless::Service' javademo: Type: 'Aliyun::Serverless::Function' Properties: Handler: example.HelloFC::handleRequest Runtime: java8 CodeUri: './example.jar' 这个 template.yml 的含义如下:声明一个名为 FunDemo 的 服务,并在这个服务下,再声明一个名为 javademo 的 函数,配置函数入口为 example.HelloFC::handleRequest,以及函数的 runtime 为 java8。并且,我们指定了 CodeUri 为 ./example.jar。在部署时,Fun 会将 CodeUri 指定的目录或文件打包上传。更多的配置规则 请参考。 示例代码包是示例中的 hello world 代码打包成的 jar 包,您可以直接使用 示例代码包 进行测试。 使用 Fun 部署: fun deploy 执行成功时,会看到相关日志: using region: cn-hangzhou using accountId: ***********3557 using accessKeyId: ***********r3Ra using timeout: 300 Waiting for service FunDemo to be deployed... Waiting for function javademo to be deployed... Waiting for packaging function javademo code... package function javademo code done function javademo deploy success service FunDemo deploy success 然后就可以登录控制台查看或直接调用了。 PojoRequestHandler 一个最简单的处理函数定义如下: // HelloFC.java package example; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.PojoRequestHandler; public class HelloFC implements PojoRequestHandler<SimpleRequest, SimpleResponse> { @Override public SimpleResponse handleRequest(SimpleRequest request, Context context) { String message = "Hello, " + request.getFirstName() + " " + request.getLastName(); return new SimpleResponse(message); } } // SimpleRequest.java package example; public class SimpleRequest { String firstName; String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public SimpleRequest() {} public SimpleRequest(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } } // SimpleResponse.java package example; public class SimpleResponse { String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public SimpleResponse() {} public SimpleResponse(String message) { this.message = message; } } 准备调用的输入文件: { "firstName": "FC", "lastName": "aliyun" } 使用 fcli 调用结果: invk hello-java -f /tmp/a.json {"message":"Hello, FC aliyun"} initializer 入口 无论您的函数使用流式输入还是通过泛型的方式自定义输入和输出,当需要在 Java runtime 中添加 initializer 接口时,都需在原有的基础上额外实现 initializer 预定义的接口。 initializer预定义接口如下: package com.aliyun.fc.runtime; import java.io.IOException; public interface FunctionInitializer { /** * The interface to handle a function compute initialize request * * @param context The function compute initialize environment context object. * @throws IOException IOException during I/O handling */ void initialize(Context context) throws IOException; } 一个简单的流式输入的函数和 initializer 结合的 demo 如下: package aliyun.serverless.test.example; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.FunctionComputeLogger; import com.aliyun.fc.runtime.StreamRequestHandler; import com.aliyun.fc.runtime.FunctionInitializer; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class InitializerAndStreamRequest implements StreamRequestHandler, FunctionInitializer { @Override public void initialize(Context context) { FunctionComputeLogger logger = context.getLogger(); logger.debug(String.format("RequestID is %s %n", context.getRequestId())); } @Override public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { FunctionComputeLogger logger = context.getLogger(); logger.debug(String.format("RequestID is %s %n", context.getRequestId())); output.write(new String("hello world!").getBytes()); output.flush(); } } 针对 InitializerAndStreamRequest 中新增加的 initialize 方法即是 initializer 接口,特性如下: 包名/类名 initializer 所属包名和类名和处理函数一致,都可以是任意的。”initializer” 的格式同为 {package}.{class}::{method},与 “handler” 不同的是 handler 中的 method 为 handleRequest,initializer 的 method 为 initialize。根据定义可知此示例的 initializer 为 aliyun.serverless.test.example.InitializerAndStreamRequest::initialize。 实现的接口 用户的代码中必须要实现函数计算预定义的接口。上面示例中 initializer 接口实现了FunctionInitializer,initializer 接口只有一个 context 参数。 context参数 context 参数中包含一些函数的运行时信息(例如 request id/临时 AK 等)。其类型是 com.aliyun.fc.runtime.Context。 返回值 实现FunctionInitializer接口的函数无返回结果。 泛型的方式输入的函数和 initializer 结合的 demo 如下: package aliyun.serverless.test.example; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.PojoRequestHandler; import com.aliyun.fc.runtime.FunctionInitializer; import com.aliyun.fc.runtime.FunctionComputeLogger; public class InitializerAndPojoRequest implements FunctionInitializer,PojoRequestHandler<SimpleRequest, SimpleResponse> { @Override public void initialize(Context context) { FunctionComputeLogger logger = context.getLogger(); logger.debug(String.format("RequestID is %s %n", context.getRequestId())); } @Override public SimpleResponse handleRequest(SimpleRequest request, Context context) { FunctionComputeLogger logger = context.getLogger(); logger.debug(String.format("RequestID is %s %n", context.getRequestId())); String message = "Hello, " + request.getFirstName() + " " + request.getLastName(); return new SimpleResponse(message); } } HTTP 触发器函数入口 HTTP 触发器函数接口 HTTP 触发器的简单示例 HTTP 触发器支持传统web应用 关于 HTTP 触发器 的使用请参考:HTTP 触发器 HTTP 触发器函数接口 函数计算提供基于 Servlet 协议的 HTTP 触发器入口,具体接口形式如下: public interface HttpRequestHandler { /** * The entrance function of fc http trigger * @param request The servlet request * @param response The servlet response * @param context The fc context * @throws IOException If IO exception happened * @throws ServletException If servlet exception happened */ public void handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) throws IOException, ServletException; } 使用 HTTP 触发器需将 fc-java-core 库版本升级到 1.3.0 及以上。 HTTP 触发器的简单示例 package com.aliyun.fc.example; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.HttpRequestHandler; public class Hello implements HttpRequestHandler { public void handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) throws IOException, ServletException { String requestPath = (String) request.getAttribute("FC_REQUEST_PATH"); String requestURI = (String) request.getAttribute("FC_REQUEST_URI"); String requestClientIP = (String) request.getAttribute("FC_REQUEST_CLIENT_IP"); response.setStatus(200); response.setHeader("header1", "value1"); response.setHeader("header2", "value2"); String body = String.format("Path: %s\n Uri: %s\n IP: %s\n", requestPath, requestURI, requestClientIP); OutputStream out = response.getOutputStream(); out.write((body).getBytes()); out.flush(); out.close(); } } 1. HttpServletRequest 函数计算 HTTP 触发器的接口直接使用标准的 Servlet 协议。 用户的请求会封装成HttpServletRequest对象,用户请求参数、请求header等均可通过此对象获取。 除此之外,函数计算在HttpServletRequest中预封装了一些属性, 可通过 getAttribute 方法来获取, 具体包括: FC_REQUEST_PATH 获取请求的 Path FC_REQUEST_URI 获取请求的 URI FC_REQUEST_CLIENT_IP 获取请求的 ClientIP HttpServletResponse 用户可通过标准的HttpServletResponse协议对象来返回响应 header 和 body. context参数 context 参数中包含一些函数的运行时信息(例如 request id/临时 AK 等)。其类型是 com.aliyun.fc.runtime.Context。 HTTP 触发器支持传统web应用 基于 Servlet 协议的传统 web 应用能很方便的迁移到函数计算平台,目前支持的主流框架包括 Spring 、 SpringBoot 、 Struts2 等。以下示例如何通过函数计算提供的 fc-java-common 库来加载 web 应用. 打包您的 web 工程,生成 demo.war 包 上传 demo.war 包到 OSS,比如为 demo-bucket 下的 demo.war 创建函数,并设置函数初始化入口和函数入口。 函数示例代码如下: package com.aliyun.fc.example; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.FcAppLoader; import com.aliyun.fc.runtime.FunctionComputeLogger; import com.aliyun.fc.runtime.FunctionInitializer; import com.aliyun.fc.runtime.HttpRequestHandler; public class HelloWeb implements FunctionInitializer, HttpRequestHandler { private FcAppLoader fcAppLoader = new FcAppLoader(); private String ossEndPoint = "YourOSSEndPoint"; private String bucket = "YourOSSBucket"; private String key = "YourWarName"; private String userContextPath = "/2016-08-15/proxy/{YourServiceName}/{YourFunctionName}"; @Override public void initialize(Context context) throws IOException { FunctionComputeLogger fcLogger = context.getLogger(); fcAppLoader.setFCContext(context); // Load code from OSS fcAppLoader.loadCodeFromOSS(ossEndPoint, bucket, key); // Init webapp from code fcAppLoader.initApp(userContextPath, HelloWeb.class.getClassLoader()); } @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) throws IOException, ServletException { try { fcAppLoader.forward(request, response); } catch (Exception e) { e.printStackTrace(); } } } 引用 Maven 库 com.aliyun.fc.runtime fc-java-core 1.3.0 com.aliyun.fc.runtime fc-java-common 2.2.2 Java 代码打包 使用 maven 打包jar 使用 IDEA 打包jar 使用 maven 打包 jar 在 pom.xml 中添加 maven-assembly-plugin 插件 maven-assembly-plugin 3.1.0 jar-with-dependencies false make-assembly package single org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 打包 mvn package 执行完毕后,生成的 jar 会被存放在 target 目录下。 使用 maven 打包 jar,并将依赖以 jar 的形式存放在 /lib 目录中 随着项目依赖的增加,jar 的体积会变得越来越大。而用户上传的 jar 或者 zip 代码,在执行前,首先会被解压缩,然后才会被加载、执行。因此在刚才的两种实现中,存在的一个问题是我们打包的 jar 中包含了大量的 class 文件,这无疑会增加解压缩的时间,进而增加函数的首次启动时间。 一个更好的实践是将第三方依赖以 jar 的形式,存放于 /lib 目录。 这里提供一种使用 maven-dependency-plugin 实现的方案: org.apache.maven.plugins maven-dependency-plugin copy-dependencies prepare-package copy-dependencies ${project.build.directory}/classes/lib runtime 执行完 mvn package,打包好的 jar 的目录结构为: /.class lib/*.jar 使用 IDEA 打包 jar 配置导出 jar 包的选项: java1 java2 java3 验证打包结果 rockuw-MBP:hello-java (master) $ ls -lrth total 6520 -rw-r--r-- 1 rockuw staff 3.2M Aug 31 21:03 hellofc.jar rockuw-MBP:hello-java (master) $ jar -tf hellofc.jar | head Picked up _JAVA_OPTIONS: -Duser.language=en META-INF/MANIFEST.MF example/ example/HelloFC.class example/SimpleRequest.class example/SimpleResponse.class META-INF/ META-INF// org/ org// org/apache/ 函数计算目前支持以下 Java 运行环境: OpenJDK 1.8.0 (runtime = java8) 对于 Java 运行环境的基本使用请参考Java 函数入口。以下将介绍 Java 运行环境相关特性: 使用 context 使用 logging 使用自定义的模块 异常处理 使用context context 是函数计算在运行时生成的一个对象,其中包含一些运行时的信息,用户在代码中可以使用这些信息。其定义如下,具体实现可以在 这里 找到: package com.aliyun.fc.runtime; public interface Context { public String getRequestId(); public Credentials getExecutionCredentials(); public FunctionParam getFunctionParam(); public FunctionComputeLogger getLogger(); } 可以看到 context 中包含了4个信息: RequestId: 本次调用请求的唯一 id,用户可以把它记录下来在出现问题的时候方便调查 FunctionParam: 当前调用的函数的一些基本信息如函数名/函数入口/函数内存/超时时间 ExecutionCredentials: 函数计算服务通过扮演用户提供的 服务角色获得的一组临时密钥,其有效时间是 5 分钟。用户可以在代码中使用它去访问相应的服务(例如 OSS),这就避免了用户把自己的 AK 信息写死在函数代码里。 Logger: 函数计算封装过的 logger,见下面的 使用logging 例如下面的代码使用临时密钥,向 OSS 中上传了一个文件: package example; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.Credentials; import com.aliyun.fc.runtime.StreamRequestHandler; import com.aliyun.oss.OSSClient; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class HelloFC implements StreamRequestHandler { @Override public void handleRequest( InputStream inputStream, OutputStream outputStream, Context context) throws IOException { String endpoint = "oss-cn-shanghai.aliyuncs.com"; String bucketName = "my-bucket"; Credentials creds = context.getExecutionCredentials(); OSSClient client = new OSSClient( endpoint, creds.getAccessKeyId(), creds.getAccessKeySecret(), creds.getSecurityToken()); client.putObject(bucketName, "my-object", new ByteArrayInputStream(new String("hello").getBytes())); outputStream.write(new String("done").getBytes()); } } 使用logging 用户的函数通过 context.getLogger() 打印的内容会被收集到用户在创建 Service 时指定的 LogStore 中: package example; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.StreamRequestHandler; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class HelloFC implements StreamRequestHandler { @Override public void handleRequest( InputStream inputStream, OutputStream outputStream, Context context) throws IOException { context.getLogger().info("hello world"); outputStream.write(new String("hello world").getBytes()); } } 上面的代码输出的日志内容是: message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [INFO] hello world 使用 context.getLogger().warn 和 context.getLogger().error 分别可以打包 WARN/ERROR 级别的日志。 使用自定义的模块 如果用户需要使用自定义的模块,则需要在打包 jar 时,将它们与代码一起打包。以下演示如何将 OSS Java SDK 打包到项目中。 在 pom.xml 中添加 OSS java SDK: com.aliyun.fc.runtime fc-java-core 1.2.1 com.aliyun.oss aliyun-sdk-oss 2.6.1 执行通用打包流程 请参考 Java 代码打包 错误处理 用户的函数在执行过程如果抛出异常,那么函数计算会把异常捕获并将异常信息返回。例如下面的代码: package example; import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.StreamRequestHandler; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class HelloFC implements StreamRequestHandler { @Override public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { throw new IOException("oops"); } } 调用时收到的响应为: invk hello-java -f /tmp/a.json { "errorMessage" : "oops", "errorType" : "java.io.IOException", "errorCause" : "oops", "stackTrace" : [ "example.HelloFC.handleRequest(HelloFC.java:15)" ] } Error: Request id: 45dd8d90-6b78-cce3-087c-8bf4ebc6c9af. Error type: UnhandledInvocationError 发生异常时,函数调用的响应的HTTP header中会包含X-Fc-Error-Type: UnhandledInvocationError。

1934890530796658 2020-03-27 16:27:27 0 浏览量 回答数 0

问题

Flink 的 Scala API 怎么指定 时间字段

冷丰 2019-12-01 19:39:10 819 浏览量 回答数 1

回答

RSA算法介绍及JAVA实现,其实java和c++差不多,参考一下吧 <一>基础 RSA算法非常简单,概述如下: 找两素数p和q 取n=p*q 取t=(p-1)*(q-1) 取任何一个数e,要求满足e<t并且e与t互素(就是最大公因数为1) 取d*e%t==1 这样最终得到三个数: n d e 设消息为数M (M <n) 设c=(M**d)%n就得到了加密后的消息c 设m=(c**e)%n则 m == M,从而完成对c的解密。 注:**表示次方,上面两式中的d和e可以互换。 在对称加密中: n d两个数构成公钥,可以告诉别人; n e两个数构成私钥,e自己保留,不让任何人知道。 给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。 别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。 rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解 从而在已知n d的情况下无法获得e;同样在已知n e的情况下无法 求得d。 <二>实践 接下来我们来一个实践,看看实际的操作: 找两个素数: p=47 q=59 这样 n=p*q=2773 t=(p-1)*(q-1)=2668 取e=63,满足e<t并且e和t互素 用perl简单穷举可以获得满主 e*d%t ==1的数d: C:\Temp>perl -e "foreach $i (1..9999){ print($i),last if $i*63%2668==1 }" 847 即d=847 最终我们获得关键的 n=2773 d=847 e=63 取消息M=244我们看看 加密: c=M**d%n = 244**847%2773 用perl的大数计算来算一下: C:\Temp>perl -Mbigint -e "print 244**847%2773" 465 即用d对M加密后获得加密信息c=465 解密: 我们可以用e来对加密后的c进行解密,还原M: m=c**e%n=465**63%2773 : C:\Temp>perl -Mbigint -e "print 465**63%2773" 244 即用e对c解密后获得m=244 , 该值和原始信息M相等。 <三>字符串加密 把上面的过程集成一下我们就能实现一个对字符串加密解密的示例了。 每次取字符串中的一个字符的ascii值作为M进行计算,其输出为加密后16进制 的数的字符串形式,按3字节表示,如01F 代码如下: #!/usr/bin/perl -w #RSA 计算过程学习程序编写的测试程序 #watercloud 2003-8-12 # use strict; use Math::BigInt; my %RSA_CORE = (n=>2773,e=>63,d=>847); #p=47,q=59 my $N=new Math::BigInt($RSA_CORE{n}); my $E=new Math::BigInt($RSA_CORE{e}); my $D=new Math::BigInt($RSA_CORE{d}); print "N=$N D=$D E=$E\n"; sub RSA_ENCRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$cmess); for($i=0;$i < length($$r_mess);$i++) { $c=ord(substr($$r_mess,$i,1)); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($D,$N); $c=sprintf "%03X",$C; $cmess.=$c; } return \$cmess; } sub RSA_DECRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$dmess); for($i=0;$i < length($$r_mess);$i+=3) { $c=substr($$r_mess,$i,3); $c=hex($c); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($E,$N); $c=chr($C); $dmess.=$c; } return \$dmess; } my $mess="RSA 娃哈哈哈~~~"; $mess=$ARGV[0] if @ARGV >= 1; print "原始串:",$mess,"\n"; my $r_cmess = RSA_ENCRYPT(\$mess); print "加密串:",$$r_cmess,"\n"; my $r_dmess = RSA_DECRYPT($r_cmess); print "解密串:",$$r_dmess,"\n"; #EOF 测试一下: C:\Temp>perl rsa-test.pl N=2773 D=847 E=63 原始串:RSA 娃哈哈哈~~~ 加密串:5CB6CD6BC58A7709470AA74A0AA74A0AA74A6C70A46C70A46C70A4 解密串:RSA 娃哈哈哈~~~ C:\Temp>perl rsa-test.pl 安全焦点(xfocus) N=2773 D=847 E=63 原始串:安全焦点(xfocus) 加密串:3393EC12F0A466E0AA9510D025D7BA0712DC3379F47D51C325D67B 解密串:安全焦点(xfocus) <四>提高 前面已经提到,rsa的安全来源于n足够大,我们测试中使用的n是非常小的,根本不能保障安全性, 我们可以通过RSAKit、RSATool之类的工具获得足够大的N 及D E。 通过工具,我们获得1024位的N及D E来测试一下: n=0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90B66EC3A85F5005D BDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF1538D4C2013433B383B 47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941D2ED173CCA50E114705D7E2 BC511951 d=0x10001 e=0xE760A3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C2995 4C5D86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF2 C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A592D2B 1965 设原始信息 M=0x11111111111122222222222233333333333 完成这么大数字的计算依赖于大数运算库,用perl来运算非常简单: A) 用d对M进行加密如下: c=M**d%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x11111111111122222222222233 333333333, 0x10001, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5F CD15F90B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F0 17F9CCF1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD6 0438941D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 即用d对M加密后信息为: c=0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 B) 用e对c进行解密如下: m=c**e%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x17b287be418c69ecd7c39227ab 681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd45692b007f3a2f7c5f5aa1d99ef3 866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b3028f9461a3b1533ec0cb4764414 65f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91f1834580c3f6d90898, 0xE760A 3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C29954C5D 86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF 2C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A 592D2B1965, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90 B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF 1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941 D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x11111111111122222222222233333333333 (我的P4 1.6G的机器上计算了约5秒钟) 得到用e解密后的m=0x11111111111122222222222233333333333 == M C) RSA通常的实现 RSA简洁幽雅,但计算速度比较慢,通常加密中并不是直接使用RSA 来对所有的信息进行加密, 最常见的情况是随机产生一个对称加密的密钥,然后使用对称加密算法对信息加密,之后用 RSA对刚才的加密密钥进行加密。 最后需要说明的是,当前小于1024位的N已经被证明是不安全的 自己使用中不要使用小于1024位的RSA,最好使用2048位的。 ---------------------------------------------------------- 一个简单的RSA算法实现JAVA源代码: filename:RSA.java /* * Created on Mar 3, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ import java.math.BigInteger; import java.io.InputStream; import java.io.OutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.FileWriter; import java.io.FileReader; import java.io.BufferedReader; import java.util.StringTokenizer; /** * @author Steve * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class RSA { /** * BigInteger.ZERO */ private static final BigInteger ZERO = BigInteger.ZERO; /** * BigInteger.ONE */ private static final BigInteger ONE = BigInteger.ONE; /** * Pseudo BigInteger.TWO */ private static final BigInteger TWO = new BigInteger("2"); private BigInteger myKey; private BigInteger myMod; private int blockSize; public RSA (BigInteger key, BigInteger n, int b) { myKey = key; myMod = n; blockSize = b; } public void encodeFile (String filename) { byte[] bytes = new byte[blockSize / 8 + 1]; byte[] temp; int tempLen; InputStream is = null; FileWriter writer = null; try { is = new FileInputStream(filename); writer = new FileWriter(filename + ".enc"); } catch (FileNotFoundException e1){ System.out.println("File not found: " + filename); } catch (IOException e1){ System.out.println("File not found: " + filename + ".enc"); } /** * Write encoded message to 'filename'.enc */ try { while ((tempLen = is.read(bytes, 1, blockSize / 8)) > 0) { for (int i = tempLen + 1; i < bytes.length; ++i) { bytes[i] = 0; } writer.write(encodeDecode(new BigInteger(bytes)) + " "); } } catch (IOException e1) { System.out.println("error writing to file"); } /** * Close input stream and file writer */ try { is.close(); writer.close(); } catch (IOException e1) { System.out.println("Error closing file."); } } public void decodeFile (String filename) { FileReader reader = null; OutputStream os = null; try { reader = new FileReader(filename); os = new FileOutputStream(filename.replaceAll(".enc", ".dec")); } catch (FileNotFoundException e1) { if (reader == null) System.out.println("File not found: " + filename); else System.out.println("File not found: " + filename.replaceAll(".enc", "dec")); } BufferedReader br = new BufferedReader(reader); int offset; byte[] temp, toFile; StringTokenizer st = null; try { while (br.ready()) { st = new StringTokenizer(br.readLine()); while (st.hasMoreTokens()){ toFile = encodeDecode(new BigInteger(st.nextToken())).toByteArray(); System.out.println(toFile.length + " x " + (blockSize / 8)); if (toFile[0] == 0 && toFile.length != (blockSize / 8)) { temp = new byte[blockSize / 8]; offset = temp.length - toFile.length; for (int i = toFile.length - 1; (i <= 0) && ((i + offset) <= 0); --i) { temp[i + offset] = toFile[i]; } toFile = temp; } /*if (toFile.length != ((blockSize / 8) + 1)){ temp = new byte[(blockSize / 8) + 1]; System.out.println(toFile.length + " x " + temp.length); for (int i = 1; i < temp.length; i++) { temp[i] = toFile[i - 1]; } toFile = temp; } else System.out.println(toFile.length + " " + ((blockSize / 8) + 1));*/ os.write(toFile); } } } catch (IOException e1) { System.out.println("Something went wrong"); } /** * close data streams */ try { os.close(); reader.close(); } catch (IOException e1) { System.out.println("Error closing file."); } } /** * Performs <tt>base</tt>^<sup><tt>pow</tt></sup> within the modular * domain of <tt>mod</tt>. * * @param base the base to be raised * @param pow the power to which the base will be raisded * @param mod the modular domain over which to perform this operation * @return <tt>base</tt>^<sup><tt>pow</tt></sup> within the modular * domain of <tt>mod</tt>. */ public BigInteger encodeDecode(BigInteger base) { BigInteger a = ONE; BigInteger s = base; BigInteger n = myKey; while (!n.equals(ZERO)) { if(!n.mod(TWO).equals(ZERO)) a = a.multiply(s).mod(myMod); s = s.pow(2).mod(myMod); n = n.divide(TWO); } return a; } }

管理贝贝 2019-12-02 01:26:59 0 浏览量 回答数 0

回答

RSA算法介绍及JAVA实现,其实java和c++差不多,参考一下吧 <一>基础 RSA算法非常简单,概述如下: 找两素数p和q 取n=p*q 取t=(p-1)*(q-1) 取任何一个数e,要求满足e<t并且e与t互素(就是最大公因数为1) 取d*e%t==1 这样最终得到三个数: n d e 设消息为数M (M <n) 设c=(M**d)%n就得到了加密后的消息c 设m=(c**e)%n则 m == M,从而完成对c的解密。 注:**表示次方,上面两式中的d和e可以互换。 在对称加密中: n d两个数构成公钥,可以告诉别人; n e两个数构成私钥,e自己保留,不让任何人知道。 给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。 别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。 rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解 从而在已知n d的情况下无法获得e;同样在已知n e的情况下无法 求得d。 <二>实践 接下来我们来一个实践,看看实际的操作: 找两个素数: p=47 q=59 这样 n=p*q=2773 t=(p-1)*(q-1)=2668 取e=63,满足e<t并且e和t互素 用perl简单穷举可以获得满主 e*d%t ==1的数d: C:\Temp>perl -e "foreach $i (1..9999){ print($i),last if $i*63%2668==1 }" 847 即d=847 最终我们获得关键的 n=2773 d=847 e=63 取消息M=244我们看看 加密: c=M**d%n = 244**847%2773 用perl的大数计算来算一下: C:\Temp>perl -Mbigint -e "print 244**847%2773" 465 即用d对M加密后获得加密信息c=465 解密: 我们可以用e来对加密后的c进行解密,还原M: m=c**e%n=465**63%2773 : C:\Temp>perl -Mbigint -e "print 465**63%2773" 244 即用e对c解密后获得m=244 , 该值和原始信息M相等。 <三>字符串加密 把上面的过程集成一下我们就能实现一个对字符串加密解密的示例了。 每次取字符串中的一个字符的ascii值作为M进行计算,其输出为加密后16进制 的数的字符串形式,按3字节表示,如01F 代码如下: #!/usr/bin/perl -w #RSA 计算过程学习程序编写的测试程序 #watercloud 2003-8-12 # use strict; use Math::BigInt; my %RSA_CORE = (n=>2773,e=>63,d=>847); #p=47,q=59 my $N=new Math::BigInt($RSA_CORE{n}); my $E=new Math::BigInt($RSA_CORE{e}); my $D=new Math::BigInt($RSA_CORE{d}); print "N=$N D=$D E=$E\n"; sub RSA_ENCRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$cmess); for($i=0;$i < length($$r_mess);$i++) { $c=ord(substr($$r_mess,$i,1)); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($D,$N); $c=sprintf "%03X",$C; $cmess.=$c; } return \$cmess; } sub RSA_DECRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$dmess); for($i=0;$i < length($$r_mess);$i+=3) { $c=substr($$r_mess,$i,3); $c=hex($c); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($E,$N); $c=chr($C); $dmess.=$c; } return \$dmess; } my $mess="RSA 娃哈哈哈~~~"; $mess=$ARGV[0] if @ARGV >= 1; print "原始串:",$mess,"\n"; my $r_cmess = RSA_ENCRYPT(\$mess); print "加密串:",$$r_cmess,"\n"; my $r_dmess = RSA_DECRYPT($r_cmess); print "解密串:",$$r_dmess,"\n"; #EOF 测试一下: C:\Temp>perl rsa-test.pl N=2773 D=847 E=63 原始串:RSA 娃哈哈哈~~~ 加密串:5CB6CD6BC58A7709470AA74A0AA74A0AA74A6C70A46C70A46C70A4 解密串:RSA 娃哈哈哈~~~ C:\Temp>perl rsa-test.pl 安全焦点(xfocus) N=2773 D=847 E=63 原始串:安全焦点(xfocus) 加密串:3393EC12F0A466E0AA9510D025D7BA0712DC3379F47D51C325D67B 解密串:安全焦点(xfocus) <四>提高 前面已经提到,rsa的安全来源于n足够大,我们测试中使用的n是非常小的,根本不能保障安全性, 我们可以通过RSAKit、RSATool之类的工具获得足够大的N 及D E。 通过工具,我们获得1024位的N及D E来测试一下: n=0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90B66EC3A85F5005D BDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF1538D4C2013433B383B 47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941D2ED173CCA50E114705D7E2 BC511951 d=0x10001 e=0xE760A3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C2995 4C5D86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF2 C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A592D2B 1965 设原始信息 M=0x11111111111122222222222233333333333 完成这么大数字的计算依赖于大数运算库,用perl来运算非常简单: A) 用d对M进行加密如下: c=M**d%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x11111111111122222222222233 333333333, 0x10001, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5F CD15F90B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F0 17F9CCF1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD6 0438941D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 即用d对M加密后信息为: c=0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 B) 用e对c进行解密如下: m=c**e%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x17b287be418c69ecd7c39227ab 681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd45692b007f3a2f7c5f5aa1d99ef3 866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b3028f9461a3b1533ec0cb4764414 65f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91f1834580c3f6d90898, 0xE760A 3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C29954C5D 86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF 2C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A 592D2B1965, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90 B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF 1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941 D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x11111111111122222222222233333333333 (我的P4 1.6G的机器上计算了约5秒钟) 得到用e解密后的m=0x11111111111122222222222233333333333 == M C) RSA通常的实现 RSA简洁幽雅,但计算速度比较慢,通常加密中并不是直接使用RSA 来对所有的信息进行加密, 最常见的情况是随机产生一个对称加密的密钥,然后使用对称加密算法对信息加密,之后用 RSA对刚才的加密密钥进行加密。 最后需要说明的是,当前小于1024位的N已经被证明是不安全的 自己使用中不要使用小于1024位的RSA,最好使用2048位的。 ---------------------------------------------------------- 一个简单的RSA算法实现JAVA源代码: filename:RSA.java /* * Created on Mar 3, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ import java.math.BigInteger; import java.io.InputStream; import java.io.OutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.FileWriter; import java.io.FileReader; import java.io.BufferedReader; import java.util.StringTokenizer; /** * @author Steve * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class RSA { /** * BigInteger.ZERO */ private static final BigInteger ZERO = BigInteger.ZERO; /** * BigInteger.ONE */ private static final BigInteger ONE = BigInteger.ONE; /** * Pseudo BigInteger.TWO */ private static final BigInteger TWO = new BigInteger("2"); private BigInteger myKey; private BigInteger myMod; private int blockSize; public RSA (BigInteger key, BigInteger n, int b) { myKey = key; myMod = n; blockSize = b; } public void encodeFile (String filename) { byte[] bytes = new byte[blockSize / 8 + 1]; byte[] temp; int tempLen; InputStream is = null; FileWriter writer = null; try { is = new FileInputStream(filename); writer = new FileWriter(filename + ".enc"); } catch (FileNotFoundException e1){ System.out.println("File not found: " + filename); } catch (IOException e1){ System.out.println("File not found: " + filename + ".enc"); } /** * Write encoded message to 'filename'.enc */ try { while ((tempLen = is.read(bytes, 1, blockSize / 8)) > 0) { for (int i = tempLen + 1; i < bytes.length; ++i) { bytes[i] = 0; } writer.write(encodeDecode(new BigInteger(bytes)) + " "); } } catch (IOException e1) { System.out.println("error writing to file"); } /** * Close input stream and file writer */ try { is.close(); writer.close(); } catch (IOException e1) { System.out.println("Error closing file."); } } public void decodeFile (String filename) { FileReader reader = null; OutputStream os = null; try { reader = new FileReader(filename); os = new FileOutputStream(filename.replaceAll(".enc", ".dec")); } catch (FileNotFoundException e1) { if (reader == null) System.out.println("File not found: " + filename); else System.out.println("File not found: " + filename.replaceAll(".enc", "dec")); } BufferedReader br = new BufferedReader(reader); int offset; byte[] temp, toFile; StringTokenizer st = null; try { while (br.ready()) { st = new StringTokenizer(br.readLine()); while (st.hasMoreTokens()){ toFile = encodeDecode(new BigInteger(st.nextToken())).toByteArray(); System.out.println(toFile.length + " x " + (blockSize / 8)); if (toFile[0] == 0 && toFile.length != (blockSize / 8)) { temp = new byte[blockSize / 8]; offset = temp.length - toFile.length; for (int i = toFile.length - 1; (i <= 0) && ((i + offset) <= 0); --i) { temp[i + offset] = toFile[i]; } toFile = temp; } /*if (toFile.length != ((blockSize / 8) + 1)){ temp = new byte[(blockSize / 8) + 1]; System.out.println(toFile.length + " x " + temp.length); for (int i = 1; i < temp.length; i++) { temp[i] = toFile[i - 1]; } toFile = temp; } else System.out.println(toFile.length + " " + ((blockSize / 8) + 1));*/ os.write(toFile); } } } catch (IOException e1) { System.out.println("Something went wrong"); } /** * close data streams */ try { os.close(); reader.close(); } catch (IOException e1) { System.out.println("Error closing file."); } } /** * Performs <tt>base</tt>^<sup><tt>pow</tt></sup> within the modular * domain of <tt>mod</tt>. * * @param base the base to be raised * @param pow the power to which the base will be raisded * @param mod the modular domain over which to perform this operation * @return <tt>base</tt>^<sup><tt>pow</tt></sup> within the modular * domain of <tt>mod</tt>. */ public BigInteger encodeDecode(BigInteger base) { BigInteger a = ONE; BigInteger s = base; BigInteger n = myKey; while (!n.equals(ZERO)) { if(!n.mod(TWO).equals(ZERO)) a = a.multiply(s).mod(myMod); s = s.pow(2).mod(myMod); n = n.divide(TWO); } return a; } }

马铭芳 2019-12-02 01:26:27 0 浏览量 回答数 0

问题

FlashBuilder启动报错?报错

爱吃鱼的程序员 2020-06-10 10:51:57 0 浏览量 回答数 1

回答

RSA算法非常简单,概述如下: 找两素数p和q 取n=p*q 取t=(p-1)*(q-1) 取任何一个数e,要求满足e<t并且e与t互素(就是最大公因数为1) 取d*e%t==1 这样最终得到三个数: n d e 设消息为数M (M <n) 设c=(M**d)%n就得到了加密后的消息c 设m=(c**e)%n则 m == M,从而完成对c的解密。 注:**表示次方,上面两式中的d和e可以互换。 在对称加密中: n d两个数构成公钥,可以告诉别人; n e两个数构成私钥,e自己保留,不让任何人知道。 给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。 别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。 rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解 从而在已知n d的情况下无法获得e;同样在已知n e的情况下无法 求得d。 <二>实践 接下来我们来一个实践,看看实际的操作: 找两个素数: p=47 q=59 这样 n=p*q=2773 t=(p-1)*(q-1)=2668 取e=63,满足e<t并且e和t互素 用perl简单穷举可以获得满主 e*d%t ==1的数d: C:\Temp>perl -e "foreach $i (1..9999){ print($i),last if $i*63%2668==1 }" 847 即d=847 最终我们获得关键的 n=2773 d=847 e=63 取消息M=244我们看看 加密: c=M**d%n = 244**847%2773 用perl的大数计算来算一下: C:\Temp>perl -Mbigint -e "print 244**847%2773" 465 即用d对M加密后获得加密信息c=465 解密: 我们可以用e来对加密后的c进行解密,还原M: m=c**e%n=465**63%2773 : C:\Temp>perl -Mbigint -e "print 465**63%2773" 244 即用e对c解密后获得m=244 , 该值和原始信息M相等。 <三>字符串加密 把上面的过程集成一下我们就能实现一个对字符串加密解密的示例了。 每次取字符串中的一个字符的ascii值作为M进行计算,其输出为加密后16进制 的数的字符串形式,按3字节表示,如01F 代码如下: #!/usr/bin/perl -w #RSA 计算过程学习程序编写的测试程序 #watercloud 2003-8-12 # use strict; use Math::BigInt; my %RSA_CORE = (n=>2773,e=>63,d=>847); #p=47,q=59 my $N=new Math::BigInt($RSA_CORE{n}); my $E=new Math::BigInt($RSA_CORE{e}); my $D=new Math::BigInt($RSA_CORE{d}); print "N=$N D=$D E=$E\n"; sub RSA_ENCRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$cmess); for($i=0;$i < length($$r_mess);$i++) { $c=ord(substr($$r_mess,$i,1)); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($D,$N); $c=sprintf "%03X",$C; $cmess.=$c; } return \$cmess; } sub RSA_DECRYPT { my $r_mess = shift @_; my ($c,$i,$M,$C,$dmess); for($i=0;$i < length($$r_mess);$i+=3) { $c=substr($$r_mess,$i,3); $c=hex($c); $M=Math::BigInt->new($c); $C=$M->copy(); $C->bmodpow($E,$N); $c=chr($C); $dmess.=$c; } return \$dmess; } my $mess="RSA 娃哈哈哈~~~"; $mess=$ARGV[0] if @ARGV >= 1; print "原始串:",$mess,"\n"; my $r_cmess = RSA_ENCRYPT(\$mess); print "加密串:",$$r_cmess,"\n"; my $r_dmess = RSA_DECRYPT($r_cmess); print "解密串:",$$r_dmess,"\n"; #EOF 测试一下: C:\Temp>perl rsa-test.pl N=2773 D=847 E=63 原始串:RSA 娃哈哈哈~~~ 加密串:5CB6CD6BC58A7709470AA74A0AA74A0AA74A6C70A46C70A46C70A4 解密串:RSA 娃哈哈哈~~~ C:\Temp>perl rsa-test.pl 安全焦点(xfocus) N=2773 D=847 E=63 原始串:安全焦点(xfocus) 加密串:3393EC12F0A466E0AA9510D025D7BA0712DC3379F47D51C325D67B 解密串:安全焦点(xfocus) <四>提高 前面已经提到,rsa的安全来源于n足够大,我们测试中使用的n是非常小的,根本不能保障安全性, 我们可以通过RSAKit、RSATool之类的工具获得足够大的N 及D E。 通过工具,我们获得1024位的N及D E来测试一下: n=0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90B66EC3A85F5005D BDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF1538D4C2013433B383B 47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941D2ED173CCA50E114705D7E2 BC511951 d=0x10001 e=0xE760A3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C2995 4C5D86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF2 C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A592D2B 1965 设原始信息 M=0x11111111111122222222222233333333333 完成这么大数字的计算依赖于大数运算库,用perl来运算非常简单: A) 用d对M进行加密如下: c=M**d%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x11111111111122222222222233 333333333, 0x10001, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5F CD15F90B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F0 17F9CCF1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD6 0438941D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 即用d对M加密后信息为: c=0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd 45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b 3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91 f1834580c3f6d90898 B) 用e对c进行解密如下: m=c**e%n : C:\Temp>perl -Mbigint -e " $x=Math::BigInt->bmodpow(0x17b287be418c69ecd7c39227ab 681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd45692b007f3a2f7c5f5aa1d99ef3 866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b3028f9461a3b1533ec0cb4764414 65f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91f1834580c3f6d90898, 0xE760A 3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C29954C5D 86B36E943080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF 2C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A 592D2B1965, 0x328C74784DF31119C526D18098EBEBB943B0032B599CEE13CC2BCE7B5FCD15F90 B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F017F9CCF 1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941 D2ED173CCA50E114705D7E2BC511951);print $x->as_hex" 0x11111111111122222222222233333333333 (我的P4 1.6G的机器上计算了约5秒钟) 得到用e解密后的m=0x11111111111122222222222233333333333 == M C) RSA通常的实现 RSA简洁幽雅,但计算速度比较慢,通常加密中并不是直接使用RSA 来对所有的信息进行加密, 最常见的情况是随机产生一个对称加密的密钥,然后使用对称加密算法对信息加密,之后用 RSA对刚才的加密密钥进行加密。 最后需要说明的是,当前小于1024位的N已经被证明是不安全的 自己使用中不要使用小于1024位的RSA,最好使用2048位的。 ---------------------------------------------------------- 一个简单的RSA算法实现JAVA源代码: filename:RSA.java /* * Created on Mar 3, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ import java.math.BigInteger; import java.io.InputStream; import java.io.OutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.FileWriter; import java.io.FileReader; import java.io.BufferedReader; import java.util.StringTokenizer; /** * @author Steve * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class RSA { /** * BigInteger.ZERO */ private static final BigInteger ZERO = BigInteger.ZERO; /** * BigInteger.ONE */ private static final BigInteger ONE = BigInteger.ONE; /** * Pseudo BigInteger.TWO */ private static final BigInteger TWO = new BigInteger("2"); private BigInteger myKey; private BigInteger myMod; private int blockSize; public RSA (BigInteger key, BigInteger n, int b) { myKey = key; myMod = n; blockSize = b; } public void encodeFile (String filename) { byte[] bytes = new byte[blockSize / 8 + 1]; byte[] temp; int tempLen; InputStream is = null; FileWriter writer = null; try { is = new FileInputStream(filename); writer = new FileWriter(filename + ".enc"); } catch (FileNotFoundException e1){ System.out.println("File not found: " + filename); } catch (IOException e1){ System.out.println("File not found: " + filename + ".enc"); } /** * Write encoded message to 'filename'.enc */ try { while ((tempLen = is.read(bytes, 1, blockSize / 8)) > 0) { for (int i = tempLen + 1; i < bytes.length; ++i) { bytes[i] = 0; } writer.write(encodeDecode(new BigInteger(bytes)) + " "); } } catch (IOException e1) { System.out.println("error writing to file"); } /** * Close input stream and file writer */ try { is.close(); writer.close(); } catch (IOException e1) { System.out.println("Error closing file."); } } public void decodeFile (String filename) { FileReader reader = null; OutputStream os = null; try { reader = new FileReader(filename); os = new FileOutputStream(filename.replaceAll(".enc", ".dec")); } catch (FileNotFoundException e1) { if (reader == null) System.out.println("File not found: " + filename); else System.out.println("File not found: " + filename.replaceAll(".enc", "dec")); } BufferedReader br = new BufferedReader(reader); int offset; byte[] temp, toFile; StringTokenizer st = null; try { while (br.ready()) { st = new StringTokenizer(br.readLine()); while (st.hasMoreTokens()){ toFile = encodeDecode(new BigInteger(st.nextToken())).toByteArray(); System.out.println(toFile.length + " x " + (blockSize / 8)); if (toFile[0] == 0 && toFile.length != (blockSize / 8)) { temp = new byte[blockSize / 8]; offset = temp.length - toFile.length; for (int i = toFile.length - 1; (i <= 0) && ((i + offset) <= 0); --i) { temp[i + offset] = toFile[i]; } toFile = temp; } /*if (toFile.length != ((blockSize / 8) + 1)){ temp = new byte[(blockSize / 8) + 1]; System.out.println(toFile.length + " x " + temp.length); for (int i = 1; i < temp.length; i++) { temp[i] = toFile[i - 1]; } toFile = temp; } else System.out.println(toFile.length + " " + ((blockSize / 8) + 1));*/ os.write(toFile); } } } catch (IOException e1) { System.out.println("Something went wrong"); } /** * close data streams */ try { os.close(); reader.close(); } catch (IOException e1) { System.out.println("Error closing file."); } } /** * Performs <tt>base</tt>^<sup><tt>pow</tt></sup> within the modular * domain of <tt>mod</tt>. * * @param base the base to be raised * @param pow the power to which the base will be raisded * @param mod the modular domain over which to perform this operation * @return <tt>base</tt>^<sup><tt>pow</tt></sup> within the modular * domain of <tt>mod</tt>. */ public BigInteger encodeDecode(BigInteger base) { BigInteger a = ONE; BigInteger s = base; BigInteger n = myKey; while (!n.equals(ZERO)) { if(!n.mod(TWO).equals(ZERO)) a = a.multiply(s).mod(myMod); s = s.pow(2).mod(myMod); n = n.divide(TWO); } return a; } } 在这里提供两个版本的RSA算法JAVA实现的代码下载: 1. 来自于 http://www.javafr.com/code.aspx?ID=27020 的RSA算法实现源代码包: http://zeal.newmenbase.net/attachment/JavaFR_RSA_Source.rar 2. 来自于 http://www.ferrara.linux.it/Members/lucabariani/RSA/implementazioneRsa/ 的实现: http://zeal.newmenbase.net/attachment/sorgentiJava.tar.gz - 源代码包 http://zeal.newmenbase.net/attachment/algoritmoRSA.jar - 编译好的jar包 另外关于RSA算法的php实现请参见文章: php下的RSA算法实现 关于使用VB实现RSA算法的源代码下载(此程序采用了psc1算法来实现快速的RSA加密): http://zeal.newmenbase.net/attachment/vb_PSC1_RSA.rar RSA加密的JavaScript实现: http://www.ohdave.com/rsa/ 参考资料:http://www.lenovonet.com/product/showarticle.asp?id=118

琴瑟 2019-12-02 01:27:17 0 浏览量 回答数 0

问题

压力测试数据share

aladdinzhao 2019-12-01 21:28:12 8400 浏览量 回答数 2

问题

CloudFoundry连接Mysql数据库出现的问题

落地花开啦 2019-12-01 19:52:51 1464 浏览量 回答数 1

问题

Jfinal与jetty作为基础开发,运行在安装的tomcat中报错【不是jar?报错

爱吃鱼的程序员 2020-06-14 17:24:51 0 浏览量 回答数 1
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站