• 关于

    随机加密程序的实现方法

    的搜索结果

问题

怎么保障iSCSI存储连接?

     iSCSI还得益于其硬件选择。在大多数情况下,周围同样的以太电缆和网络设备可以用来顺利传送iSCSI流量。   由于所有这些都适用于它,把服务器连接到存储系统的iSCSI协议似乎是跨IT环境的首要选择。...
elainebo 2019-12-01 21:04:12 7482 浏览量 回答数 0

问题

Java 序列化的高级认识 热:报错

简介: 如果你只知道实现 Serializable 接口的对象,可以序列化为本地文件。那你最好再阅读该篇文章,文章对序列化进行了更深一步的讨论,用实际的例子代码讲述了序列化的高级认识&...
kun坤 2020-06-07 21:41:37 0 浏览量 回答数 1

问题

PPVOD云转码系统

PPVOD云转码系统     在三网融合的环境下,一云多屏正在成为视频行业重点布局的发展方向,以用户为核心,在包括移动终端在内的多种终端之间形成无缝的视频资讯传递、互动和可定制的统一服务&#x...
云转码 2019-12-01 21:29:57 3830 浏览量 回答数 0

回答

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

回答

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

回答

选择一门编程语言,例如C之类的。如果不想学编程,就尝试下Excel里面的公式。-------------------------算法的定义 算法(Algorithm)是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。 算法可以理解为有基本运算及规定的运算顺序所构成的完整的解题步骤。或者看成按照要求设计好的有限的确切的计算序列,并且这样的步骤和序列可以解决一类问题。 一个算法应该具有以下五个重要的特征: 1、有穷性: 一个算法必须保证执行有限步之后结束; 2、确切性: 算法的每一步骤必须有确切的定义; 3、输入:一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定除了初始条件; 4、输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的; 5、可行性: 算法原则上能够精确地运行,而且人们用笔和纸做有限次运算后即可完成。 计算机科学家尼克劳斯-沃思曾著过一本著名的书《数据结构十算法= 程序》,可见算法在计算机科学界与计算机应用界的地位。 [编辑本段]算法的复杂度 同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。一个算法的评价主要从时间复杂度和空间复杂度来考虑。 时间复杂度 算法的时间复杂度是指算法需要消耗的时间资源。一般来说,计算机算法是问题规模n 的函数f(n),算法的时间复杂度也因此记做 T(n)=Ο(f(n)) 因此,问题的规模n 越大,算法执行的时间的增长率与f(n) 的增长率正相关,称作渐进时间复杂度(Asymptotic Time Complexity)。 空间复杂度 算法的空间复杂度是指算法需要消耗的空间资源。其计算和表示方法与时间复杂度类似,一般都用复杂度的渐近性来表示。同时间复杂度相比,空间复杂度的分析要简单得多。 详见百度百科词条"算法复杂度" [编辑本段]算法设计与分析的基本方法 1.递推法 递推法是利用问题本身所具有的一种递推关系求问题解的一种方法。它把问题分成若干步,找出相邻几步的关系,从而达到目的,此方法称为递推法。 2.递归 递归指的是一个过程:函数不断引用自身,直到引用的对象已知 3.穷举搜索法 穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从众找出那些符合要求的候选解作为问题的解。 4.贪婪法 贪婪法是一种不追求最优解,只希望得到较为满意解的方法。贪婪法一般可以快速得到满意的解,因为它省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪婪法常以当前情况为基础作最优选择,而不考虑各种可能的整体情况,所以贪婪法不要回溯。 5.分治法 把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。 6.动态规划法 动态规划是一种在数学和计算机科学中使用的,用于求解包含重叠子问题的最优化问题的方法。其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。动态规划的思想是多种算法的基础,被广泛应用于计算机科学和工程领域。 7.迭代法 迭代是数值分析中通过从一个初始估计出发寻找一系列近似解来解决问题(一般是解方程或者方程组)的过程,为实现这一过程所使用的方法统称为迭代法。 [编辑本段]算法分类 算法可大致分为基本算法、数据结构的算法、数论与代数算法、计算几何的算法、图论的算法、动态规划以及数值分析、加密算法、排序算法、检索算法、随机化算法、并行算法。 算法可以宏泛的分为三类: 有限的,确定性算法 这类算法在有限的一段时间内终止。他们可能要花很长时间来执行指定的任务,但仍将在一定的时间内终止。这类算法得出的结果常取决于输入值。 有限的,非确定算法 这类算法在有限的时间内终止。然而,对于一个(或一些)给定的数值,算法的结果并不是唯一的或确定的。 无限的算法 是那些由于没有定义终止定义条件,或定义的条件无法由输入的数据满足而不终止运行的算法。通常,无限算法的产生是由于未能确定的定义终止条件。 [编辑本段]举例 经典的算法有很多,如:"欧几里德算法,割圆术,秦九韶算法"。 [编辑本段]算法经典专著 目前市面上有许多论述算法的书籍,其中最著名的便是《计算机程序设计艺术》(The Art Of Computer Programming) 以及《算法导论》(Introduction To Algorithms)。 [编辑本段]算法的历史 “算法”即演算法的大陆中文名称出自《周髀算经》;而英文名称Algorithm 来自于9世纪波斯数学家al-Khwarizmi,因为al-Khwarizmi在数学上提出了算法这个概念。“算法”原为"algorism",意思是阿拉伯数字的运算法则,在18世纪演变为"algorithm"。欧几里得算法被人们认为是史上第一个算法。 第一次编写程序是Ada Byron于1842年为巴贝奇分析机编写求解解伯努利方程的程序,因此Ada Byron被大多数人认为是世界上第一位程序员。因为查尔斯·巴贝奇(Charles Babbage)未能完成他的巴贝奇分析机,这个算法未能在巴贝奇分析机上执行。 因为"well-defined procedure"缺少数学上精确的定义,19世纪和20世纪早期的数学家、逻辑学家在定义算法上出现了困难。20世纪的英国数学家图灵提出了著名的图灵论题,并提出一种假想的计算机的抽象模型,这个模型被称为图灵机。图灵机的出现解决了算法定义的难题,图灵的思想对算法的发展起到了重要作用的。
马铭芳 2019-12-02 01:19:58 0 浏览量 回答数 0

