ivaneeo's blog

自由的力量,自由的生活。

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

#

查看密钥

密匙生成后,可以随时用以下命令查看。

查看所有密钥:
snapshot9.png

查看所有公钥:
snapshot10.png

查看所有私钥:
snapshot11.png

列出所有签名:
snapshot12.png


导出公钥

在非对称加密体系中,私钥是由用户保管,而公钥是对外公开的。用户在生成密钥对后,需要把其中的公钥导出到一个文件中,然后将其分发给其它用户。

导出公钥的方法很简单,通过gpg命令的“-export”参数就可完成。为了使导出文件是ASCⅡ编码的,还需要加上参数“-a”。比如,导出Terry Yu ASCⅡ编码的公钥文件,可以使用以下命令:
snapshot13.png


分发公钥

这个包含公钥信息的文件需要对外分发,可以通过各种方式将terry.acs文件分发给所有与用户有信息通信需求的人。

最简单的分发方式是,将该文件放到互联网上供人下载。这种方式需要注意的问题是,所发布公钥文件的网站一定要是一个可以信赖的站点。实际应用中,类似的做法很普遍。

比如,Red Hat的公钥就是在它的官方网站上发布的,任何人都可以下载获得,并用来验证Red Hat所发布软件的签名的正确性。

posted @ 2005-09-22 14:08 ivaneeo 阅读(270) | 评论 (0)编辑 收藏

命令开始运行后,首先,会看到版本和路径信息如下
snapshot3.png

随后需要回答一系列问题,以帮助产生一对密钥。首先遇到的问题是要求选择密钥使用的算法:
snapshot4.png

其中,DSA是数字签名算法,RSA和ElGamal是两种不同原理的非对称密钥算法。通常可以选择“1”,这样生成的密钥可以同时用作签名和加密两种用途。

接着,会要求选择密钥的长度:
snapshot5.png

这里的密钥长度有768、1024和2048位三种。显然,密钥越长越安全,但太长又会影响使用的速度。所以,可以根据不同的需要选择适合的长度。


另外,还需要设定密钥过期的时间:
snapshot6.png

原则上,密钥使用的频率越高,密钥有效的时间越长,被攻击的可能性就越大。所以,要根据应用的实际情况综合考虑,确定一个适当的时间长度。需要注意的是,密钥要定期更换,建议绝对不要永远使用同一对密钥。

最后,需要输入一些个人信息,包括真实姓名、电子邮件地址等,用来识别密钥,最好是如实填写。比如:
snapshot7.png

然后,必须输入一个密码。密码用来保护密钥,没有这个密码,任何人都不能看到密钥本身的内容。密码是在密钥文件泄露后惟一的保密措施,它的最大敌人是暴力破解和字典攻击。所以,一定要选择一个强壮的密码,来有效地对抗这些攻击。

密码确定以后,系统开始运算:
snapshot8.png
这时需要随便地敲击键盘或是移动鼠标,以产生一些随机数,协助密钥的顺利生成。注意,如果没有以上动作,很可能最终不能产生密钥。

以上信息表示已经成功地为“ivan wan”生成并签名了一对密钥,密钥过期时间为“2005-09-22”。在生成密钥的同时,默认用户目录的.gnupg目录中也存放了与该用户相关的 GPG配置及密钥存储文件。这些文件控制了用户的GPG环境,用户不能直接修改这些文件,所有改动都将通过“gpg”命令实现。
posted @ 2005-09-22 14:02 ivaneeo 阅读(247) | 评论 (0)编辑 收藏

建立GPG环境

GPG软件作为用于加密和数字签名的开放源码工具,许多Linux发行版本都自带了该软件。在默认安装的情况下,gpg会作为一个基本命令事先安装好。

如果选用的Linux发行版默认没有安装GPG,可以通过tar包或RPM包进行安装,可从http://www.gnupg.org/download/下载安装包。安装过程比较简单,这里省略了。

判断是否安装有GPG的方法也很简单。直接在命令行下输入“gpg -h”命令,如果系统已经安装有GPG,就会显示关于GPG用法的信息。

确定Linux系统中已经安装了GPG后,就可以开始下面加密和签名的工作了。建立GPG环境

GPG软件作为用于加密和数字签名的开放源码工具,许多Linux发行版本都自带了该软件。在默认安装的情况下,gpg会作为一个基本命令事先安装好。

如果选用的Linux发行版默认没有安装GPG,可以通过tar包或RPM包进行安装,可从http://www.gnupg.org/download/下载安装包。安装过程比较简单,这里省略了。