回答

<p>//这是调用的测试程序:</p> public static void test(){         //加密内容         String source = "加密加密加12abc";         //加密密钥         String key = "chiscdc_fsws_@%^";         String encrypt = EncryptUtil.encryptByKey(source,key);         System.out.println("加密后:"+encrypt);         String decrypt = EncryptUtil.decryptByKey(encrypt,key);         System.out.println("解密后:"+decrypt);     }      //这是 EncryptUtil : import java.io.UnsupportedEncodingException; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.xml.transform.Source; public class EncryptUtil {    /**     * 密钥算法     */    private static final String ALGORITHM = "DES";    /**     * 加解密算法/工作模式/填充方式     */    private static final String ALGORITHM_STR = "DES/ECB/NoPadding";    private static final String CHARSET = "UTF-8";        /**     * 填充内容     */    private static final String PAD_STR = "\0";    /**     * <p>方法描述:根据自己的密钥实现des加密</p>     *     * @MethodAuthor yzd, 2018/7/23,encryptByKey     *     */     public static String encryptByKey(String souce, String key) {         try {             return encryptByDes(pkcs5Pad(souce), pkcs5Pad(key));         } catch (Exception e) {             e.printStackTrace();             return null;         }     }    /**     * <p>方法描述:根据密钥解密</p>     *     * @MethodAuthor yzd, 2018/7/23,decryptByKey     *     */     public static String decryptByKey(String souceString,String key) {         try {             byte [] source = hexStringToBytes(souceString);             return decryptByDes(source, pkcs5Pad(key)).trim();         } catch (Exception e) {             e.printStackTrace();             return null;         }     }     /**      * <p>方法描述:正式加密操作</p>      *      * @MethodAuthor yzd, 2018/7/23,decryptByKey      *      */    private static String encryptByDes( byte[] souce, byte[] bs)          throws Exception {       // DES算法要求有一个可信任的随机数源       SecureRandom sr = new SecureRandom();       // 从原始密匙数据创建DESKeySpec对象       DESKeySpec dks = new DESKeySpec(bs);       // 创建一个密匙工厂,然后用它把DESKeySpec转换成 一个SecretKey对象       SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);       SecretKey key1 = keyFactory.generateSecret(dks);       // Cipher对象实际完成加密操作       Cipher cipher = Cipher.getInstance(ALGORITHM_STR);       // 用密匙初始化Cipher对象       cipher.init(Cipher.ENCRYPT_MODE, key1, sr);       // 现在,获取数据并加密       byte encryptedData[] = cipher.doFinal(souce);       return byteArr2HexStr(encryptedData);    }    public static String byteArr2HexStr(byte[] arrB) {       int iLen = arrB.length;       // 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍       StringBuffer sb = new StringBuffer(iLen * 2);       for (int i = 0; i < iLen; i++) {          int intTmp = arrB[i];          // 把负数转换为正数          while (intTmp < 0) {             intTmp = intTmp + 256;          }          // 小于0F的数需要在前面补0          if (intTmp < 16) {             sb.append("0");          }          sb.append(Integer.toString(intTmp, 16));       }       return sb.toString();    }    public static byte[] hexStringToBytes(String hexString) {         if (hexString == null) {             return null;         }        if (hexString.length() <= 0){            return new byte[0];        }         hexString = hexString.toUpperCase();         int length = hexString.length() / 2;         char[] hexChars = hexString.toCharArray();         byte[] result = new byte[length];         for (int i = 0; i < length; i++) {             int step = i * 2;             result[i] = (byte) (charToByte(hexChars[step]) << 4 | charToByte(hexChars[step + 1]));         }         return result;     }    private static final String HEX_STRING_MAPPING = "0123456789ABCDEF";    private static byte charToByte(char c) {         return (byte) HEX_STRING_MAPPING.indexOf(c);     }        private static String decryptByDes(byte[] souce, byte[] bs)          throws Exception {       // DES算法要求有一个可信任的随机数源       SecureRandom sr = new SecureRandom();       // 从原始密匙数据创建DESKeySpec对象       DESKeySpec dks = new DESKeySpec(bs);       // 创建一个密匙工厂,然后用它把DESKeySpec转换成 一个SecretKey对象       SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);       SecretKey key1 = keyFactory.generateSecret(dks);       // Cipher对象实际完成加密操作       Cipher cipher = Cipher.getInstance(ALGORITHM_STR);       // 用密匙初始化Cipher对象       cipher.init(Cipher.DECRYPT_MODE, key1, sr);       // 将加密报文用BASE64算法转化为字节数组       byte[] encryptedData =souce;       // 用DES算法解密报文       byte decryptedData[] = cipher.doFinal(encryptedData);       return new String(decryptedData, CHARSET);    }    public static byte[] hexStr2ByteArr(byte[] byIn) throws Exception {       byte[] arrB = byIn;       int iLen = arrB.length;       // 两个字符表示一个字节,所以字节数组长度是字符串长度除以2       byte[] arrOut = new byte[iLen / 2];       for (int i = 0; i < iLen; i = i + 2) {          String strTmp = new String(arrB, i, 2);          arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);       }       return arrOut;    }    /**     * <p>方法描述:不足8的倍数,后面追加空格</p>     *     * @MethodAuthor yzd, 2018/7/27,pkcs5Pad     *     */    private static byte[] pkcs5Pad(final String inSouce) {         byte[] bySource = new byte[0];         try {             bySource = inSouce.getBytes(CHARSET);             // 密文和密钥的长度必须是8的倍数             if (0 == bySource.length % 8) {                 return bySource;             }         } catch (UnsupportedEncodingException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }         int length = bySource.length;         int nPaddedLength = (length / 8 + 1) * 8;         byte[] byReturn = new byte[nPaddedLength];         System.arraycopy(bySource, 0, byReturn, 0, length);         int i = length;         while (i < nPaddedLength) {             byReturn[i] = (byte) (nPaddedLength - length);             i++;         }         return byReturn;     } }   原因在于: 输入的原文必须是BYTE数据,汉字的话,使用UTF-8获取其BYTE值。 DES加密时,是需要按分组长度为8字节补齐的。   大神 小弟不才 请问 result[i] = (byte) (charToByte(hexChars[step]) << 4 | charToByte(hexChars[step + 1])); 这段是做什么的? 卧槽 可以的 大神大神 膜拜一下 谢了~ <p>UTF-8</p> <p>另外, 原代码中的pkcs5Pad的补码方式是不对的。 请参考 https://blog.csdn.net/stewart/article/details/52462273</p> <p>不用楼上说的那么麻烦直接将这行代码</p> private static final String ALGORITHM_STR = "DES/ECB/NoPadding" 改为 public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding "; 即可 错误原因: DES、AES 或者 3DES 属于块加密算法,一般来说原文必须是 8 的整数倍,所以块加密算法除子加密模式之外,还涉及到一个填充模式。 如果一定要用 NoPadding 的话,那么必须保证原文字节是 8 的倍数,否则的话需要使用其他的填充模式。 在 Sun JCE 中默认的填充模式除了 NoPadding 之外,还有: PKCS5Padding 和 ISO10126Padding PKCS5Padding 的填充规则是: 填充至符合块大小的整数倍,填充值为填充数量数。例如: 原始:FF FF FF FF FF FF FF FF FF 填充:FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07 ISO10126Padding 的填充规则是: 填充至符合块大小的整数倍,填充值最后一个字节为填充的数量数,其他字节随机处理。例如: 原始:FF FF FF FF FF FF FF FF FF 填充:FF FF FF FF FF FF FF FF FF 3F 7A B4 09 14 36 07 使用填充模式后原文字节并不需要是 8 的整数倍,采用填充模式之后,块加密的密文长度为: (N / 8 * 8) + 8 如上,假如原文长度为 15 个字节,密文长度就是 16 个字节。假如原文长度为 16 个字节,密文长度就为 24 个字节。也就是说,采用填充模式后必须进行填充,哪怕是 8 的整数倍。 厉害了 都是大神啊 <div class='ref'><h4>引用来自“melon_jj”的评论</h4><p>不用楼上说的那么麻烦直接将这行代码</p> private static final String ALGORITHM_STR = "DES/ECB/NoPadding" 改为 public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding "; 即可 错误原因: DES、AES 或者 3DES 属于块加密算法,一般来说原文必须是 8 的整数倍,所以块加密算法除子加密模式之外,还涉及到一个填充模式。 如果一定要用 NoPadding 的话,那么必须保证原文字节是 8 的倍数,否则的话需要使用其他的填充模式。 在 Sun JCE 中默认的填充模式除了 NoPadding 之外,还有: PKCS5Padding 和 ISO10126Padding PKCS5Padding 的填充规则是: 填充至符合块大小的整数倍,填充值为填充数量数。例如: 原始:FF FF FF FF FF FF FF FF FF 填充:FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07 ISO10126Padding 的填充规则是: 填充至符合块大小的整数倍,填充值最后一个字节为填充的数量数,其他字节随机处理。例如: 原始:FF FF FF FF FF FF FF FF FF 填充:FF FF FF FF FF FF FF FF FF 3F 7A B4 09 14 36 07 使用填充模式后原文字节并不需要是 8 的整数倍,采用填充模式之后,块加密的密文长度为: (N / 8 * 8) + 8 如上,假如原文长度为 15 个字节,密文长度就是 16 个字节。假如原文长度为 16 个字节,密文长度就为 24 个字节。也就是说,采用填充模式后必须进行填充,哪怕是 8 的整数倍。 回复 <a class="referer" target="_blank">@Jordan裔</a> : 需要交流学习的话可以加群826183079 回复 <a class="referer" target="_blank">@Jordan裔</a> : 好吧 实在不好意思 我也想给你采纳 可是在你回答之前 我已经给楼上的哥们采纳过了 不能重复采纳了
爱吃鱼的程序员 2020-06-08 11:21:39 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: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