判断是否安装有GPG的方法也很简单。直接在命令行下输入“gpg -h”命令,如果系统已经安装有GPG,就会显示关于GPG用法的信息。

确定Linux系统中已经安装了GPG后,就可以开始下面加密和签名的工作了。

生成密钥

用户应用GPG,首先要有一对自己的密钥。所以,第一步就是产生一对密钥。gpg命令通过大量参数提供所需要的几乎所有操作。其中,参数“-gen-key”就是用来产生一对密钥的。在安装了GPG的Linux系统上可以运行以下命令:
snapshot1.png

如果想对产生密钥的操作进行一些个性化设置,还可以加上其它参数。比如,要指定生成密钥存放的位置,可以运行以下命令:
snapshot2.png
posted @ 2005-09-22 13:49 ivaneeo 阅读(332) | 评论 (0)编辑 收藏

范例(Examples)
Java 2拥有一组全新群集(collections)--并非仅仅加入一些新classes,而是完全改变了群集的风格.所以在Java 1.1Java 2中,封装群集的方式也完全不同.我首先讨论Java 2的方式,因为我认为功能更强大的Java 2 collections会取代Java 1.1 collections的地位.

范例(Examples): Java 2

假设有个人要去上课.我们用一个简单的Course来表示[课程]:
class Course...
   public Course(String name, boolean isAdvanced) {...};
   public boolean isAdvanced() {...};

我不关心课程其他细节.我感兴趣的是表示[人]的Person:
class Person...
   public Set getCourse() {
      return _courses;
   }
   public void setCourse(Set arg) {
      _courses = arg;
   }
   private Set _courses;

有了这个接口,我们就可以这样为某人添加课程:
   Person kent = new Person();
   Set s = new HashSet();
   s.add(new Course("Smalltalk Programming", false));
   s.add(new Course("Appreciating Single Malts", true));
   kent.setCourses(s);
   Assert.equals(2, Kent.getCourses().size());

   Course refact = new Course("Refactoring", true);
   kent.getCourses().add(refact);
   kent.getCourses().add(new Course("Brutal Sarcasm", false));
   Assert.equals(4, kent.getCourses().size());

   kent.getCourses().remove(refact);
   Assert.equals(3, kent.getCourses().size());
如果想了解高级课程,可以这么做:
   Iterator iter = person.getCourses().iterator();
   int count = 0;
   while(iter.hasNext()) {
      Course each = (Course)iter.next();
      if(each.isAdvanced()) count++;
   }
我要做的第一件事就是为Person中的群集(collections)建立合适的修改函数(modifiers, 亦即add/remove函数),如下所示,然后编译:
class Person...
   public void addCourse(Course arg) {
      _courses.add(arg);
   }
   public void removeCourse(Course arg) {
      _courses.remove(arg);
   }

如果我想下面这样初始化_courses值域,我的人生会轻松得多:
   private Set _courses = new HashSet();

接下来我需要观察设值函数(setter)的调用者.如果有许多地点大量运用了设值函数,我就需要修改设值函数,令它调用添加/移除(add/remove)函数.这个过程的复杂度取决于设值函数的被使用方式.设值函数的用法有两种,最简单的情况就是:它被用来[对集群进行初始化动作].换句话说,设值函数被调用之前,_courses是个空群集.这种情况下我需要修改设值函数,令它调用添加函数(add)就行了:
class Person...
   public void setCourses(Set arg) {
      Assert.isTrue(_courses.isEmpty());
      Iterator iter = arg.iterator();
      while(iter.hasNext()) {
         addCourse((Course)iter.next());
      }
   }
修改完毕后,最后以Rename Method(273)更明确地展示这个函数的意图.
   public void initializeCourses(Set arg) {
      Assert.isTrue(_courses.isEmpty());
      Iterator iter = arg.iterator();
      while(iter.hasNext()) {
         addCourse((Course)iter.next());
      }
   }

更普通的情况下,我必须首先以移除函数(remove)将群集中的所有元素全部移除,然后再调用添加函数(add)将元素一一添加进去.不过我发现这种情况很少出现(唔,愈是普通的情况,愈少出现).

如果我知道初始化时,除了添加元素,不会再有其他行为,那么我可以不使用循环,直接调用addAll()函数:
   public void initializeCourses(Set arg) {
      Assert.isTrue(_courses.isEmpty());
      
_courses.addAll(arg);
   }