回答

Spring Cloud 学习笔记(一)——入门、特征、配置 0 放在前面 0.1 参考文档 http://cloud.spring.io/spring-cloud-static/Brixton.SR7/ https://springcloud.cc/ http://projects.spring.io/spring-cloud/ 0.2 maven配置 org.springframework.boot spring-boot-starter-parent 1.5.2.RELEASE org.springframework.cloud spring-cloud-dependencies Dalston.RELEASE pom import org.springframework.cloud spring-cloud-starter-config org.springframework.cloud spring-cloud-starter-eureka 0.3 简介 Spring Cloud为开发人员提供了快速构建分布式系统中的一些通用模式(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式 会话,群集状态)。 分布式系统的协调引出样板模式(boiler plate patterns),并且使用Spring Cloud开发人员可以快速地实现这些模式来启动服务和应用程序。 它们可以在任何分布式环境中正常工作,包括开发人员自己的笔记本电脑,裸机数据中心和受管平台,如Cloud Foundry。 Version: Brixton.SR7 1 特征 Spring Cloud专注于为经典用例和扩展机制提供良好的开箱即用 分布式/版本配置 服务注册与发现 路由选择 服务调用 负载均衡 熔断机制 全局锁 领导人选举和集群状态 分布式消息 2 原生云应用程序 原生云是应用程序开发的一种风格,鼓励在持续交付和价值驱动领域的最佳实践。 Spring Cloud的很多特性是基于Spring Boot的。更多的是由两个库实现:Spring Cloud Context and Spring Cloud Commons。 2.1 Spring Cloud Context: 应用上下文服务 Spring Boot关于使用Spring构建应用有硬性规定:通用的配置文件在固定的位置,通用管理终端,监控任务。建立在这个基础上,Spring Cloud增加了一些额外的特性。 2.1.1 引导应用程序上下文 Spring Cloud会创建一个“bootstrap”的上下文,这是主应用程序的父上下文。对应的配置文件拥有最高优先级,并且,默认不能被本地配置文件覆盖。对应的文件名bootstrap.yml或bootstrap.properties。 可通过设置spring.cloud.bootstrap.enabled=false来禁止bootstrap进程。 2.1.2 应用上下文层级结构 当用SpringApplication或SpringApplicationBuilder创建应用程序上下文时,bootstrap上下文将作为父上下文被添加进去,子上下文将继承父上下文的属性。 子上下文的配置信息可覆盖父上下文的配置信息。 2.1.3 修改Bootstrap配置文件位置 spring.cloud.bootstrap.name(默认是bootstrap),或者spring.cloud.bootstrap.location(默认是空) 2.1.4 覆盖远程配置文件的值 spring.cloud.config.allowOverride=true spring.cloud.config.overrideNone=true spring.cloud.config.overrideSystemProperties=false 2.1.5 定制Bootstrap配置 在/META-INF/spring.factories的key为org.springframework.cloud.bootstrap.BootstrapConfiguration,定义了Bootstrap启动的组件。 在主应用程序启动之前,一开始Bootstrap上下文创建在spring.factories文件中的组件,然后是@Beans类型的bean。 2.1.6 定制Bootstrap属性来源 关键点:spring.factories、PropertySourceLocator 2.1.7 环境改变 应用程序可通过EnvironmentChangedEvent监听应用程序并做出响应。 2.1.8 Refresh Scope Spring的bean被@RefreshScope将做特殊处理,可用于刷新bean的配置信息。 注意 需要添加依赖“org.springframework.boot.spring-boot-starter-actuator” 目前我只在@Controller测试成功 需要自己发送POST请求/refresh 修改配置文件即可 2.1.9 加密和解密 Spring Cloud可对配置文件的值进行加密。 如果有"Illegal key size"异常,那么需要安装JCE。 2.1.10 服务点 除了Spring Boot提供的服务点,Spring Cloud也提供了一些服务点用于管理,注意都是POST请求 /env:更新Environment、重新绑定@ConfigurationProperties跟日志级别 /refresh重新加载配置文件,刷新标记@RefreshScope的bean /restart重启应用,默认不可用 生命周期方法:/pause、/resume 2.2 Spring Cloud Commons:通用抽象 服务发现、负载均衡、熔断机制这种模式为Spring Cloud客户端提供了一个通用的抽象层。 2.2.1 RestTemplate作为负载均衡客户端 通过@Bean跟@LoadBalanced指定RestTemplate。注意URI需要使用虚拟域名(如服务名,不能用域名)。 如下: @Configuration public class MyConfiguration { @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } } public class MyClass { @Autowired private RestTemplate restTemplate; public String doOtherStuff() { String results = restTemplate.getForObject(" http://stores/stores", String.class); return results; } } 2.2.2 多个RestTemplate对象 注意@Primary注解的使用。 @Configuration public class MyConfiguration { @LoadBalanced @Bean RestTemplate loadBalanced() { return new RestTemplate(); } @Primary @Bean RestTemplate restTemplate() { return new RestTemplate(); } } public class MyClass { @Autowired private RestTemplate restTemplate; @Autowired @LoadBalanced private RestTemplate loadBalanced; public String doOtherStuff() { return loadBalanced.getForObject(" http://stores/stores", String.class); } public String doStuff() { return restTemplate.getForObject(" http://example.com", String.class); } } 2.2.3 忽略网络接口 忽略确定名字的服务发现注册,支持正则表达式配置。 3 Spring Cloud Config Spring Cloud Config提供服务端和客户端在分布式系统中扩展配置。支持不同环境的配置(开发、测试、生产)。使用Git做默认配置后端,可支持配置环境打版本标签。 3.1 快速开始 可通过IDE运行或maven运行。 默认加载property资源的策略是克隆一个git仓库(at spring.cloud.config.server.git.uri')。 HTTP服务资源的构成: /{application}/{profile}[/{label}] /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties application是SpringApplication的spring.config.name,(一般来说'application'是一个常规的Spring Boot应用),profile是一个active的profile(或者逗号分隔的属性列表),label是一个可选的git标签(默认为"master")。 3.1.1 客户端示例 创建以Spring Boot应用即可,添加依赖“org.springframework.cloud:spring-cloud-starter-config”。 配置application.properties,注意URL为配置服务端的地址 spring.cloud.config.uri: http://myconfigserver.com 3.2 Spring Cloud Config 服务端 针对系统外的配置项(如name-value对或相同功能的YAML内容),该服务器提供了基于资源的HTTP接口。使用@EnableConfigServer注解,该服务器可以很容易的被嵌入到Spring Boot 系统中。使用该注解之后该应用系统就是一个配置服务器。 @SpringBootApplication @EnableConfigServer public class ConfigApplicion { public static void main(String[] args) throws Exception { SpringApplication.run(ConfigApplicion.class, args); } } 3.2.1 资源库环境 {application} 对应客户端的"spring.application.name"属性 {profile} 对应客户端的 "spring.profiles.active"属性(逗号分隔的列表) {label} 对应服务端属性,这个属性能标示一组配置文件的版本 如果配置库是基于文件的,服务器将从application.yml和foo.yml中创建一个Environment对象。高优先级的配置优先转成Environment对象中的PropertySource。 3.2.1.1 Git后端 默认的EnvironmentRepository是用Git后端进行实现的,Git后端对于管理升级和物理环境是很方便的,对审计配置变更也很方便。也可以file:前缀从本地配置库中读取数据。 这个配置库的实现通过映射HTTP资源的{label}参数作为git label(提交id,分支名称或tag)。如果git分支或tag的名称包含一个斜杠 ("/"),此时HTTP URL中的label需要使用特殊字符串"(_)"来替代(为了避免与其他URL路径相互混淆)。如果使用了命令行客户端如 curl,请谨慎处理URL中的括号(例如:在shell下请使用引号''来转义它们)。 Git URI占位符 Spring Cloud Config Server支持git库URL中包含针对{application}和 {profile}的占位符(如果你需要,{label}也可包含占位符, 不过要牢记的是任何情况下label只指git的label)。所以,你可以很容易的支持“一个应用系统一个配置库”策略或“一个profile一个配置库”策略。 模式匹配和多资源库 spring: cloud: config: server: git: uri: https://github.com/spring-cloud-samples/config-repo repos: simple: https://github.com/simple/config-repo special: pattern: special*/dev*,special/dev* uri: https://github.com/special/config-repo local: pattern: local* uri: file:/home/configsvc/config-repo 如果 {application}/{profile}不能匹配任何表达式,那么将使用“spring.cloud.config.server.git.uri”对应的值。在上例子中,对于 "simple" 配置库, 匹配模式是simple/* (也就说,无论profile是什么,它只匹配application名称为“simple”的应用系统)。“local”库匹配所有application名称以“local”开头任何应用系统,不管profiles是什么(来实现覆盖因没有配置对profile的匹配规则,“/”后缀会被自动的增加到任何的匹配表达式中)。 Git搜索路径中的占位符 spring.cloud.config.server.git.searchPaths 3.2.1.2 版本控制后端文件系统使用 伴随着版本控制系统作为后端(git、svn),文件都会被check out或clone 到本地文件系统中。默认这些文件会被放置到以config-repo-为前缀的系统临时目录中。在Linux上,譬如应该是/tmp/config-repo- 目录。有些操作系统routinely clean out放到临时目录中,这会导致不可预知的问题出现。为了避免这个问题,通过设置spring.cloud.config.server.git.basedir或spring.cloud.config.server.svn.basedir参数值为非系统临时目录。 3.2.1.3 文件系统后端 使用本地加载配置文件。 需要配置:spring.cloud.config.server.native.searchLocations跟spring.profiles.active=native。 路径配置格式:classpath:/, classpath:/config,file:./, file:./config。 3.2.1.4 共享配置给所有应用 基于文件的资源库 在基于文件的资源库中(i.e. git, svn and native),这样的文件名application 命名的资源在所有的客户端都是共享的(如 application.properties, application.yml, application-*.properties,etc.)。 属性覆盖 “spring.cloud.config.server.overrides”添加一个Map类型的name-value对来实现覆盖。 例如 spring: cloud: config: server: overrides: foo: bar 会使所有的配置客户端应用程序读取foo=bar到他们自己配置参数中。 3.2.2 健康指示器 通过这个指示器能够检查已经配置的EnvironmentRepository是否正常运行。 通过设置spring.cloud.config.server.health.enabled=false参数来禁用健康指示器。 3.2.3 安全 你可以自由选择任何你觉得合理的方式来保护你的Config Server(从物理网络安全到OAuth2 令牌),同时使用Spring Security和Spring Boot 能使你做更多其他有用的事情。 为了使用默认的Spring Boot HTTP Basic 安全,只需要把Spring Security 增加到classpath中(如org.springframework.boot.spring-boot-starter-security)。默认的用户名是“user”,对应的会生成一个随机密码,这种情况在实际使用中并没有意义,一般建议配置一个密码(通过 security.user.password属性进行配置)并对这个密码进行加密。 3.2.4 加密与解密 如果远程属性包含加密内容(以{cipher}开头),这些值将在通过HTTP传递到客户端之前被解密。 使用略 3.2.5 密钥管理 配置服务可以使用对称(共享)密钥或者非对称密钥(RSA密钥对)。 使用略 3.2.6 创建一个测试密钥库 3.2.7 使用多密钥和循环密钥 3.2.8 加密属性服务 3.3 可替换格式服务 配置文件可加后缀".yml"、".yaml"、".properties" 3.4 文本解释服务 /{name}/{profile}/{label}/{path} 3.5 嵌入配置服务器 一般配置服务运行在单独的应用里面,只要使用注解@EnableConfigServer即可嵌入到其他应用。 3.6 推送通知和总线 添加依赖spring-cloud-config-monitor,激活Spring Cloud 总线,/monitor端点即可用。 当webhook激活,针对应用程序可能已经变化了的,配置服务端将发送一个RefreshRemoteApplicationEvent。 3.7 客户端配置 3.7.1 配置第一次引导 通过spring.cloud.config.uri属性配置Config Server地址 3.7.2 发现第一次引导 如果用的是Netflix,则用eureka.client.serviceUrl.defaultZone进行配置。 3.7.3 配置客户端快速失败 在一些例子里面,可能希望在没有连接配置服务端时直接启动失败。可通过spring.cloud.config.failFast=true进行配置。 3.7.4 配置客户端重试 添加依赖spring-retry、spring-boot-starter-aop,设置spring.cloud.config.failFast=true。默认的是6次重试,初始补偿间隔是1000ms,后续补偿为1.1指数乘数,可通过spring.cloud.config.retry.*配置进行修改。 3.7.5 定位远程配置资源 路径:/{name}/{profile}/{label} "name" = ${spring.application.name} "profile" = ${spring.profiles.active} (actually Environment.getActiveProfiles()) "label" = "master" label对于回滚到之前的版本很有用。 3.7.6 安全 通过spring.cloud.config.password、spring.cloud.config.username进行配置。 答案来源于网络
养狐狸的猫 2019-12-02 02:18:34 0 浏览量 回答数 0

问题

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

阿里极客公益活动: 或许你挑灯夜战只为一道难题 或许你百思不解只求一个答案 或许你绞尽脑汁只因一种未知 那么他们来了,阿里系技术专家来云栖问答为你解答技术难题了 他们用户自己手中的技术来帮助用户成长 本次活动特邀百位阿里技术专家对Java常...
管理贝贝 2019-12-01 20:07:15 27612 浏览量 回答数 19

问题

实例标识

实例标识作为 实例元数据 的一部分,可以帮助您快速辨识并区分 ECS 实例,为应用程序权限控制和软件激活等提供重要的信任基础。 实例标识的所有信息均实时生成,随取即用,并跟随实例信息...
chenchuan 2019-12-01 21:37:26 722 浏览量 回答数 0

问题

实例标识

实例标识作为 实例元数据 的一部分,可以帮助您快速辨识并区分 ECS 实例,为应用程序权限控制和软件激活等提供重要的信任基础。 实例标识的所有信息均实时生成,随取即用,并跟随实例信息...
chenchuan 2019-12-01 21:34:14 490 浏览量 回答数 0

回答

92题 一般来说,建立INDEX有以下益处:提高查询效率;建立唯一索引以保证数据的唯一性;设计INDEX避免排序。 缺点,INDEX的维护有以下开销:叶节点的‘分裂’消耗;INSERT、DELETE和UPDATE操作在INDEX上的维护开销;有存储要求;其他日常维护的消耗:对恢复的影响,重组的影响。 需要建立索引的情况:为了建立分区数据库的PATITION INDEX必须建立; 为了保证数据约束性需要而建立的INDEX必须建立; 为了提高查询效率,则考虑建立(是否建立要考虑相关性能及维护开销); 考虑在使用UNION,DISTINCT,GROUP BY,ORDER BY等字句的列上加索引。 91题 作用:加快查询速度。原则:(1) 如果某属性或属性组经常出现在查询条件中,考虑为该属性或属性组建立索引;(2) 如果某个属性常作为最大值和最小值等聚集函数的参数,考虑为该属性建立索引;(3) 如果某属性经常出现在连接操作的连接条件中,考虑为该属性或属性组建立索引。 90题 快照Snapshot是一个文件系统在特定时间里的镜像,对于在线实时数据备份非常有用。快照对于拥有不能停止的应用或具有常打开文件的文件系统的备份非常重要。对于只能提供一个非常短的备份时间而言,快照能保证系统的完整性。 89题 游标用于定位结果集的行,通过判断全局变量@@FETCH_STATUS可以判断是否到了最后,通常此变量不等于0表示出错或到了最后。 88题 事前触发器运行于触发事件发生之前,而事后触发器运行于触发事件发生之后。通常事前触发器可以获取事件之前和新的字段值。语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次。 87题 MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。具体原因为:MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。 86题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 85题 存储过程是一组Transact-SQL语句,在一次编译后可以执行多次。因为不必重新编译Transact-SQL语句,所以执行存储过程可以提高性能。触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。 84题 存储过程是用户定义的一系列SQL语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。 83题 减少表连接,减少复杂 SQL,拆分成简单SQL。减少排序:非必要不排序,利用索引排序,减少参与排序的记录数。尽量避免 select *。尽量用 join 代替子查询。尽量少使用 or,使用 in 或者 union(union all) 代替。尽量用 union all 代替 union。尽量早的将无用数据过滤:选择更优的索引,先分页再Join…。避免类型转换:索引失效。优先优化高并发的 SQL,而不是执行频率低某些“大”SQL。从全局出发优化,而不是片面调整。尽可能对每一条SQL进行 explain。 82题 如果条件中有or,即使其中有条件带索引也不会使用(要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)。对于多列索引,不是使用的第一部分,则不会使用索引。like查询是以%开头。如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引。如果mysql估计使用全表扫描要比使用索引快,则不使用索引。例如,使用<>、not in 、not exist,对于这三种情况大多数情况下认为结果集很大,MySQL就有可能不使用索引。 81题 主键不能重复,不能为空,唯一键不能重复,可以为空。建立主键的目的是让外键来引用。一个表最多只有一个主键,但可以有很多唯一键。 80题 空值('')是不占用空间的,判断空字符用=''或者<>''来进行处理。NULL值是未知的,且占用空间,不走索引;判断 NULL 用 IS NULL 或者 is not null ,SQL 语句函数中可以使用 ifnull ()函数来进行处理。无法比较 NULL 和 0;它们是不等价的。无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。NULL 值可以使用 <=> 符号进行比较,该符号与等号作用相似,但对NULL有意义。进行 count ()统计某列的记录数的时候,如果采用的 NULL 值,会被系统自动忽略掉,但是空值是统计到其中。 79题 HEAP表是访问数据速度最快的MySQL表,他使用保存在内存中的散列索引。一旦服务器重启,所有heap表数据丢失。BLOB或TEXT字段是不允许的。只能使用比较运算符=,<,>,=>,= <。HEAP表不支持AUTO_INCREMENT。索引不可为NULL。 78题 如果想输入字符为十六进制数字,可以输入带有单引号的十六进制数字和前缀(X),或者只用(Ox)前缀输入十六进制数字。如果表达式上下文是字符串,则十六进制数字串将自动转换为字符串。 77题 Mysql服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。 76题 在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的。但是如果你的MYSQL表类型是使用InnoDB Tables 或 BDB tables的话,你的MYSQL就可以使用事务处理,使用SET AUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改。 75题 它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。 74题 创建索引的时候尽量使用唯一性大的列来创建索引,由于使用b+tree做为索引,以innodb为例,一个树节点的大小由“innodb_page_size”,为了减少树的高度,同时让一个节点能存放更多的值,索引列尽量在整数类型上创建,如果必须使用字符类型,也应该使用长度较少的字符类型。 73题 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下: 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读。垂直分区: 根据数据库里面数据表的相关性进行拆分。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。水平分区: 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。水平拆分可以支撑非常大的数据量。 72题 乐观锁失败后会抛出ObjectOptimisticLockingFailureException,那么我们就针对这块考虑一下重试,自定义一个注解,用于做切面。针对注解进行切面,设置最大重试次数n,然后超过n次后就不再重试。 71题 一致性非锁定读讲的是一条记录被加了X锁其他事务仍然可以读而不被阻塞,是通过innodb的行多版本实现的,行多版本并不是实际存储多个版本记录而是通过undo实现(undo日志用来记录数据修改前的版本,回滚时会用到,用来保证事务的原子性)。一致性锁定读讲的是我可以通过SELECT语句显式地给一条记录加X锁从而保证特定应用场景下的数据一致性。 70题 数据库引擎:尤其是mysql数据库只有是InnoDB引擎的时候事物才能生效。 show engines 查看数据库默认引擎;SHOW TABLE STATUS from 数据库名字 where Name='表名' 如下;SHOW TABLE STATUS from rrz where Name='rrz_cust';修改表的引擎alter table table_name engine=innodb。 69题 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);哈希索引也不支持多列联合索引的最左匹配规则;B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。 68题 decimal精度比float高,数据处理比float简单,一般优先考虑,但float存储的数据范围大,所以范围大的数据就只能用它了,但要注意一些处理细节,因为不精确可能会与自己想的不一致,也常有关于float 出错的问题。 67题 datetime、timestamp精确度都是秒,datetime与时区无关,存储的范围广(1001-9999),timestamp与时区有关,存储的范围小(1970-2038)。 66题 Char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。Varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储。char和varchar后面如果有空格,char会自动去掉空格后存储,varchar虽然不会去掉空格,但在进行字符串比较时,会去掉空格进行比较。Varbinary保存变长的字符串,后面不会补\0。 65题 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。 64题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 63题 存储过程是一些预编译的SQL语句。1、更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。 62题 密码散列、盐、用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率。 61题 推荐使用自增ID,不要使用UUID。因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。总之,在数据量大一些的情况下,用自增主键性能会好一些。 60题 char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间。在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。 59题 一. read uncommitted(读取未提交数据) 即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。 二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别 当前会话只能读取到其他事务提交的数据,未提交的数据读不到。 三. repeatable read(可重读)---MySQL默认的隔离级别 当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。 四. serializable(串行化) 其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。 58题 B+树的高度一般为2-4层,所以查找记录时最多只需要2-4次IO,相对二叉平衡树已经大大降低了。范围查找时,能通过叶子节点的指针获取数据。例如查找大于等于3的数据,当在叶子节点中查到3时,通过3的尾指针便能获取所有数据,而不需要再像二叉树一样再获取到3的父节点。 57题 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。 56题 redo log是物理日志,记录的是"在某个数据页上做了什么修改"。 binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给ID=2这一行的c字段加1"。 redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。 redo log是循环写的,空间固定会用完:binlog 是可以追加写入的。"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。 最开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog日志只能用于归档。而InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。 55题 重做日志(redo log)      作用:确保事务的持久性,防止在发生故障,脏页未写入磁盘。重启数据库会进行redo log执行重做,达到事务一致性。 回滚日志(undo log)  作用:保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。 二进 制日志(binlog)    作用:用于主从复制,实现主从同步;用于数据库的基于时间点的还原。 错误日志(errorlog) 作用:Mysql本身启动,停止,运行期间发生的错误信息。 慢查询日志(slow query log)  作用:记录执行时间过长的sql,时间阈值可以配置,只记录执行成功。 一般查询日志(general log)    作用:记录数据库的操作明细,默认关闭,开启后会降低数据库性能 。 中继日志(relay log) 作用:用于数据库主从同步,将主库发来的bin log保存在本地,然后从库进行回放。 54题 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。 那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。死锁的解决办法:1.查出的线程杀死。2.设置锁的超时时间。3.指定获取锁的顺序。 53题 当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性(脏读,不可重复读,幻读等),可能产生死锁。 乐观锁:乐观锁不是数据库自带的,需要我们自己去实现。 悲观锁:在进行每次操作时都要通过获取锁才能进行对相同数据的操作。 共享锁:加了共享锁的数据对象可以被其他事务读取,但不能修改。 排他锁:当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 行锁:就是给某一条记录加上锁。 52题 Mysql是关系型数据库,MongoDB是非关系型数据库,数据存储结构的不同。 51题 关系型数据库优点:1.保持数据的一致性(事务处理)。 2.由于以标准化为前提,数据更新的开销很小。 3. 可以进行Join等复杂查询。 缺点:1、为了维护一致性所付出的巨大代价就是其读写性能比较差。 2、固定的表结构。 3、高并发读写需求。 4、海量数据的高效率读写。 非关系型数据库优点:1、无需经过sql层的解析,读写性能很高。 2、基于键值对,数据没有耦合性,容易扩展。 3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。 缺点:1、不提供sql支持,学习和使用成本较高。 2、无事务处理,附加功能bi和报表等支持也不好。 redis与mongoDB的区别: 性能:TPS方面redis要大于mongodb。 可操作性:mongodb支持丰富的数据表达,索引,redis较少的网络IO次数。 可用性:MongoDB优于Redis。 一致性:redis事务支持比较弱,mongoDB不支持事务。 数据分析:mongoDB内置了数据分析的功能(mapreduce)。 应用场景:redis数据量较小的更性能操作和运算上,MongoDB主要解决海量数据的访问效率问题。 50题 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。 49题 分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。 48题 除了缓存服务器自带的缓存失效策略之外(Redis默认的有6种策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种: 1.定时去清理过期的缓存; 2.当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。 两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,可以根据应用场景来权衡。 47题 Redis提供了两种方式来作消息队列: 一个是使用生产者消费模式模式:会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列里没有消息,则消费者继续监听 。另一个就是发布订阅者模式:也是一个或多个客户端订阅消息频道,只要发布者发布消息,所有订阅者都能收到消息,订阅者都是平等的。 46题 Redis的数据结构列表(list)可以实现延时队列,可以通过队列和栈来实现。blpop/brpop来替换lpop/rpop,blpop/brpop阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。Redis的有序集合(zset)可以用于实现延时队列,消息作为value,时间作为score。Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。 45题 1.热点数据缓存:因为Redis 访问速度块、支持的数据类型比较丰富。 2.限时业务:expire 命令设置 key 的生存时间,到时间后自动删除 key。 3.计数器:incrby 命令可以实现原子性的递增。 4.排行榜:借助 SortedSet 进行热点数据的排序。 5.分布式锁:利用 Redis 的 setnx 命令进行。 6.队列机制:有 list push 和 list pop 这样的命令。 44题 一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。 43题 RDB的优点:适合做冷备份;读写服务影响小,reids可以保持高性能;重启和恢复redis进程,更加快速。RDB的缺点:宕机会丢失最近5分钟的数据;文件特别大时可能会暂停数毫秒,或者甚至数秒。 AOF的优点:每个一秒执行fsync操作,最多丢失1秒钟的数据;以append-only模式写入,没有任何磁盘寻址的开销;文件过大时,不会影响客户端读写;适合做灾难性的误删除的紧急恢复。AOF的缺点:AOF日志文件比RDB数据快照文件更大,支持写QPS比RDB支持的写QPS低;比RDB脆弱,容易有bug。 42题 对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。Redis的操作之所以是原子性的,是因为Redis是单线程的。而在程序中执行多个Redis命令并非是原子性的,这也和普通数据库的表现是一样的,可以用incr或者使用Redis的事务,或者使用Redis+Lua的方式实现。对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么执行失败,这就是Redis的命令是原子性的原因。 41题 (1)twemproxy,使用方式简单(相对redis只需修改连接端口),对旧项目扩展的首选。(2)codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在节点数改变情况下,旧节点数据可恢复到新hash节点。(3)redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。(4)在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key进行hash计算,然后去对应的redis实例操作数据。这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的代替算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。 40题 (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。 39题 比如订单管理,热数据:3个月内的订单数据,查询实时性较高;温数据:3个月 ~ 12个月前的订单数据,查询频率不高;冷数据:1年前的订单数据,几乎不会查询,只有偶尔的查询需求。热数据使用mysql进行存储,需要分库分表;温数据可以存储在ES中,利用搜索引擎的特性基本上也可以做到比较快的查询;冷数据可以存放到Hive中。从存储形式来说,一般情况冷数据存储在磁带、光盘,热数据一般存放在SSD中,存取速度快,而温数据可以存放在7200转的硬盘。 38题 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。 37题 分层架构设计,有一条准则:站点层、服务层要做到无数据无状态,这样才能任意的加节点水平扩展,数据和状态尽量存储到后端的数据存储服务,例如数据库服务或者缓存服务。显然进程内缓存违背了这一原则。 36题 更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。 35题 redis分布式锁加锁过程:通过setnx向特定的key写入一个随机值,并同时设置失效时间,写值成功既加锁成功;redis分布式锁解锁过程:匹配随机值,删除redis上的特点key数据,要保证获取数据、判断一致以及删除数据三个操作是原子的,为保证原子性一般使用lua脚本实现;在此基础上进一步优化的话,考虑使用心跳检测对锁的有效期进行续期,同时基于redis的发布订阅优雅的实现阻塞式加锁。 34题 volatile-lru:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。 volatile-ttl:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选将要过期的数据淘汰。 volatile-random:当内存不足以容纳写入数据时,从已设置过期时间的数据集中任意选择数据淘汰。 allkeys-lru:当内存不足以容纳写入数据时,从数据集中挑选最近最少使用的数据淘汰。 allkeys-random:当内存不足以容纳写入数据时,从数据集中任意选择数据淘汰。 noeviction:禁止驱逐数据,当内存使用达到阈值的时候,所有引起申请内存的命令会报错。 33题 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 32题 缓存击穿,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。如何避免:在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。 31题 缓存雪崩,是指在某一个时间段,缓存集中过期失效。大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。而缓存服务器某个节点宕机或断网,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。如何避免:1.redis高可用,搭建redis集群。2.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。3.数据预热,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间。 30题 缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。一些恶意的请求会故意查询不存在的 key,请求量很大,对数据库造成压力,甚至压垮数据库。 如何避免:1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。 29题 1.memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型。 2.redis 的速度比 memcached 快很多。 3.redis 可以持久化其数据。 4.Redis支持数据的备份,即master-slave模式的数据备份。 5.Redis采用VM机制。 6.value大小:redis最大可以达到1GB,而memcache只有1MB。 28题 Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过spring提供的@ImportResource来加载xml配置。例如:@ImportResource({"classpath:some-context.xml","classpath:another-context.xml"}) 27题 Spring像一个大家族,有众多衍生产品例如Spring Boot,Spring Security等等,但他们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,而AOP解决了面向切面的编程,然后在此两者的基础上实现了其他衍生产品的高级功能。Spring MVC是基于Servlet的一个MVC框架,主要解决WEB开发的问题,因为 Spring的配置非常复杂,各种xml,properties处理起来比较繁琐。Spring Boot遵循约定优于配置,极大降低了Spring使用门槛,又有着Spring原本灵活强大的功能。总结:Spring MVC和Spring Boot都属于Spring,Spring MVC是基于Spring的一个MVC框架,而Spring Boot是基于Spring的一套快速开发整合包。 26题 YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。YAML 的配置文件后缀为 .yml,是一种人类可读的数据序列化语言,可以简单表达清单、散列表,标量等数据形态。它通常用于配置文件,与属性文件相比,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 25题 Spring Boot有3种热部署方式: 1.使用springloaded配置pom.xml文件,使用mvn spring-boot:run启动。 2.使用springloaded本地加载启动,配置jvm参数-javaagent:<jar包地址> -noverify。 3.使用devtools工具包,操作简单,但是每次需要重新部署。 用
游客ih62co2qqq5ww 2020-03-27 23:56:48 0 浏览量 回答数 0

问题

【javascript学习全家桶】934道javascript热门问题,阿里百位技术专家答疑解惑

阿里极客公益活动:或许你挑灯夜战只为一道难题或许你百思不解只求一个答案或许你绞尽脑汁只因一种未知那么他们来了,阿里系技术专家来云栖问答为你解答技术难题了他们用户自己手中的技术来帮助用户成长本次活动特邀百位阿里技术专家对javascript常...
管理贝贝 2019-12-01 20:07:22 6202 浏览量 回答数 1

云产品推荐

上海奇点人才服务相关的云产品 小程序定制 上海微企信息技术相关的云产品 国内短信套餐包 ECS云服务器安全配置相关的云产品 开发者问答 阿里云建站 自然场景识别相关的云产品 万网 小程序开发制作 视频内容分析 视频集锦 代理记账服务 阿里云AIoT