我不能仅仅对这个set赋值,就算原本这个set是空的也不行.因为万一用户在[把set传递给Person对象]之后又去修改它,会破坏封装.我必须像上面那样创建set的一个拷贝.

如果用户仅仅只是创建一个set,然后使用设值函数(setter.译注:目前已改名为initializeCourses()),我可以让它们直接使用添加/移除(add/remove)函数,并将设值函数完全移除.于是,以下代码:
   Person kent = new Person();
   Set s = new HashSet();
   s.add(new Course("Smalltalk Programming", false));
   s.add(new Course("Appreciating Single Malts", true));
   kent.initializeCourses(s);

就变成了:
   Person kent = new Person();
   kent.addCourse(new Course("Smalltalk Programming", false));
   kent.addCourse(new Course("Appreciating Single Malts", true));



接下来我开始观察取值函数(getter)的使用情况.首先处理[有人以取值函数修改底部群集(underlying collection)]的情况,例如:
   kent.getCourses().add(new Course("Brutal Sarcasm", false));
这种情况下我必须加以改变,使它调用新的修改函数(modifier):
   kent.addCourse(new Course("Brutal Sarcasm", false));
修改完所有此类情况之后,我可以让取值函数(getter)返回一个只读映件(read-only view),用以确保没有任何一个用户能够通过取值函数(getter)修改群集:
   public Set getCourses() {
      return Collections.unmodifiableSet(_courses);
   }
这样我就完成了对群集的封装.此后,不通过Person提供的add/remove函数,谁也不能修改群集内的元素.

将行为移到这个class中

我拥有了合理的接口.现在开始观察取值函数(getter)的用户,从中找出应该属于Person的代码.下面这样的代码就应该搬移到Person去:
   Iterator iter = person.getCourses().iterator();
   int counter = 0;
   while(iter.hasNext()){
      Course each = (Course)iter.next();
      if(each.isAdvanced()) cout++;
   }

因为以上只使用了属于Person的数据.首先我使用Extract Method(110)将这段代码提炼为一个独立函数:
   int numberOfAdvancedCourses(Person person) {
      Iterator iter = person.getCourses().iterator();
      int count = 0;
      while(iter.hasNext()) {
         Course each = (Course)iter.next();
         if(each.isAdvanced()) count++;
      }
      return count;
   }
然后使用Move Method(142)将这个函数搬移到Person中:
class Person...
   int numberOfAdvancedCourses(Person person) {
      Iterator iter = person.getCourses().iterator();
      int count = 0;
      while(iter.hasNext()) {
         Course each = (Course)iter.next();
         if(each.isAdvanced()) count++;
      }
      return count;
   }

举个常见例子,下列代码:
   kent.getCourses().size();
可以修改更具可读性的样子,像这样:

kent.numberOfCourses();

class Person...
public int numberOfCourses() {
   return _courses.size();
}

数年以前,我曾经担心将这样的行为搬移到Person中会导致Person变得臃肿.但是在实际工作经验中,我发现这通常并不成为问题.

posted @ 2005-09-19 13:51 ivaneeo 阅读(525) | 评论 (0)编辑 收藏

  • 作法(Mechanics)
    • 加入[为群集添加(add),移除(remove)元素]的函数.
    • 将[用以保存群集]的值域初始化为一个空群集.
    • 编译.
    • 找出[群集设值函数]的所有调用者.你可以修改那个设值函数,让它使用上述新建立的[添加/移除元素]函数;也可以直接修改调用端,改让它们调用上述新建立的[添加/移除元素]函数.
        • ==>两种情况下需要用到[群集设值函数];(1)群集为空时;(2)准备将原有群集替换为另一个群集时.
        • ==>你或许会想运用Rename Method(273)为[群集设值函数]改名,从setXxx()改为initializeXxx()或replaceXxx().
    • 编译,测试.
    • 找出所有[通过取值函数(getter)获得群集并修改其内容]的函数.逐一修改这些函数,让它们改用[添加/移除](add/remove)函数.每次修改后,编译并测试.
    • 修改完上述所有[通过取值函数(getter)获得群集并修改群集内容]的函数后,修改取值函数自身,使它返回该群集的一个只读映件(read-only view).
        • ==>在Java 2中,你可以使用Collection.unmodifiableXxx()得到该集群的只读映件.
        • ==>在Java 1.1中,你应该返回群集的一份拷贝.
    • 编译,测试.
    • 找出取值函数(getter)的所有用户,从中找出应该存在于[群集之宿主对象(host object)]内的代码.运用Extract Method(110)和Move Method(142)将这些代码移到宿主对象去.
  • 如果你使用Java 2,那么本项重构到此为止.如果你使用Java 1.1,那么用户也许会喜欢使用枚举(enumeration).为了提供这个枚举,你应该这样做.
    • 修改现有取值函数(getter)的名字,然后添加一个新取值函数,使其返回一个枚举.找出旧取值函数的所有被使用点,将它们都改为使用新取值函数.
        • ==>如果这一步跨度太大,你可以先使用Rename Method(273)修改原取值函数的名称;再建立一个新取值函数用以返回枚举;最后再修改所有调用者,使其调用新取值函数.
    • 编译,测试.
posted @ 2005-09-15 17:51 ivaneeo 阅读(529) | 评论 (0)编辑 收藏

动机(Motivation)
class常常会使用群集(collection,可能是array,list,set或vector)来保存一组实体.这样的class通常也会提供针对该群集[取值/设值函数](getter/setter).

但是,集群的处理方式应该和其他种类的数据略有不同.取值函数(getter)不该返回群集自身,因为这将让用户得以修改群集内容而群集拥有者却一无所悉.这也会对用户暴露过多[对象内部数据结构]的信息.如果一个取值函数(getter)确实需要返回多个值,它应该避免用户直接操作对象内所保存的群集,并隐藏对象内[与用户无关]的数据结构.至于如何做到这一点,视你使用的Java版本不同而有所不同.

另外,不应该为这整个群集提供一个设值函数(setter),但应该提供用以为群集添加/移除(add/remove)元素的函数.这样,群集拥有者(对象)就可以控制群集元素的添加和移除.

如果你做到以上数点,群集(collection)就被很好地封装起来了,这便可以降低群集拥有者(class)和用户之间的耦合度.
posted @ 2005-09-15 15:35 ivaneeo 阅读(353) | 评论 (0)编辑 收藏

有个函数(method)返回一个群集(collection).

让这个函数返回该群集的一个只读映件(read-only view),并在这个class中提供[添加/移除](add/remove)群集元素的函数.

Encapsulate Collection.jpg
posted @ 2005-09-15 15:08 ivaneeo 阅读(388) | 评论 (0)编辑 收藏

  • 作法(Mechanics)
    • 为public值域提供取值/设值函数(getter/setter).
    • 找到这个class以外使用该值域的所有地点.如果客户只是使用该值域,就把引用动作(reference)替换为对取值函数(getter)的调用];如果客户修改了该值值域,就将此一引用点替换为[对设值函数(setter)的调用].
        • ==>如果这个值域是个对象,而客户只不过是调用该对象的某个函数,那么不论该函数是否为修改函数(modifier,会改变对象状态),都只能算是使用该值域.只有当客户为该值域赋值时,才能将其替换为设值函数(setter).
    • 每次修改之后,编译并测试.
    • 将值域的所有用户修改完毕后,把值域声明为private.
    • 编译,测试.
posted @ 2005-09-15 14:30 ivaneeo 阅读(332) | 评论 (0)编辑 收藏

动机(Motivation)
面向对象的首要原则之一就是封装(encapsulation),或者称为[数据隐藏](data hidding).

public数据被看做是一种不好的作法,因为这样会降低程序的模块化程度(modularity).如果数据和使用该数据的行为被集中在一起,一旦情况发生变化,代码的修改就会比较简单,因为需要修改的代码都集中于同一块地方,而不是星罗棋布地散落在整个程序中.

Encapsulate Field(206)是封装过程的第一步.通过这项重构手法,你可以将数据隐藏起来,并提供相应的访问函数(accessors).但它毕竟只是第一步.如果一个class除了访问函数(accessors)外不能提供其他行为,它终究只是一个dumb class(哑类).这样的class并不能获得对象技术的优势,而你知道,浪费如何一个对象都是很不好的.实施Encapsulate Field(206)之后,我会尝试寻找那些使用[新建访问函数]的函数,看看是否可以通过简单的Move Method(142)轻快地将它们移到新对象去.
posted @ 2005-09-15 14:21 ivaneeo 阅读(423) | 评论 (0)编辑 收藏

你的class中存在一个public值域.

将它声明为private,并提供相应的访问函数(accessors).

public String _name

                                       126.gif
private String _name;
public String getName() {return _name;}
public void setName(String arg) {_name = arg;}
posted @ 2005-09-15 14:07 ivaneeo 阅读(326) | 评论 (0)编辑 收藏

仅列出标题
共67页: First 上一页 37 38 39 40 41 42 43 44 45 下一页 Last