Gallery 2.2 (Double Double) Released!

이전 포스팅에서도 잠깐 언급했던 설치형 갤러리인 Gallery2
3월17일자로 근 일여년만에 2.1.2에서  2.2로 업버전을 릴리즈 했다.

사이트에서 소개하고 있는 Gallery2의 새로운 기능은

New Features of Gallery 2.2 Include
:

  1. Downloadable Plugins.
    • This feature allows you to download and install Modules and Themes directly via the Site Admin interface. You can select from different sets of plugins (officially released plugins, experimental plugins under development and plugins provided by the Gallery community). This makes it very easy to stay up to date with the latest changes.
  2. Added support for themes to display dynamic albums.
    • New Keyword Album module makes use of this feature to show albums based on a search of item keywords.
    • New Dynamic Albums module shows albums of newest, most viewed or even random items.
    • Ratings module has a new view to display highly rated items from across the Gallery.
  3. Watermarking changes
    • Edit Album now has a Watermark tab where watermarks may be added or removed from an entire album, optionally including subalbums too.
    • Edit Watermark now has an option to replace a watermark image and apply the new image everywhere the old was one used.
    • New option to always use a single watermark and give users no watermarking options. Only Site Admins can change/remove existing watermarks.
    • New option to turn off the ability for users to upload their own watermark images.
  4. New themes: Carbon and Ajaxian
  5. New WebDAV module to mount Gallery as network device on your computer. This allows you to easily manage your Gallery with any WebDAV client like Windows Explorer.
  6. New module to send Ecards.
  7. New Digibug module for prints from digibug.com.
  8. Added support for Flash Video and Windows ASF video.
  9. Photo auto-rotation based on camera sensors or on settings from other applications.

...and many more!

란다..

와우~ 바로 업그레이드를 단행했다..
2.1.2버전까지 지원되지 않아 많은 갤러리2 유저가 원했던 일괄 워터마크 적용
기능이 가장 마음에 든다.
업그레이드를 단행 하면서 테마도 럭셔리한 PGtheme로 교체하고..
몇가지 손을 더 봐야 하지만... 좀 느긋이 진행 해야겠다..

2007/03/23 14:30 2007/03/23 14:30
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
  1. 저도 최근에 2.2로 업그레이드를 단행했습니다.

    gallery2 짱이죠...^^

    저 같은 경우엔 gallery를 쓰는 이유가.
    .사진을 쉽게 온라인으로 올릴 수 있다는 점
    .사진을 일정 크기로 자동 변환해준다는 점.
    .사진의 링크 주소를 쉽게 만들어 준다는 점.
    (이건 안 쓰시는것 같던데.. URL Rewrite 한번 사용해 보세요. 주소를 http://photo.nanbean.net/1616-1/300.jpg 이런식으로 만들어줍니다.)
    입니다.

    정말 잘만든 프로그램 같습니다.
    조금 느리다는게 조금 걸리는데..
    온라인으로 사진을 관리하는데는 이만한 프로그램이 없는것 같습니다.^^

  2. kldp쪽 보니 Gallery2에대한 얘기가 심심찮게 올라오더라구요..
    저역시 Rewrite 모듈을 활성화 할까 만까로 약간 고민 중이랍니다. ^^

와~~ 붙였다...

내 계정에는 블로그와 이미지 갤러리가 설치되어 있다..

블로그는 보시는 바와같이 태터툴스 1.1이고 갤러리http://gallery.menalto.com/ 에서
Open Source로 배포하고있는 Gallery2를 이용하고 있다.

국내는 워낙 제로보드의 갤러리가 많이 퍼져있다보니 다른 갤러리를 사용하고 있는걸
보기가 힘들다..

내가 이 Gallery2를 알게 된것도 꽤 오래전에 wordpress 로 블로그를 개설 했을 때로,
wordpress와 연동 할 만한 갤러리 솔루션을 찾다가 알게된게 계기가 되어 지금까지
사용하고 있다. 국내에서는 거의 사용자가 없을지도 모른다는 유니크한 점도 마음에 들고
사진을 웹에 게시하기위한 목적으로 만들어진 만큼 편리하고 재미있는 기능이 많아서
매력적인 프로그램이다.

태터로 블로그를 연지 얼마 되지 않은 상태에서 이 블로그 메인화면에 Gallery2와 연동하여
갤러리에 올린 사진을 랜덤으로 뿌려 줄 수 없을지 고민하다 어제 아이디어가 떠올랐고
오늘 코드를 짜고 적용 해 보니 생각  만큼 잘 작동하고 있다. ^^

솔직히 자바로 밥벌어먹고 살고 있긴하지만 내게 php는 왠지 외계어 같기도 하고
가까이하기엔 좀 먼 당신과 같은 존재 였지만.. '궁하면 통'하고 '목마른 놈이 우물 판다' 하지
않았던가.. 태터사이트의 플러그인 개발참고문서와 다른 플러그인의 동작방식을 뜯어보고
설렁설렁 만들었는데 잘 작동 해 주고 있어서 기분이 좋다 ^^
2007/03/22 22:59 2007/03/22 22:59
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
  1. php.. 외계어.. 공감합니다 ㅎㅎ

  2. 오호~ 멋진데요?^^

    초면에 무리한 부탁인것 같기도 하지만,
    저도 혹시 소스 좀 얻을 수 있을까요?

    혹시 가능하다면 nanbean앳nanbean점net으로 보내주시면 감사히 쓰겠습니다..^^

  3. 일단 플러그인으로 제작은 했는데..
    제 환경에 맞춰 만들다보니
    옵션으로 설정을 할 수 있는 부분이 없습니다.
    몇가지 옵션을 적용 해서 태터 플러그인으로 공개 하겠습니다.

봄이 찾아드는 길목에서

지난 주말 회사 동료들과 함께 삼청동으로 나들이를 나갔더랬습니다.
좀더 날이 풀리고 꽃이 피기시작하면 더 예쁘게 물들지 않을까 하는 생각을
했더랬습니다.



아주 약간 쌀쌀하긴 했지만 봄은 우리 코앞에 있었습니다.





책읽는 사람의 얼굴은 다르다고 합니다.. 독서로 춘곤증을 날려 볼까요..





세린양과 첫 대면인데.. 뭔가 불만이 있는듯 하군요..
담엔 아저씨 한테도 미소를 보여 줄 수 있겠지?





그분의 뒷모습입니다..





앗! 도촬 중 딱 걸렸습니다. 무방비상태로 당해도 미모는 여전 하시군요.. ^^







직장 상사와 그분 이십니다.. 봄날의 연인. 아름답지 않으세요?





이번 나들이를 함께한 사우입니다.



2007/03/22 10:03 2007/03/22 10:03
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
  1. 직장동료들과의 출사라.. 부럽네요^^;;;
    그분이라고 해서 '그녀'인줄 알았는데.. 직장상사분의 '그녀'신가 보네요 ㅎㅎ

  2. 예.. 사내 사진 동호회가 있어서 한달에 한번 출사를 나갑니다.(늘 모여 놀기만 하지만요..^^)
    저도 얼른 저의 '그분'을 찾아야 겠습니다.

  3. JRVg3n subpages-and-index-page_06.07.12;3;8

Web Services (JAX-WS) in Java EE 5

Java API for XML Web Services (JAX-WS) 2.0, JSR 224, is an important part of the Java EE 5 platform. A follow-on release of Java API for XML-based RPC 1.1(JAX-RPC), JAX-WS simplifies the task of developing web services using Java technology. It addresses some of the issues in JAX-RPC 1.1 by providing support for multiple protocols such as SOAP 1.1, SOAP 1.2, XML, and by providing a facility for supporting additional protocols along with HTTP. JAX-WS uses JAXB 2.0 for data binding and supports customizations to control generated service endpoint interfaces. With its support for annotations, JAX-WS simplifies web service development and reduces the size of runtime JAR files.

This document takes you through the basics of using the IDE to develop a JAX-WS web service and to consume it in three different clients—either a Java class in a Java SE application, or a servlet or JSP page in a web application. The three clients that you create in this document are separate applications, all consuming the same web service.

Expected duration: 25 minutes

Software Needed for the Tutorial

Before you begin, you need to install the following software on your computer:

  • NetBeans IDE 5.5 (download).
  • Java Standard Development Kit (JDK) version 5.0 or version 6.0 (download).
  • Sun Java System Application Server 9.0 (if not bundled with your NetBeans IDE installation, download and install it separately).

Tutorial Exercises

Installing and Configuring the Tutorial Environment

If you have not registered an instance of the Sun Java System Application Server 9.0, you must do so before you can begin developing Java EE 5 applications:

  1. Choose Tools > Server Manager from the main window.
  2. Click Add Server. Select Sun Java System Application Server and give a name to the instance. Then click Next.
  3. Specify the server information, the location of the local instance of the application server, and the domain to which you want to deploy.
  4. Click Finish.

Note: If you want to deploy to the Tomcat Web Server, you can do so, except that, since it only has a web container, you should create a web application, not an EJB module, in the next section. JAX-WS web services, unlike JSR-109 web services, can deploy successfully to the Tomcat web container.

Creating a Web Service

The goal of this exercise is to create a project appropriate to the deployment container that you decide to use. Once you have a project, you will create a web service in it.

Choosing a Container

You can either deploy your web service in a web container or in an EJB container. This depends on implementation choices. For example, if you plan to deploy to the Tomcat Web Server, which only has a web container, you should choose to create a web application, and not an EJB module.

  1. Choose File > New Project (Ctrl-Shift-N). Select Web Application from the Web category or EJB Module from the Enterprise category.
  2. Name the project CalculatorWSApplication.
  3. Depending on the deployment server that you want to use, do the following:
    • For the Sun Java System Application Server, set the J2EE Version to Java EE 5.
    • For the Tomcat Web Server, unselect the Set Source Level to 1.4 checkbox.
  4. Click Finish.

Creating a Web Service from a Java Class

  1. Right-click the CalculatorWSApplication node and choose New > Web Service.
  2. Name the web service CalculatorWS, type org.me.calculator in Package, and click Finish.

    The Projects window displays the new web service. For example, for web applications the Projects window now looks as follows:

    Projects window displaying the web service

    The IDE automatically creates the deployment descriptors required for the server, if any. For the Sun Java System Application Server, no deployment descriptor is needed. For web services deployed to the Tomcat Web Server, sun-jaxws.xml and a WSServlet item in web.xml are added.

Summary

In this exercise, you created a NetBeans project and set up the web service.

Coding the Web Service

The goal of this exercise is to do something meaningful with the files and code that the IDE has generated for you. You will add an operation that will add two numbers received from a client.

Adding Business Logic to the Web Service

  1. Expand the Web Services node and double-click the CalculatorWS node. The web service opens in the Source Editor. Note that an operation exists in the code already. It is commented out. Here, we create a new operation from scratch. Another way of creating the operation would be to remove the lines that comment out the code.
  2. Right-click within the body of the class, either above or below the code that is commented out, and choose Web Service > Add Operation.
  3. In the upper part of the Add Operation dialog box, type add in Name and choose int from the Return Type drop-down list.
  4. In the lower part of the Add Operation dialog box, click Add and create a parameter of type int named i. Click OK.
  5. Click Add again and create a parameter of type int called j.
  6. Click OK at the bottom of the Add Operation dialog box. Notice that a skeleton for the add method has been added to the Source Editor:
        
    1. @WebMethod
    2.     public int add(@WebParam(name = "i") int i, @WebParam(name = "j") int j) {
    3.         // TODO implement operation
    4.         return 0;
    5.     }

  7. Change the add method to the following (changes are in bold):
       
    1. @WebMethod
    2.     public int add(@WebParam(name = "i") int i, @WebParam(name = "j") int j) {
    3.         int k = i + j;
    4.         return k;
    5.     }


Summary

In this exercise, you added code to the web service.

Deploying and Testing the Web Service

When you deploy a web service to a web container, the IDE lets you test the web service to see if it functions as you expect. The Tester application, provided by the Sun Java System Application Server, is integrated into the IDE for this purpose. For the Tomcat Web Server, there is a similar tool. However, while the Sun Java System Application Server's Tester page lets you enter values and test them, the Tomcat Web Server does not. In the latter case, you can only see that the web service is deployed, you cannot test the values. No facility for testing whether an EJB module is deployed successfully is currently available.

To test successful deployment to a web container:

  1. Right-click the project node, choose Properties, and click Run. Depending on the deployment server that you want to use, do the following:
    • For the Sun Java System Application Server, type /CalculatorWSService?Tester in the Relative URL field.
    • For the Tomcat Web Server, type /CalculatorWS?Tester in the Relative URL field.

    Note: Since the result of a deployed EJB module is not displayed in a browser, you cannot take the step above if you are working with an EJB module.

  2. Right-click the project node and choose Run Project.

    The IDE starts the application server, builds the application, and opens the tester page in your browser, if you deployed a web application to the Sun Java System Application Server. For the Tomcat Web Server and deployment of EJB modules, the situation is different:

    • If you deployed to the Tomcat Web Server, you will see the following instead, which indicates that you have successfully deployed your web service:

      Web page displayed when web service was successfully deployed to Tomcat server

    • If you deployed an EJB module, successful deployment is indicated by the following messages in the Output window:
          Deployment of application CalculatorWSApplication  completed successfully
          Enable of CalculatorWSApplication in target server   completed successfully
          Enable of application in all targets  completed successfully
          All operations completed successfully
          run-deploy:
          run:
          BUILD SUCCESSFUL
    • If you deployed to the Sun Java System Application Server, type two numbers in the tester page, as shown below:

      Web service tester page when service successfully deployed to Sun Java System Application Server

      The sum of the two numbers is displayed:

      Web page showing result of web service test

Summary

In this exercise, you deployed a web service and tested it.

Consuming the Web Service

Now that we have deployed our web service, we need to create a client to make use of the web service's add method. Here, we create three clients— a Java class in a Java SE application, a servlet, and a JSP page in a web application.

Client 1: Java Class in Java SE Application

  1. Choose File > New Project (Ctrl-Shift-N). Select Java Application from the General category. Name the project CalculatorWS_Client_Application.

    Note: At the time of writing, issue Issue 10 was unresolved; therefore, you must create your web service client in a project folder that does not contain spaces in its path. For example, the path should not be "C:\Documents and Settings\...".

    Click Finish.
  2. Right-click the CalculatorWS_Client_Application node and choose New > Web Service Client.
  3. In Project, click Browse. Browse to the web service that you want to consume. When you have selected the web service, click OK.
  4. Type org.me.calculator.client in Package, and click Finish.

    The Projects window displays the new web service client:

    New web service client in Java SE application displayed in the Projects window

  5. Double-click Main.java so that it opens in the Source Editor. Delete the TODO comment and right-click in that line. Choose Web Service Client Resources > Call Web Service Operation.
  6. Browse to the Add operation and click OK.
  7. Change the line that is underlined in red to the following:
        System.out.println("Sum: " + port.add(3,4));
  8. Right-click the project node and choose Run Project.

    The Output window should now show the following:

        compile:
        run:
        Sum: 7
            BUILD SUCCESSFUL (total time: 1 second)

Client 2: Servlet in Web Application

  1. Choose File > New Project (Ctrl-Shift-N). Select Web Application from the Web category. Name the project CalculatorWSServletClient.

    Note: At the time of writing, issue Issue 10 was unresolved; therefore, you must create your web service client in a project folder that does not contain spaces in its path. For example, the path should not be "C:\Documents and Settings\...".

    Click Finish.

  2. Right-click the CalculatorWSServletClient node and choose New > Web Service Client.
  3. In Project, click Browse. Browse to the web service that you want to consume. When you have selected the web service, click OK.
  4. Type org.me.calculator.client in Package, and click Finish.

    The Projects window displays the new web service client:

    New web service client in servlet displayed in the Projects window

  5. Right-click the project node and choose New > Servlet. Name the servlet ClientServlet and house it in a package called org.me.calculator.client. Click Finish. To make the servlet the entry point to your application, right-click the project node, choose Properties, click Run, and type /ClientServlet in Relative URL. Click OK.
  6. In the Source Editor, remove the line that comments out the body of the processRequest method. This is the line that starts the section that comments out the code:
        /* TODO output your page here

    Next, delete the line that ends the section of commented out code:

        */

    Add some empty lines after this line:

        out.println("<h1>Servlet ClientServlet at " + request.getContextPath () + "</h1>");

    Now, right-click in one of the empty lines that you added. Choose Web Service Client Resources > Call Web Service Operation. The Select Operation to Invoke dialog box appears.

  7. Browse to the add operation and click OK.

    The processRequest method now looks as follows (the added code is in bold below):


    1.     protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    2.     throws ServletException, IOException {
    3.         response.setContentType("text/html;charset=UTF-8");
    4.         PrintWriter out = response.getWriter();
    5.         out.println("<html>");
    6.         out.println("<head>");
    7.         out.println("<title>Servlet ClientServlet</title>");
    8.         out.println("</head>");
    9.         out.println("<body>");
    10.         out.println("<h1>Servlet ClientServlet at " + request.getContextPath () + "</h1>");
    11.  
    12.         try { // Call Web Service Operation
    13.             org.me.calculator.client.CalculatorWSService service = new org.me.calculator.client.CalculatorWSService();
    14.             org.me.calculator.client.CalculatorWS port = service.getCalculatorWSPort();
    15.             // TODO initialize WS operation arguments here
    16.             int arg0 = 0;
    17.             int arg1 = 0;
    18.             // TODO process result here
    19.             int result = port.add(arg0, arg1);
    20.             System.out.println("Result = "+result);
    21.         } catch (Exception ex) {
    22.             // TODO handle custom exceptions here
    23.         }
    24.  
    25.         out.println("</body>");
    26.         out.println("</html>");
    27.         out.close();
    28.     }

    Change the value for arg0 and arg1 to other numbers, such as 3 and 4.

    Change the System.out.println statement to out.println.

    Add a line that prints out an exception, if an exception is thrown.

    The try/catch block should now look as follows (new and changed lines are highlighted):


    1.     try { // Call Web Service Operation
    2.         org.me.calculator.client.CalculatorWSService service = new org.me.calculator.client.CalculatorWSService();
    3.         org.me.calculator.client.CalculatorWSApplication port = service.getCalculatorWSApplicationPort();
    4.         // TODO initialize WS operation arguments here
    5.         int arg0 = 3;
    6.         int arg1 = 4;
    7.         // TODO process result here
    8.         int result = port.add(arg0, arg1);
    9.         out.println("<p>Result: " + result);
    10.     } catch (Exception ex) {
    11.         out.println("<p>Exception: " + ex);
    12.     }

  8. Right-click the project node and choose Run Project.

    The server starts, if it wasn't running already; the application is built and deployed, and the browser opens, displaying the calculation result.

Client 3: JSP Page in Web Application

  1. Choose File > New Project (Ctrl-Shift-N). Select Web Application from the Web category. Name the project CalculatorWSJSPClient.

    Note: At the time of writing, issue Issue 10 was unresolved; therefore, you must create your web service client in a project folder that does not contain spaces in its path. For example, the path should not be "C:\Documents and Settings\...".

    Click Finish.

  2. Right-click the CalculatorWSJSPClient node and choose New > Web Service Client.
  3. In Project, click Browse. Browse to the web service that you want to consume. When you have selected the web service, click OK.
  4. Type org.me.calculator.client in Package, and click Finish.

    The Projects window displays the new web service client.

  5. In the Web Pages folder, double-click index.jsp so that it opens in the Source Editor.
  6. In the Web Service References node, expand the node that represents the web service. The add operation, which you want to invoke from the client, is now exposed.
  7. Drag the add operation to the client's index.jsp page, and drop it below the H1 tags. The code for invoking the service's operation is now generated in the index.jsp page.

    Change the value for arg0 and arg1 to other numbers, such as 3 and 4.

  8. Right-click the project node and choose Run Project.

    The server starts, if it wasn't running already; the application is built and deployed, and the browser opens, displaying the calculation result:

    JSP page showing result 

    @http://www.netbeans.org/kb/55/websvc-jax-ws.html
2007/03/21 15:36 2007/03/21 15:36
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

Creating a Simple SOA Project with NetBeans Enterprise Pack

Contents

Overview

You will be creating a simple SOA project. You will add a WSDL file to your BPEL Module project. You use the Partner view to add the messages, partner link type, port type, and operation. Then you will create a composite application project and use the CASA editor to modify the project configuration. This tutorial also illustrates a basic scenario of how a File Binding Component can be used in a composite application.

Software Needed for this Tutorial

Before you begin, you must install the following software on your computer:

  • NetBeans IDE 5.5.1 Beta with NetBeans Enterprise Pack 5.5.1 Beta

 

Configuring the Tutorial Environment

Before you can deploy your application, the Sun Java System Application Server and JBI runtime must be configured correctly and running.

To configure the tutorial environment:

  1. Click the Runtime tab to open the Runtime window.
  2. In the Runtime window, expand the Servers node.
  3. If the Servers node already contains a Sun Java System Application Server 9 node, then go to step 5.
  4. If the Servers node does not contain a Sun Java System Application Server 9 node, then do the following to add an application server:
    1. Right-click the Servers node and choose Add Server from the pop-up menu.
      The Add Server Instance dialog box opens.
    2. In the Choose Server page, from the Server drop-down list, select Sun Java System Application Server.
    3. (Optional) In the Name field, accept the default value or type the name you want to use to identify the server in the IDE.
    4. Click Next.
      The Platform Location Folder page opens.
    5. In the Platform Location field, use the Browse button to navigate to and select the Application Server installation location.
      If you accepted the default values during the installation, the location is C:\Sun\Appserver .
    6. Select the Register Local Default Domain radio button.
    7. Click Next.
    8. Supply the user name and password for the domain's administrator.
      If you accepted the default values during the installation, the user name is admin and the password is adminadmin .
    9. Click Finish.
  5. In the Runtime window, right-click the Sun Java System Application Server 9 node and choose Start.
    If the Start option is not available, the server is already running and you can skip the next step.
  6. Wait until the following message appears in the Output window:
    Application server startup complete.
    When the server is running, the IDE displays a green arrow badge on the Sun Java System Application Server 9 node.

Creating the Project

In this section, you create a BPEL Module project called HelloSample .

To create the HelloSample project:

  1. From the IDE's main menu, choose File > New Project.
    The New Project wizard opens.
  2. In the Categories list, select the Service Oriented Architecture node.
  3. In the Projects list, select the BPEL Module node.
  4. Click Next.
  5. In the Project Name field, type HelloSample .
  6. (Optional) In the Project Location field, use the Browse button to navigate to and select a different folder where the IDE will store the project files.
  7. Click Finish.
    The Projects window now contains a project node for a BPEL Module project called HelloSample .

Creating the WSDL Document

In this section, you add a WSDL file to your BPEL Module project and then use Partner view to configure the components of the WSDL Document.

To create HelloSample.wsdl :

  1. In the Projects window, expand the HelloSample project node, then right-click the Process Files node and choose New > WSDL Document.
    The New WSDL Document wizard opens.
  2. In the File Name field, type HelloSample .
  3. Click Finish.
  4. The IDE does the following:
    • Creates HelloSample.wsdl node under the Process Files.
    • Opens the HelloSample.wsdl in the source editor.
      The Source Editor contains 3 tabs for the WSDL file, Source, WSDL, and Partner, with the WSDL view opened.
    • Opens the Properties window. If the Properties window is not visible, choose Window > Properties.
  5. In the WSDL view, click the Partner button to open the Partner view of the WSDL editor.
    The IDE opens the WSDL Palette. If the Palette window is not visible, choose Window > Palette from the main menu.
    You can create the SequenceDiagram in this view.

To add Messages :

  1. In the Palette of the Partner view select the Message icon.
  2. Drag your selection to the WSDL Partner View design area, below the Messages.
    The IDE adds a Message and the name of the new Message is ( Messages1 ).
  3. Click the down arrow to expand the new message. If the arrow is up, the message is already expanded.
    The design area now shows Part Name and Part element or Type columns.
  4. In the Message Part Name column, double-click the default value (part1) to make the field editable.
  5. Type inputType and press Enter. If the Message1 is collapsed, click the down arrow to expand the new message
  6. In the Part Element Or Type column, make sure the default type is xsd:string
    If the type is not string then click the ellipsis button and select BuiltIn Schema Types > Built-in Types > String
  7. Repeat step 1-6 and for the Message Part Name, enter resultType.

To add PartnerLinkType :

  1. In the Palette of the Partner view select the PartnerLinkType icon.
  2. Drag your selection to the WSDL Partner View design area, below the PartnerLinkTypes(0).
    The IDE adds a PartnerLink and is ready to create new Roles and Port Types. Roles and PortTypes are drawn as dotted vertical lines( Lifeline) with the External names showing at the top.
  3. For Port Types double click the green rectangle under the role1 node.
  4. Click Enter. The new portType1 is assigned.
  5. In the Palette of the Partner view select the Request-Response icon.
  6. Drag your selection to the WSDL Partner View design area, below the portType1.
    The new Operation, operation1 is added.
  7. Under operation1, double click the upper message arrow where it says <No Message Selected> and select tns:message1.
  8. Repeat step 7and 8 for the lower message arrow and select tns:message2.

Creating the BPEL Process

To create HelloSample.bpel :

  1. In the Projects window, expand the HelloSample project node, then right-click the Process Files node and choose New > BPEL Process.
    The New BPEL Process wizard opens.
  2. In the File Name field, type HelloSample.
  3. Click Finish.
    The Sample.bpel is created

To add a partner link:

  1. In the Web Service section of the Palette, select the Partner Link icon and drag your selection to the design area.
    The Create New Partnerlink1Property Editor opens.
  2. Accept the defaults and click OK.

To add a Receive activity:

  1. In the Web Service section of the Palette, select the Receive icon and drag your selection to the design area between the Process Start activity and the Process End activity.
    The IDE provides you with visual clues to show you where you can drop the selection.
    This action places a Receive activity called Receive1 in the Design view.
  2. Double-click the Receive1 activity.
    The Receive1 [Receive] - Property Editor opens.
  3. From the Partner Link drop-down list, select PartnerLink1.
    The IDE fills in the Operation field.
  4. Create a new input variable by doing the following:
    1. Click the Create button next to the Input Variable field.
      The New Input Variable dialog box opens.
    2. Change the value in the Name field to inputVar .
    3. Click OK.
  5. Click OK to close the Receive1 [Receive] - Property Editor.
    The Receive activity is now labeled start in the Design view.

To add a Reply activity:

  1. In the Web Service section of the Palette, select the Reply icon and drag your selection to the design area between the Receive1 activity and the Process End activity.
    The IDE provides you with visual clues to show you where you can drop the selection.
    This action places a Reply activity called Reply1 in the Design view.
  2. Double-click the Reply1 activity.
    The Reply1 [Reply] - Property Editor opens.
  3. From the Partner Link drop-down list, select PartnerLink1.
    The IDE fills in the Operation field.
  4. Create a new output variable by doing the following:
    1. Make sure the Normal Response radio button is selected.
    2. Click the Create button next to the Output Variable field.
      The New Output Variable dialog box opens.
    3. Change the value in the Name field to outputVar .
    4. Click OK.
  5. Click OK to close the Reply1 [Reply] - Property Editor.
    The Reply activity is now labeled end in the Design view.

To add an Assign activity:

  1. In the Basic Activities section of the Palette, select the Assign icon and drag your selection to the design area between the Receive1 activity and the Reply1 activity.
    This action places an Assign activity called Assign1 in the Design view.
  2. Select the Assign1 activity.
  3. If the BPEL Mapper window is not visible, choose Window > BPEL Mapper from the main menu.
  4. In the left pane of the BPEL Mapper, under Variables, expand the inputVar node.
    inputType appears under inputVar .
  5. In the right pane of the BPEL Mapper, under Variables, expand the outputVar node.
    resultType appears under outputVar .
  6. Drag inputType from the left pane of the BPEL Mapper to the resultType node in the right pane of the BPEL Mapper.
    This assignment copies the input statement into the output.
  7. To save your changes, in the Projects window, select the SynchronousSample project node, and from the IDE's main menu, choose File > Save All.

Creating the Composite Application

Before you deploy the BPEL Module project, you must add the JBI module to the deployment project. Deploying the project makes the service assembly available to the application server, thus allowing its service units to be run.

To create the Composite Application project:

  1. From the IDE's main menu, choose File > New Project.
    The New Project wizard opens.
  2. In the Categories list, select the Service Oriented Architecture node.
  3. In the Projects list, select the Composite Application node.
  4. Click Next.
  5. In the Project Name field, type SampleCompositeApp .
  6. Click Finish.
    The Projects window now contains a project node for a Composite Application project called SampleCompositeApp .

Using the CASA Editor

To use the CASA editor to modify the project configuration:

  1. Right click on the SampleCompositeApp project and select Edit Project.
  2. Click on the HelloSample node and drag-n-drop it onto the JBI module area.



  3. Click the build button on CASA toolbar to build the bpel project.

To create the WSDL endpoint:

  1. Click on the "file" palette item on the WSDL Bindings category in the Palette panel.
  2. Drag-n-drop it to the WSDL Ports area in the CASA editor.
  3. A new "casasport1" WSDL endpoint is added.

To createa new connection:

  1. Click on the consume endpoint of the new port.
  2. Drag it to the erole1_myRole to create a new connection.

To Check auto-generated WSDL endpoint properties

  1. In the Navigator panel, expand the WSDL Ports node.
  2. Expand casaPort1 > casaBinding1 > operation1 > input1.
  3. Select file:message.
  4. In the Properties window, assign use='literal" , pollingIntervl=5000 and fileName=input.txt.
  5. Click on WSDL Ports area in the CASA editor to open the Navigator panel again.
  6. In the Navigator panel, expand WSDL Ports > casaPort1 > casaBinding1 > operation1 > output1.
  7. Select file:message.
  8. In the Properties window, assign fileName=output.txt.
  9. Click on WSDL Ports area in the CASA editor to open the Navigator panel.
  10. In the Navigator panel, expand the WSDL Ports node.
  11. Expand casaPort1 ->casaPort1 to select the file:address node.
  12. In the Properties window, in the fileDirectory, replace C:/Temp with the string c:/temp.
  13. Click Ok.



Deploying and Testing the SampleCompositeApp

To deploy the Composite Application:

  1. Right-click the SampleCompositeApp project node and choose Deploy Project.
    If a message similar to the following message appears in the Output window, then the deployment has succeeded:
    BUILD SUCCESSFUL (total time: 11 seconds)

To test the SampleCompositeApp:

  1. Create the input.txt file in c:/temp folder and edit the file to content 'Hello World!!'.
  2. input.txt will be renamed to input.txt_processed.
  3. output.txt will be created in the same folder with the same content 'Hello World!!'.


@http://blogs.sun.com/barkodar/resource/HelloSample.html

2007/03/21 15:16 2007/03/21 15:16
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

Tomcat/JSP와 한글 문제...

◎ Tomcat 4.x
단순히 JSP 혹은 서블릿의 최 상단에 request.setCharacterEncoding("euc-kr");을 하면 된다.
GET과 POST 방식에 상관없이 인코딩을 해준다.


◎ Tomcat 5.x
POST 방식은 request.setCharacterEncoding("euc-kr");로 계속 하면된다.
하지만 GET 방식은 server.xml의 설정 부분을 바꿔줘야만 한다.

Server.xml 보기



위에서 URIEncoding="euc-kr" 부분이다.그리고 아래의 port="8009" 부분은 mod_jk를 이용해서 Apache와 Tomcat 5.x 를 연동할 때 URIEncoding="euc-kr"을 지정할 필요가 있다.

URIEncoding으로 지정할 경우, 만약 웹 어플리케이션이 EUC-KR과 UTF-8을 각 요청 별로 따로 처리할 필요가 있을경우 그에 대응할 수 없다. 대신, useBodyEncodingForURI="true"을 사용하면 Tomcat 4.x와 동일한 방식으로 즉, request.setCharacterEncoding() 값에 따라 GET/POST 방식 모두를 처리할 수도 있다. (참조 : http://tomcat.apache.org/tomcat-5.5-doc/config/http.html)

결론적으로 Tomcat 4.x와 Tomcat 5.x 는 모두 request.setCharacterEncoding()이 필요하다는 사실에는 변함이 없다.
2007/03/20 11:38 2007/03/20 11:38
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

QUEUE와 DELAYED 프로세싱

J2SE 5.0 출시에는 새로운 top-level Queue 인터페이스가 Collections Framework에 추가되어 Map, List, Set 인터페이스와 어우러진다. 일반적으로 queue는 먼저 들어온 것이 먼저 나가는 데이터 스트럭쳐이지만 priority queue같은 몇몇 구현들에서는 queue 뒤에 엘리먼트가 첨부되지 않는다. 이 queue와 FIFO(first in, first out)구조에 관한 얘기는 은행에서의 대기선에 비유할 수 있겠다. 은행직원은 고객이 대기선에 있는지 확인한 후 대기선의 첫번째 손님을 맞이하여 손님이 원하는 거래를 처리한다. 그리고 그 손님은 이제 대기선에서 제외된다.

J2SE 5.0에는 Queue 인터페이스와 함께 몇 가지 새로운 queue 구현이 있다. DelayQueue가 그 중 하나인데, DelayQueue에서 queue 안의 아이템들은 지연시간 동안 처리되지 않는다. 이번 테크팁에서는 새로운 Queue 인터페이스와 DelayQueue 구현에 대해 알아보도록 하자.

첫번째로 Queue 인터페이스를 분석해보자. 이 인터페이스는 Collection을 확장하고 다섯개의 고유 메서드들을 추가한다.

  • E element()
  • boolean offer(E o)
  • E peek()
  • E poll()
  • E remove()

J2SE 5.0이 새롭게 generics를 지원하므로 여기에서의 E는 어느 타입이든지 가능하며, Queue가 생성될 때 정의된 엘리먼트 타입으로 결정된다.

Queue의 엘리먼트를 추가하고 제거하는 데 당연히 Collection 인터페이스 메서드들을 사용할 수도 있지만, 그 메서드들은 동작할 때 부가적인 요구사항을 가지므로, Queue 인터페이스에서는 사용하지 않을 것을 권장하고 있다. 예를 들어 Collection.add 메서드로 queue에 엘리먼트를 추가하는 대신에 offer 메서드로 queue에 엘리먼트를 추가할 수 있다. 이 둘은 무슨 차이가 있을까? add 실행이 오류가 날 수 있다. 그 한 예는 queue에 사이즈 제한이 있을 때이다.(은행 대기선에 비유하자면, 10명만 대기 가능할 경우) Collectionadd 메서드를 사용하면 add는 예외를 던지면서 실패한다. 이와 비교할 때 offer 메서드는 false를 리턴하며 "실패"하게 된다. 따라서 offer 메서드를 사용하면 실제로 예외적인 상황에서만(특히 체크 안 된 런타임 예외가 던져졌을 경우) 예외처리(exception handling)을 사용하게 된다.

Queue의 다른 네가지 메서드는 두개씩 짝지어 설명할 수 있다. remove/poll, element/peek. removepoll 메서드는 둘 다 queue의 첫번째 엘리먼트 즉 "head"를 제거하는 데 사용된다. 빈 Collection 객체에서 호출되었을 때, remove 메서드는 예외를 던지고, poll 메서드는 단순히 null 값을 리턴한다. head 엘리먼트를 제거하는 대신 단지 그 엘리먼트를 살펴볼 수도 있다. 이 때 element와 peek 메서드가 사용된다. 여기서 element 메서드는 빈 queue에서는 예외를 던지고, peek은 null값을 리턴한다. Queue는 일반적으로 태스크를 진행하는 데 사용되므로 빈 queue를 갖는 것이 예외상황일 필요는 없다. 따라서, poll/peek 모델이 사용하기에 보다 적합할 것이다. (앞에서 본 메서드들 중 예외를 안 던지고 null 리턴하는 메서드들)

Queue는 다음과 같은 상황에서 일반적으로 사용된다.

   class Producer implements Runnable {
     private final Queue queue;
     Producer(Queue q) { queue = q; }
     public void run() {
       try {
         while(true) { queue.offer(produce()); }
       } catch (InterruptedException ex) { ... handle ...}
     }
     Object produce() { ... }
   }

   class Consumer implements Runnable {
     private final Queue queue;
     Consumer(Queue q) { queue = q; }
     public void run() {
       try {
         Object o;
         while((o = queue.poll()) != null) { consume(o); }
       } catch (InterruptedException ex) { ... handle ...}
     }
     void consume(Object x) { ... }
   }

Queue가 꽉 차 있거나(생산자의 입장에서) 비어있을 때(소비자의 입장에서) 어떤 일이 일어나는 지 궁금할 것이다. 이 시점에서 새로운 queue 인터페이스 BlockingQueue를 설명하는 것이 좋겠다. Queue를 사용하여 엘리먼트를 무작정 추가하거나(offer사용) 삭제하는(poll 사용) 대신 BlockingQueueput 메서드로 엘리먼트를 추가하고 take메서드로 제거할 수 있다. puttake는 모두 이를 호출한 쓰레드가, 특정 조건 하에서 블로킹되게끔 한다. put은 queue가 꽉 차 있을 경우, take는 queue가 비어있을 경우가 블로킹 조건이다.

BlockingQueue의 일반적인 사용패턴은 다음과 같다.

   class Producer implements Runnable {
     private final BlockingQueue queue;
     Producer(BlockingQueue q) { queue = q; }
     public void run() {
       try {
         while(true) { queue.put(produce()); }
       } catch (InterruptedException ex) { ... handle ...}
     }
       Object produce() { ... }
  }
  
   class Consumer implements Runnable {
     private final BlockingQueue queue;
     Consumer(BlockingQueue q) { queue = q; }
     public void run() {
       try {
         while(true) { consume(queue.take()); }
       } catch (InterruptedException ex) { ... handle ...}
     }
     void consume(Object x) { ... }
   }

각 생성된 생산자가 꽉 찬 queue에 새로운 아이템을 추가하려 하면 put메서드에서 기다리고, take 메서드에서는 꺼내갈 것이 추가될 때까지 기다린다. queue가 비어있다면 while(true) 조건문에는 아무런 변화도 일어나지 않을 것이다.

DelayQueue는 BlockingQueue 인터페이스의 구체적인 구현이다. DelayQueue 에 추가된 아이템들은 반드시 새로운 Delayed 인터페이스를 구현해야하며, 이 Delayed는 한 개의 메서드, long getDelay(TimeUnit unit)를 갖고 있다. DelayQueue는 우선순위 힙 데이터 스트럭쳐에 기반한 시간 기준 스케쥴링 Queue로 동작한다

데모를 위해, 다음의 프로그램 DelayTest는 몇 초안에 실행되는 Delayed 인터페이스를 구현한다. 알아둬야할 것은1) nanosecond는 10억분의 1초, 2) nanosecond 유니트에서 작업을 가능케하는 System의 새로운 메서드, nanoTime 이 있다는 것이다. getDelay 메서드가 nanosecond로 리턴된 횟수를 필요로 하기 때문에 nanosecond에서 작업하는 것이 중요하다.

   import java.util.Random;
   import java.util.concurrent.Delayed;
   import java.util.concurrent.DelayQueue;
   import java.util.concurrent.TimeUnit;

   public class DelayTest {
     public static long BILLION = 1000000000;
     static class SecondsDelayed implements Delayed { 
       long trigger;
       String name;
       SecondsDelayed(String name, long i) { 
         this.name = name;
         trigger = System.nanoTime() + (i * BILLION);
       }
       public int compareTo(Delayed d) {
         long i = trigger;
         long j = ((SecondsDelayed)d).trigger;
         int returnValue;
         if (i < j) {
           returnValue = -1;
         } else if (i > j) {
           returnValue = 1;
         } else {
           returnValue = 0;
         }
         return returnValue;
       }
       public boolean equals(Object other) {
         return ((SecondsDelayed)other).trigger == trigger;
       }
       public long getDelay(TimeUnit unit) {
         long n = trigger - System.nanoTime();
         return unit.convert(n, TimeUnit.NANOSECONDS);
       }
       public long getTriggerTime() {
         return trigger;
       }
       public String getName() {
         return name;
       }
       public String toString() {
         return name + " / " + String.valueOf(trigger);
       }
     }
     public static void main(String args[]) 
             throws InterruptedException {
       Random random = new Random();
       DelayQueue<SecondsDelayed> queue = 
             new DelayQueue<SecondsDelayed>();
       for (int i=0; i < 10; i++) {
         int delay = random.nextInt(10);
         System.out.println("Delaying: " + 
               delay + " for loop " + i);
         queue.add(new SecondsDelayed("loop " + i, delay));
       }
       long last = 0;
       for (int i=0; i < 10; i++) {
         SecondsDelayed delay = (SecondsDelayed)(queue.take());
         String name = delay.getName();
         long tt = delay.getTriggerTime();
         if (i != 0) {
           System.out.println("Delta: " + 
                 (tt - last) / (double)BILLION);
         }
         System.out.println(name + " / Trigger time: " + tt);
         last = tt;
       }
     }
   }

DelayTest 프로그램은 엘리먼트를 실행하기 전 DelayQueue 안에 그 10개의 엘리먼트를 위치시킨다.

다음은 DelayQueue를 한번 구동했을 때의 출력물이다.

   Delaying: 8 for loop 0
   Delaying: 7 for loop 1
   Delaying: 2 for loop 2
   Delaying: 4 for loop 3
   Delaying: 0 for loop 4
   Delaying: 9 for loop 5
   Delaying: 3 for loop 6
   Delaying: 4 for loop 7
   Delaying: 6 for loop 8
   Delaying: 2 for loop 9
   loop 4 / Trigger time: 1883173869520000
   Delta: 1.9995545
   loop 2 / Trigger time: 1883175869074500
   Delta: 0.0012475
   loop 9 / Trigger time: 1883175870322000
   Delta: 0.9995177
   loop 6 / Trigger time: 1883176869839700
   Delta: 0.9995187
   loop 3 / Trigger time: 1883177869358400
   Delta: 6.408E-4
   loop 7 / Trigger time: 1883177869999200
   Delta: 2.0001667
   loop 8 / Trigger time: 1883179870165900
   Delta: 0.9986953
   loop 1 / Trigger time: 1883180868861200
   Delta: 0.9995595
   loop 0 / Trigger time: 1883181868420700
   Delta: 1.001262
   loop 5 / Trigger time: 1883182869682700

이 출력물은 loop4를 위한 아이템이 time 0, 즉 지연 없이 시작하기로 설정되어있다는 것을 가리키고 있으며,

   Delaying: 0 for loop 4

따라서 첫번째로 다음과 같이 구동한다.

   loop 4 / Trigger time: 1883173869520000

Loop 2에서는 2초간의 지연이 있으며,

   Delaying: 2 for loop 2

따라서 다음과 같이 나타난다.

   loop 2 / Trigger time: 1883175869074500

여기서의 delta는 1.9995545로 약 2초이다.

   Delta: 1.9995545

다른 loop를 위한 비슷한 delta들도 존재한다.

좀 더 실제적인 예를 위해 DelayQueue에서 pull된 것을 단지 출력하는 대신, queue의 아이템들을 Runnable 구현시키고, 그 아이템들의 run 메서드를 호출할 수 있다.

Queue, DelayQueue 와 J2SE 5.0에서 바뀐 다른 Collections Framework에 대한 좀 더 많은 정보를 원한다면 Collection Framework Enhancements를 참조하기 바란다.


@http://kr.sun.com/developers/techtips/c2004_1019.html

2007/03/16 18:01 2007/03/16 18:01
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

HTTPURLCONNECTION를 사용하여 웹 페이지 액세스하기

이 글은 HttpURLConnection 과 이의 서브클래스인 HttpsURLConnection 을 사용하여 보안 웹 페이지에 액세스하는 방법을 보여준다. 또한 비보안 페이지(non-secure page)에서 보안 페이지(secure one)로의 리다이렉트를 쉽게 할 수 있는 방법도 볼 수 있다. HTTP 와 HTTPS에 관한 정보는 HTTP 1.1 RFC 2616HTTPS RFC 2818를 참고하기 바란다.

첫번째 예로, 주어진 URL에 접속하기 위해 다음 WebPageReader 프로그램의 HttpURLConnection 를 이용해 보자. 그리고 페이지의 내용을 스탠다드 아웃(standard out)에 출력하자.

[code] import java.net.URL; import java.net.MalformedURLException; import java.net.URLConnection; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; public class WebPageReader { private static URLConnection connection; private static void connect( String urlString ) { try { URL url = new URL(urlString); connection = url.openConnection(); //for jdk 1.5 or higher connection.setConnectionTimeout(1000); connection.setReadTimeout(3000); //for jdk 1.4 above System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); System.setProperty("sun.net.client.defaultReadTimeout", "50000"); } catch (MalformedURLException e){ e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static void readContents() { BufferedReader in = null; try { in = new BufferedReader( new InputStreamReader( connection.getInputStream())); String inputLine; while ( (inputLine = in.readLine()) != null) { System.out.println(inputLine); } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { if (args.length != 1) { System.err.println("usage: java WebPageReader " + "<url>"); System.exit(0); } connect(args[0]); readContents(); } } [/code]

만약 현재의 위치가 방화벽 뒤라면, 다음과 같이 설정된 proxyHost과 proxyPort 변수들이 필요하다.

[code] http.proxyHost=webcache http.proxyPort=8080 https.proxyHost=webcache https.proxyPort=8080 [/code]

커맨드 라인에 -D플래그를 이용해서 값을 직접 입력하거나 프로그램 상에서 System.setProperty()를 호출함으로써 변수를 구할 수있다. WebPageReader 를 컴파일한 후에 이하와 같은 커맨드로 Core Java Technologies Tech Tips 홈 페이지의 내용을 열거해 볼 수 있다.

[code] java WebPageReader http://java.sun.com/developer/JDCTechTips/ [/code]

URLConnection는 추상 클래스이다. URL클래스의 openConnection() 메소드는 지정된 URL을 읽을 수 있도록 적절하고 구체적인 서브클래스를 리턴한다. http나 https URL을 입력하면 이는 HttpURLConnection나 HttpsURLConnection의 서브클래스가 될 것이다. 만약 다음을 openConnection()를 호출하는 라인에 추가하면,

[code] System.out.println(connection.getClass()); [/code]

HttpURLConnection의 숨겨진 구현 클래스의 인스턴스를 리턴하는 커넥션(connection)을 보게 된다. 예를 들면, 다음과 같다.

[code] class sun.net.www.protocol.http.HttpURLConnection [/code]

이와 유사하게 보안 페이지를 읽기 위해 동일한 WebPageReader코드를 사용할 수가 있다.

[code] java WebPageReader https://today.dev.java.net [/code]

후자의 경우, 커넥션은 HttpsURLConnection의 서브클래스인 HttpURLConnection타입이라는 것을 알아야 한다. 보다 명확하게 말하자면 다음과 같은 숨어있는 구현 클래스가 있다는 것을 인식할 수 있어야 한다.

[code] class sun.net.www.protocol.https.HttpsURLConnectionImpl [/code]

일반적으로 브라우저에 URL을 입력할 때, 이동하고자하는 페이지가 보안 페이지인지 아닌지는 알 수가 없다. 다시 말하면, today.dev.java.net 페이지를 보기 위해서는 http://today.dev.java.net를 입력한다. 필요하다면 브라우저가 리다이렉트할 것이고 사용자를 https://today.dev.java.net로 연결하기 위해 적절한 신호변경을 수행한다. WebPageReader프로그램이 요청된 리다이렉션을 수행하는지를 살펴보자.

[code] java WebPageReader http://today.dev.java.net [/code]

원하는 페이지로 리다이렉트되는 대신에 다음과 같은 메시지를 보게 된다.

[code] <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <HTML><HEAD> <TITLE>301 Moved Permanently</TITLE> </HEAD><BODY> <H1>Moved Permanently</H1> The document has moved <A HREF="https://today.dev.java.net/">here</A>.<P> <HR> <ADDRESS> Apache/1.3.26 Server at today.dev.java.net Port 80 </ADDRESS> </BODY></HTML> [/code]

이 정보로부터 무언가를 읽어내는 것은 어렵지만 문제는 리다이렉션에 관한 것이 아니다. URL http://linux.java.net으로 프로그램을 실행하면, 프로그램은 http://community.java.net/linux으로 적절히 이를 리다이렉트하고 사용자는 원하는 컨텐츠를 볼 수가 있다. 어떤 일이 일어나는지를 자세히 살펴보려면 HttpURLConnection를 명시적으로 이용해야 한다. 스탠다드 아웃에 웹 페이지의 컨텐츠를 출력하는 코드를 삭제해서 일을 간단히 해보자. RedirectingReader프로그램이다.

[code] import java.net.URL; import java.net.MalformedURLException; import java.net.HttpURLConnection; import java.io.IOException; public class RedirectingReader { private static HttpURLConnection connection; private static void connect( String urlString ) { try { URL url = new URL(urlString); connection = (HttpURLConnection)url.openConnection(); //for jdk 1.5 or higher connection.setConnectionTimeout(1000); connection.setReadTimeout(3000); //for jdk 1.4 above System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); System.setProperty("sun.net.client.defaultReadTimeout", "30000"); System.out.println(connection.getURL()); System.out.println( connection.getResponseCode() + " " + connection.getResponseMessage()); System.out.println(connection.getURL()); } catch (MalformedURLException e){ e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { if (args.length != 1) { System.err.println( "usage: java WebPageReader " + "<url>"); System.exit(0); } connect(args[0]); } } [/code]

다음과 같이 리다이렉트하는 URL을 입력하여 RedirectingReader 를 컴파일하고 실행해 보자.

[code] java RedirectingReader http://linux.java.net/ [/code]

다음과 같은 출력값을 보게 될 것이다.

[code] http://linux.java.net/ 200 OK http://community.java.net/linux/ [/code]

첫번째 라인이 재빨리 나타난다. String값으로 URL을 생성하고 HttpURLConnection객체를 실행하자. 그러면 http://linux.java.net를 요청하는 동안에 잠깐의 멈춤이 생긴다. 페이지가 리다이렉트되는 이 시간동안 받게 되는 응답 코드와 메시지는 리다이렉트된 페이지로부터 온 것이다. 이 리다이렉트된 페이지는 출력값의 3번째 라인에 열거된다. URL url = new URL(urlString);아래의 라인을 추가해서 리다이렉션을 허용하지 않았을 때 발생하는 현상을 보자.

[code] HttpURLConnection.setFollowRedirects(false); [/code]

출력값은 다음과 같다.

[code] http://linux.java.net/ 302 Found http://linux.java.net/ [/code]

이는 302 에러가 발생했다는 것을 나타낸다. 곧 리다이렉트되지 않고 URL이 그대로 유지되었다는 것이다. 이를 처리하기 전에, 좀 전에 추가했던 라인을 지우고 리다이렉션이 다시 작동하는지를 확인하기 위해 RedirectingReader 프로그램을 실행시켜보자. RedirectingReader를 다시 한번 실행시키고, http://today.dev.java.net 를 입력하자. 다음과 같은 출력값을 보게 된다.

[code] http://today.dev.java.net 301 Moved Permanently http://today.dev.java.net [/code]

위는 이 프로그램이 "Moved Permanently" 에러를 처리할 수 없어서 리다이렉트 했다는 것을 말한다. 이것이 바로 원했던 디폴트 속성이다. 보안문제 때문에 http 과 https간에는 리다이렉트할 수 없다. 어디로 리다이렉트할 것이냐하는 정보는 이 응답의 헤더 부분에 있다. 이전의 요청에 대한 전체 응답 헤더는 다음과 같다.

[code] HTTP/1.1 301 Moved Permanently Date: Tue, 03 Feb 2004 01:38:43 GMT Server: Apache/1.3.26 (Unix) mod_ssl/2.8.10 OpenSSL/0.9.6b mod_jk/1.2.1 Location: https://today.dev.java.net/ Content-type: text/html; charset=iso-8859-1 [/code]

HttpURLConnection 내의 getResponseCode() 과 getResponseMessage() 메소드가 이 응답의 첫번째 라인에 포함된 정보를 리턴하는 것을 본 적이 있을 것이다. 혹은 getHeaderField() 메소드를 이용해서 헤더 필드의 이름에 스트링값을 넣어주어도 된다. 가령, getHeaderField("Location")는 https://today.dev.java.net/값을 리턴한다.

이 글의 시작부분에서 언급했던 HTTP 1.1 과 HTTPS RFCs에서 요청과 응답 헤더의 포맷에 관해 자세히 살펴 볼 수 있다. 300 레벨 응답에서, "Location:"는 리다이렉션을 위한 위치값을 제공해야만 한다. 301나 302 에러를 발생하는지를 확인하기 위해 다음 사항을 추가하자.

[code] private static boolean mustRedirect(int code){ if (code == HttpURLConnection.HTTP_MOVED_PERM || code == HttpURLConnection.HTTP_MOVED_TEMP) { System.out.println("Received error " + code + ", trying secure redirect"); return true; } else return false; } [/code]

리다이렉트가 자동적으로 처리되지 않는다면 사용자는 301 나 302 응답 코드만을 받게 된다는 것을 기억하자. 지금까지 이것은 리다이렉트가 HttpURLConnection가 아닌 HttpsURLConnection가 필요하다는 것을 의미했다. "Location:" 필드에 제공된 정보를 따르자. 다음과 같이 새로운 정보를 이용해서 url 값과 커넥션을 재설정하자.

[code] url = new URL("https://"+ url.getHost() + url.getFile()); connection = (HttpsURLConnection)url.openConnection(); [/code]

마지막으로, 웹 리더를 받기 위해 위의 모든 사항을 모으고 필요할 때 보안 페이지로 리다이렉트될 수 있도록 하자.

[code] import javax.net.ssl.HttpsURLConnection; import java.net.URL; import java.net.MalformedURLException; import java.net.HttpURLConnection; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; public class RedirectingReader { private static HttpURLConnection connection; private static URL url; private static void connect(String urlString) { try { url = new URL(urlString); connection = (HttpURLConnection) url.openConnection(); //for jdk 1.5 or higher connection.setConnectionTimeout(1000); connection.setReadTimeout(3000); //for jdk 1.4 above System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); System.setProperty("sun.net.client.defaultReadTimeout", "50000"); int code = connection.getResponseCode(); if (mustRedirect(code)) secureRedirect( connection.getHeaderField("Location")); readContents(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static boolean mustRedirect(int code) { if (code == HttpURLConnection.HTTP_MOVED_PERM || code == HttpURLConnection.HTTP_MOVED_TEMP) { return true; } else return false; } private static void secureRedirect(String location) throws IOException { System.out.println(location); url = new URL(location); connection = (HttpsURLConnection) url.openConnection(); } private static void readContents() { BufferedReader in = null; try { in = new BufferedReader( new InputStreamReader( connection.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) { System.out.println(inputLine); } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { if (args.length != 1) { System.err.println("usage: java WebPageReader " + "<url>"); System.exit(0); } connect(args[0]); } } [/code]

업데이트된 RedirectingReader 를 컴파일하고 동작이 제대로 이루어지는지 확인하기 위해 몇 개의 다른 입력값을 넣어 실행해보자. 예를 들면 http://today.dev.java.net 와 http://linux.java.net를 넣어보자. 리다이렉트되지 않는 보안페이지와 비보안 페이지를 입력해서 RedirectingReader를 실행해도 동작이 적절하게 이루어져야 한다. 이제 다시 뒤로 돌아가서 최초 WebReader 프로그램에 모든 println() 메소드를 제거하고 readContents()를 추가할 수 있다.


@http://kr.sun.com/developers/techtips/c2004_02_10.html

2007/03/15 12:58 2007/03/15 12:58
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
  1. Blog Icon
    감사합니다.

    좋은 정보 감사합니다. 비공개로 담아갑니다 ^^;

  2. Blog Icon
    비밀방문자

    관리자만 볼 수 있는 댓글입니다.

  3. Blog Icon
    비밀방문자

    관리자만 볼 수 있는 댓글입니다.

행사장에서 만난 꼬마 친구들



















minolta @7, tokina 28-80, potra 160vc
2007/03/11 01:05 2007/03/11 01:05
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
  1. 역시 포트라다.. 라는 느낌이 듭니다^^

  2. 우담아빠님 또 찾아주셨군요.. ^^
    이번 주말엔 직장 동료 애기 돌 스냅사진을 부탁받았는데..
    이런 부탁을 받으면 한편으론 기쁘면서도 또 한편으론
    부담스러워 집니다.

    카메라를 처음들었을때같은 편한 마음으로 찍는 스냅이라면 좋으련만
    그런 행사장 사진은 저 보단 사진 받을 사람의 마음에 드는 결과물이
    나와줘야 하기 때문에 아직은 제 사진에대한 확신이 없는 저로선
    부담스러워 지는게 어찌보면 당연한 일이겠지요..

역쉬...뒷풀이는 고깃집이..









출사 후 뒷풀이.
허기진 배를 채우러 들어온 나름 이름있는 고깃집.
너무 오랜만에 느껴보는  선술집 분위기...
소주한잔이 생각나는 밤이다.

minolta @7, km 17-35mm, portra 160vc
2007/03/11 00:13 2007/03/11 00:13
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

JavaTM Cryptography Extension (JCE) Reference Guide


JavaTM Cryptography Extension (JCE)

Reference Guide

for the JavaTM 2 Platform Standard Edition Development Kit (JDK) 5.0



Introduction


What's New in JCE in the JDK 5.0


Cryptographic Concepts

Encryption and Decryption

Password-Based Encryption

Cipher

Key Agreement

Message Authentication Code


Core Classes

The Cipher Class

The Cipher Stream Classes

The CipherInputStream Class

The CipherOutputStream Class

The KeyGenerator Class

The SecretKeyFactory Class

The SealedObject Class

The KeyAgreement Class

The Mac Class


How to Make Applications "Exempt" from Cryptographic Restrictions


Installing JCE Providers for the JDK 5.0


JCE Keystore


Code Examples

Using Encryption

Using Password-Based Encryption

Using Key Agreement



Appendix A: Standard Names


Appendix B: SunJCE Default Keysizes


Appendix C: SunJCE Keysize Restrictions


Appendix D: Jurisdiction Policy File Format


Appendix E: Maximum Key Sizes Allowed by "Strong" Jurisdiction Policy Files


Appendix F: Sample Programs

Diffie-Hellman Key Exchange between 2 Parties

Diffie-Hellman Key Exchange between 3 Parties

Blowfish Example

HMAC-MD5 Example

Introduction

This document is intended as a companion to the JavaTM Cryptography Architecture (JCA) API Specification & Reference. References to chapters not present in this document are to chapters in the JCA Specification.

The JavaTM Cryptography Extension (JCE) provides a framework and implementations for encryption, key generation and key agreement, and Message Authentication Code (MAC) algorithms. Support for encryption includes symmetric, asymmetric, block, and stream ciphers. The software also supports secure streams and sealed objects.

JCE was previously an optional package (extension) to the JavaTM 2 SDK, Standard Edition (Java 2 SDK), versions 1.2.x and 1.3.x. JCE has been integrated into the Java 2 SDK since the 1.4 release.

JCE is based on the same design principles found elsewhere in the JCA: implementation independence and, whenever possible, algorithm independence. It uses the same "provider" architecture. Providers signed by a trusted entity can be plugged into the JCE framework, and new algorithms can be added seamlessly.

The JCE API covers:

  • Symmetric bulk encryption, such as DES, RC2, and IDEA
  • Symmetric stream encryption, such as RC4
  • Asymmetric encryption, such as RSA
  • Password-based encryption (PBE)
  • Key Agreement
  • Message Authentication Codes (MAC)

The JDK 5.0 release comes standard with a JCE provider named "SunJCE", which comes pre-installed and registered and which supplies the following cryptographic services:

  • An implementation of the DES (FIPS PUB 46-1), Triple DES, and Blowfish encryption algorithms in the Electronic Code Book (ECB), Cipher Block Chaining (CBC), Cipher Feedback (CFB), Output Feedback (OFB), and Propagating Cipher Block Chaining (PCBC) modes. (Note: Throughout this document, the terms "Triple DES" and "DES-EDE" will be used interchangeably.)
  • Key generators for generating keys suitable for the DES, Triple DES, Blowfish, HMAC-MD5, and HMAC-SHA1 algorithms.
  • An implementation of the MD5 with DES-CBC password-based encryption (PBE) algorithm defined in PKCS #5.
  • "Secret-key factories" providing bi-directional conversions between opaque DES, Triple DES and PBE key objects and transparent representations of their underlying key material.
  • An implementation of the Diffie-Hellman key agreement algorithm between two or more parties.
  • A Diffie-Hellman key pair generator for generating a pair of public and private values suitable for the Diffie-Hellman algorithm.
  • A Diffie-Hellman algorithm parameter generator.
  • A Diffie-Hellman "key factory" providing bi-directional conversions between opaque Diffie-Hellman key objects and transparent representations of their underlying key material.
  • Algorithm parameter managers for Diffie-Hellman, DES, Triple DES, Blowfish, and PBE parameters.
  • An implementation of the HMAC-MD5 and HMAC-SHA1 keyed-hashing algorithms defined in RFC 2104.
  • An implementation of the padding scheme described in PKCS #5.
  • A keystore implementation for the proprietary keystore type named "JCEKS".

A Note on Terminology

The JCE within the JDK 5.0 includes two software components:

  • the framework that defines and supports cryptographic services that providers can supply implementations for. This framework includes everything in the javax.crypto package.
  • a provider named "SunJCE"
Throughout this document, the term "JCE" by itself refers to the JCE framework in the JDK 5.0. Whenever the JCE provider supplied with the JDK 5.0 is mentioned, it will be referred to explicitly as the "SunJCE" provider.

What's New in JCE in the JDK 5.0

Here are the differences in JCE between v1.4 and 5.0:

Support for PKCS #11 Based Crypto Provider

In JDK 5.0, a JCA/JCE provider, SunPKCS11 that acts as a generic gateway to the native PKCS#11 API has been implemented. PKCS#11 is the de-facto standard for crypto accelerators and also widely used to access cryptographic smartcards. The administrator/user can configure this provider to talk any PKCS#11 v2.x compliant token.

Here's an example of the configuration file format.

Integration with Solaris Cryptographic Framework

On Solaris 10, the default Java security provider configuration has been changed in JDK 5.0 to include an instance of the SunPKCS11 provider that uses the Solaris Cryptographic Framework. It is the provider with the highest precedence thereby allowing all existing applications to take advantage of the improved performance on Solaris 10. There is no change in behavior on Solaris 8 and Solaris 9 systems.

As a result of this change, many cryptographic operations will execute several times as fast as before on all Solaris 10 systems. On systems with cryptographic hardware acceleration, the performance improvements may be two orders of magnitude.

Support for ECC Algorithm

Prior to JDK 5.0 the JCA/JCE framework did not include support classes for ECC-related crypto algorithms. Users who wanted to use ECC had to depend on a 3rd party library that implemented ECC. However, this did not integrate well with existing JCA/JCE framework.

Starting in JDK 5.0, full support for ECC classes to facilitate providers that support ECC have been included.

The following interfaces have been added:

The following classes have been added:

Added ByteBuffer API Support

Methods that take ByteBuffer arguments have been added to the JCE API and SPI classes that are used to process bulk data. Providers can override the engine* methods if they can process ByteBuffers more efficiently than byte[].

The following JCE methods have been added to support ByteBuffers:

    javax.crypto.Mac.update(ByteBuffer input)
javax.crypto.MacSpi.engineUpdate(ByteBuffer input)
javax.crypto.Cipher.update(ByteBuffer input, ByteBuffer output)
javax.crypto.Cipher.doFinal(ByteBuffer input, ByteBuffer output)
javax.crypto.CipherSpi.engineUpdate(ByteBuffer input, ByteBuffer output)
javax.crypto.CipherSpi.engineDoFinal(ByteBuffer input, ByteBuffer output)
The following JCA methods have been added to support ByteBuffers:
    java.security.MessageDigest.update(ByteBuffer input)
java.security.Signature.update(ByteBuffer data)
java.security.SignatureSpi.engineUpdate(ByteBuffer data)
java.security.MessageDigestSpi.engineUpdate(ByteBuffer input)

Support for RC2ParameterSpec

The RC2 algorithm implementation has been enhanced in JDK 5.0 to support effective key size that is distinct from the length of the input key.

Full support for XML Encryption RSA-OAEP Algorithm

Prior to JDK 5.0, JCE did not define any parameter class for specifying the non-default values used in OAEP and PSS padding as defined in PKCS#1 v2.1 and the RSA-OAEP Key Transport algorithm in the W3C Recommendation for XML Encryption. Therefore, there was no generic way for applications to specify non-default values used in OAEP and PSS padding.

In JDK 5.0, new parameter classes have been added to fully support OAEP padding and the existing PSS parameter class was enhanced with APIs to fully support RSA PSS signature implementations. Also, SunJCE provider has been enhanced to accept OAEPParameterSpec when OAEPPadding is used.

The following classes have been added:

The following methods and fields have been added to java.security.spec.PSSParameterSpec:

    public static final PSSParameterSpec DEFAULT
public PSSParameterSpec(String mdName, String mgfName,
AlgorithmParameterSpec mgfSpec,
int saltLen, int trailerField)
public String getDigestAlgorithm()
public String getMGFAlgorithm()
public AlgorithmParameterSpec getMGFParameters()
public int getTrailerField()

Simplified Retrieval of PKCS8EncodedKeySpec from javax.crypto.EncryptedPrivateKeyInfo

In JDK 5.0, javax.crypto.EncryptedPrivateKeyInfo only has one method, getKeySpec(Cipher) for retrieving the PKCS8EncodedKeySpec from the encrypted data. This limitation requires users to specify a cipher which is initialized with the decryption key and parameters. When users only have the decryption key, they would have to first retrieve the parameters out of this EncryptedPrivateKeyInfo object, get hold of matching Cipher implementation, initialize it, and then call the getKeySpec(Cipher) method.

To make EncyptedPrivateKeyInfo easier to use and to make its API consistent with javax.crypto.SealedObject, the following methods have been added to javax.crypto.EncryptedPrivateKeyInfo:

    getKeySpec(Key decryptKey)
getKeySpec(Key decryptKey, String provider)

Ability to Dynamically Determine Maximum Allowable Key Length

In 1.4.2, the crypto jurisdiction policy files bundled in J2SE limits the maximum key length (and parameter value for some crypto algorithms) that can be used for encryption/decryption. Users who desire unlimited version of crypto jurisdiction files must download them separately.

Also, an exception is thrown when the Cipher instance is initialized with keys (or parameters for certain crypto algorithms) exceeds the maximum values allowed by the crypto jurisdiction files.

In JDK 5.0, the Cipher class has been updated to provide the maximum values for key length and parameters configured in the jurisdiction policy files, so that applications can use a shorter key length when the default (limited strength) jurisdiction policy files are installed.

The following methods have been added to javax.crypto.Cipher:

    public static final int getMaxAllowedKeyLength(String transformation)
throws NoSuchAlgorithmException

public static final AlgorithmParameterSpec
getMaxAllowedParameterSpec(String transformation)
throws NoSuchAlgorithmException;

Support for HmacSHA256, HmacSHA384, HmacSHA512

Support for HmacSHA-256, HmacSHA-384, and HmacSHA-512 algorithms have been added to JDK 5.0.

Support for RSA Encryption to SunJCE Provider

A publicly accessible RSA encryption implementation has been added to the SunJCE provider.

Support for RC2 and ARCFOUR Ciphers to SunJCE Provider

The SunJCE provider now implements the RC2 (RFC 2268) and ARCFOUR (an RC4TM-compatible algorithm) ciphers.

Support for "PBEWithSHA1AndDESede" and "PBEWithSHA1AndRC2_40" Ciphers

Added support for PBEWithSHA1AndDESede and PBEWithSHA1AndRC2_40 ciphers in SunJCE provider.

Support for XML Encryption Padding Algorithm in JCE Block Encryption Ciphers

W3C XML Encryption defines a new padding algorithm, "ISO10126Padding," for block ciphers. See 5.2 Block Encryption Algorithms for more information.

To allow Sun's provider to be used by XML Encryption implementations and JSR 106 providers, we have added support for this padding in JDK 5.0.

Cryptographic Concepts

This section provides a high-level description of the concepts implemented by the API, and the exact meaning of the technical terms used in the API specification.

Encryption and Decryption

Encryption is the process of taking data (called cleartext) and a short string (a key), and producing data (ciphertext) meaningless to a third-party who does not know the key. Decryption is the inverse process: that of taking ciphertext and a short key string, and producing cleartext.

Password-Based Encryption

Password-Based Encryption (PBE) derives an encryption key from a password. In order to make the task of getting from password to key very time-consuming for an attacker, most PBE implementations will mix in a random number, known as a salt, to create the key.

Cipher

Encryption and decryption are done using a cipher. A cipher is an object capable of carrying out encryption and decryption according to an encryption scheme (algorithm).

Key Agreement

Key agreement is a protocol by which 2 or more parties can establish the same cryptographic keys, without having to exchange any secret information.

Message Authentication Code

A Message Authentication Code (MAC) provides a way to check the integrity of information transmitted over or stored in an unreliable medium, based on a secret key. Typically, message authentication codes are used between two parties that share a secret key in order to validate information transmitted between these parties.

A MAC mechanism that is based on cryptographic hash functions is referred to as HMAC. HMAC can be used with any cryptographic hash function, e.g., MD5 or SHA-1, in combination with a secret shared key. HMAC is specified in RFC 2104.


Core Classes

  • The Cipher Class

    The Cipher class provides the functionality of a cryptographic cipher used for encryption and decryption. It forms the core of the JCE framework.

    Creating a Cipher Object

    Like other engine classes in the API, Cipher objects are created using the getInstance factory methods of the Cipher class. A factory method is a static method that returns an instance of a class, in this case, an instance of Cipher, which implements a requested transformation.

    To create a Cipher object, you must specify the transformation name. You may also specify which provider you want to supply the implementation of the requested transformation:

        
    public static Cipher getInstance(String transformation);

    public static Cipher getInstance(String transformation,
    String provider);

    If just a transformation name is specified, the system will determine if there is an implementation of the requested transformation available in the environment, and if there is more than one, if there is a preferred one.

    If both a transformation name and a package provider are specified, the system will determine if there is an implementation of the requested transformation in the package requested, and throw an exception if there is not.

    A transformation is a string that describes the operation (or set of operations) to be performed on the given input, to produce some output. A transformation always includes the name of a cryptographic algorithm (e.g., DES), and may be followed by a mode and padding scheme.

    A transformation is of the form:

    For example, the following are valid transformations:

        "DES/CBC/PKCS5Padding"

    "DES"

    If no mode or padding is specified, provider-specific default values for the mode and padding scheme are used. For example, the SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider,

        Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding");

    and

        Cipher c1 = Cipher.getInstance("DES");

    are equivalent statements.

    When requesting a block cipher in stream cipher mode (e.g., DES in CFB or OFB mode), you may optionally specify the number of bits to be processed at a time, by appending this number to the mode name as shown in the "DES/CFB8/NoPadding" and "DES/OFB32/PKCS5Padding" transformations. If no such number is specified, a provider-specific default is used. (For example, the SunJCE provider uses a default of 64 bits.)

    Appendix A of this document contains a list of standard names that can be used to specify the algorithm name, mode, and padding scheme components of a transformation.

    The objects returned by factory methods are uninitialized, and must be initialized before they become usable.

    Initializing a Cipher Object

    A Cipher object obtained via getInstance must be initialized for one of four modes, which are defined as final integer constants in the Cipher class. The modes can be referenced by their symbolic names, which are shown below along with a description of the purpose of each mode:

    • ENCRYPT_MODE
      Encryption of data.
    • DECRYPT_MODE
      Decryption of data.
    • WRAP_MODE
      Wrapping a Key into bytes so that the key can be securely transported.
    • UNWRAP_MODE
      Unwrapping of a previously wrapped key into a java.security.Key object.

    Each of the Cipher initialization methods takes a mode parameter (opmode), and initializes the Cipher object for that mode. Other parameters include the key (key) or certificate containing the key (certificate), algorithm parameters (params), and a source of randomness (random).

    To initialize a Cipher object, call one of the following init methods:

        public void init(int opmode, Key key);

    public void init(int opmode, Certificate certificate)

    public void init(int opmode, Key key,
    SecureRandom random);

    public void init(int opmode, Certificate certificate,
    SecureRandom random)

    public void init(int opmode, Key key,
    AlgorithmParameterSpec params);

    public void init(int opmode, Key key,
    AlgorithmParameterSpec params,
    SecureRandom random);

    public void init(int opmode, Key key,
    AlgorithmParameters params)

    public void init(int opmode, Key key,
    AlgorithmParameters params,
    SecureRandom random)

    If a Cipher object that requires parameters (e.g., an initialization vector) is initialized for encryption, and no parameters are supplied to the init method, the underlying cipher implementation is supposed to supply the required parameters itself, either by generating random parameters or by using a default, provider-specific set of parameters.

    However, if a Cipher object that requires parameters is initialized for decryption, and no parameters are supplied to the init method, an InvalidKeyException or InvalidAlgorithmParameterException exception will be raised, depending on the init method that has been used.

    See the section about Managing Algorithm Parameters for more details.

    The same parameters that were used for encryption must be used for decryption.

    Note that when a Cipher object is initialized, it loses all previously-acquired state. In other words, initializing a Cipher is equivalent to creating a new instance of that Cipher, and initializing it. For example, if a Cipher is first initialized for decryption with a given key, and then initialized for encryption, it will lose any state acquired while in decryption mode.

    Encrypting and Decrypting Data

    Data can be encrypted or decrypted in one step (single-part operation) or in multiple steps (multiple-part operation). A multiple-part operation is useful if you do not know in advance how long the data is going to be, or if the data is too long to be stored in memory all at once.

    To encrypt or decrypt data in a single step, call one of the doFinal methods:

        public byte[] doFinal(byte[] input);

    public byte[] doFinal(byte[] input, int inputOffset,
    int inputLen);

    public int doFinal(byte[] input, int inputOffset,
    int inputLen, byte[] output);

    public int doFinal(byte[] input, int inputOffset,
    int inputLen, byte[] output, int outputOffset)

    To encrypt or decrypt data in multiple steps, call one of the update methods:

        public byte[] update(byte[] input);

    public byte[] update(byte[] input, int inputOffset, int inputLen);

    public int update(byte[] input, int inputOffset, int inputLen,
    byte[] output);

    public int update(byte[] input, int inputOffset, int inputLen,
    byte[] output, int outputOffset)

    A multiple-part operation must be terminated by one of the above doFinal methods (if there is still some input data left for the last step), or by one of the following doFinal methods (if there is no input data left for the last step):

        public byte[] doFinal();

    public int doFinal(byte[] output, int outputOffset);

    All the doFinal methods take care of any necessary padding (or unpadding), if padding (or unpadding) has been requested as part of the specified transformation.

    A call to doFinal resets the Cipher object to the state it was in when initialized via a call to init. That is, the Cipher object is reset and available to encrypt or decrypt (depending on the operation mode that was specified in the call to init) more data.

    Wrapping and Unwrapping Keys

    Wrapping a key enables secure transfer of the key from one place to another.

    The wrap/unwrap API makes it more convenient to write code since it works with key objects directly. These methods also enable the possibility of secure transfer of hardware-based keys.

    To wrap a Key, first initialize the Cipher object for WRAP_MODE, and then call the following:

        public final byte[] wrap(Key key);

    If you are supplying the wrapped key bytes (the result of calling wrap) to someone else who will unwrap them, be sure to also send additional information the recipient will need in order to do the unwrap:

    1. the name of the key algorithm, and
    2. the type of the wrapped key (one of Cipher.SECRET_KEY, Cipher.PRIVATE_KEY, or Cipher.PUBLIC_KEY).

    The key algorithm name can be determined by calling the getAlgorithm method from the Key interface:

        public String getAlgorithm();

    To unwrap the bytes returned by a previous call to wrap, first initialize a Cipher object for UNWRAP_MODE, then call the following:

        public final Key unwrap(byte[] wrappedKey,
    String wrappedKeyAlgorithm,
    int wrappedKeyType));

    Here, wrappedKey is the bytes returned from the previous call to wrap, wrappedKeyAlgorithm is the algorithm associated with the wrapped key, and wrappedKeyType is the type of the wrapped key. This must be one of Cipher.SECRET_KEY, Cipher.PRIVATE_KEY, or Cipher.PUBLIC_KEY.

    Managing Algorithm Parameters

    The parameters being used by the underlying Cipher implementation, which were either explicitly passed to the init method by the application or generated by the underlying implementation itself, can be retrieved from the Cipher object by calling its getParameters method, which returns the parameters as a java.security.AlgorithmParameters object (or null if no parameters are being used). If the parameter is an initialization vector (IV), it can also be retrieved by calling the getIV method.

    In the following example, a Cipher object implementing password-based encryption is initialized with just a key and no parameters. However, the selected algorithm for password-based encryption requires two parameters - a salt and an iteration count. Those will be generated by the underlying algorithm implementation itself. The application can retrieve the generated parameters from the Cipher object as follows:

        import javax.crypto.*;
    import java.security.AlgorithmParameters;

    // get cipher object for password-based encryption
    Cipher c = Cipher.getInstance("PBEWithMD5AndDES");

    // initialize cipher for encryption, without supplying
    // any parameters. Here, "myKey" is assumed to refer
    // to an already-generated key.
    c.init(Cipher.ENCRYPT_MODE, myKey);

    // encrypt some data and store away ciphertext
    // for later decryption
    byte[] cipherText = c.doFinal("This is just an example".getBytes());

    // retrieve parameters generated by underlying cipher
    // implementation
    AlgorithmParameters algParams = c.getParameters();

    // get parameter encoding and store it away
    byte[] encodedAlgParams = algParams.getEncoded();

    The same parameters that were used for encryption must be used for decryption. They can be instantiated from their encoding and used to initialize the corresponding Cipher object for decryption, as follows:

        import javax.crypto.*;
    import java.security.AlgorithmParameters;

    // get parameter object for password-based encryption
    AlgorithmParameters algParams;
    algParams =
    AlgorithmParameters.getInstance("PBEWithMD5AndDES");

    // initialize with parameter encoding from above
    algParams.init(encodedAlgParams);

    // get cipher object for password-based encryption
    Cipher c = Cipher.getInstance("PBEWithMD5AndDES");

    // initialize cipher for decryption, using one of the
    // init() methods that takes an AlgorithmParameters
    // object, and pass it the algParams object from above
    c.init(Cipher.DECRYPT_MODE, myKey, algParams);

    If you did not specify any parameters when you initialized a Cipher object, and you are not sure whether or not the underlying implementation uses any parameters, you can find out by simply calling the getParameters method of your Cipher object and checking the value returned. A return value of null indicates that no parameters were used.

    The following cipher algorithms implemented by the SunJCE provider use parameters:

    • DES, DES-EDE, and Blowfish, when used in feedback (i.e., CBC, CFB, OFB, or PCBC) mode, use an initialization vector (IV). The javax.crypto.spec.IvParameterSpec class can be used to initialize a Cipher object with a given IV.
    • PBEWithMD5AndDES uses a set of parameters, comprising a salt and an iteration count. The javax.crypto.spec.PBEParameterSpec class can be used to initialize a Cipher object implementing PBEWithMD5AndDES with a given salt and iteration count.

    Note that you do not have to worry about storing or transferring any algorithm parameters for use by the decryption operation if you use the SealedObject class. This class attaches the parameters used for sealing (encryption) to the encrypted object contents, and uses the same parameters for unsealing (decryption).

    Cipher Output Considerations

    Some of the update and doFinal methods of Cipher allow the caller to specify the output buffer into which to encrypt or decrypt the data. In these cases, it is important to pass a buffer that is large enough to hold the result of the encryption or decryption operation.

    The following method in Cipher can be used to determine how big the output buffer should be:

        public int getOutputSize(int inputLen)
  • The Cipher Stream Classes

    JCE introduces the concept of secure streams, which combine an InputStream or OutputStream with a Cipher object. Secure streams are provided by the CipherInputStream and CipherOutputStream classes.

    • The CipherInputStream Class

      This class is a FilterInputStream that encrypts or decrypts the data passing through it. It is composed of an InputStream, or one of its subclasses, and a Cipher. CipherInputStream represents a secure input stream into which a Cipher object has been interposed. The read methods of CipherInputStream return data that are read from the underlying InputStream but have additionally been processed by the embedded Cipher object. The Cipher object must be fully initialized before being used by a CipherInputStream.

      For example, if the embedded Cipher has been initialized for decryption, the CipherInputStream will attempt to decrypt the data it reads from the underlying InputStream before returning them to the application.

      This class adheres strictly to the semantics, especially the failure semantics, of its ancestor classes java.io.FilterInputStream and java.io.InputStream. This class has exactly those methods specified in its ancestor classes, and overrides them all, so that the data are additonally processed by the embedded cipher. Moreover, this class catches all exceptions that are not thrown by its ancestor classes. In particular, the skip(long) method skips only data that has been processed by the Cipher.

      It is crucial for a programmer using this class not to use methods that are not defined or overridden in this class (such as a new method or constructor that is later added to one of the super classes), because the design and implementation of those methods are unlikely to have considered security impact with regard to CipherInputStream.

      As an example of its usage, suppose cipher1 has been initialized for encryption. The code below demonstrates how to use a CipherInputStream containing that cipher and a FileInputStream in order to encrypt input stream data:

          FileInputStream fis;
      FileOutputStream fos;
      CipherInputStream cis;

      fis = new FileInputStream("/tmp/a.txt");
      cis = new CipherInputStream(fis, cipher1);
      fos = new FileOutputStream("/tmp/b.txt");
      byte[] b = new byte[8];
      int i = cis.read(b);
      while (i != -1) {
      fos.write(b, 0, i);
      i = cis.read(b);
      }

      The above program reads and encrypts the content from the file /tmp/a.txt and then stores the result (the encrypted bytes) in /tmp/b.txt.

      The following example demonstrates how to easily connect several instances of CipherInputStream and FileInputStream. In this example, assume that cipher1 and cipher2 have been initialized for encryption and decryption (with corresponding keys), respectively.

          FileInputStream fis;
      FileOutputStream fos;
      CipherInputStream cis1, cis2;

      fis = new FileInputStream("/tmp/a.txt");
      cis1 = new CipherInputStream(fis, cipher1);
      cis2 = new CipherInputStream(cis1, cipher2);
      fos = new FileOutputStream("/tmp/b.txt");
      byte[] b = new byte[8];
      int i = cis2.read(b);
      while (i != -1) {
      fos.write(b, 0, i);
      i = cis2.read(b);
      }

      The above program copies the content from file /tmp/a.txt to /tmp/b.txt, except that the content is first encrypted and then decrypted back when it is read from /tmp/a.txt. Of course since this program simply encrypts text and decrypts it back right away, it's actually not very useful except as a simple way of illustrating chaining of CipherInputStreams.

    • The CipherOutputStream Class

      This class is a FilterOutputStream that encrypts or decrypts the data passing through it. It is composed of an OutputStream, or one of its subclasses, and a Cipher. CipherOutputStream represents a secure output stream into which a Cipher object has been interposed. The write methods of CipherOutputStream first process the data with the embedded Cipher object before writing them out to the underlying OutputStream. The Cipher object must be fully initialized before being used by a CipherOutputStream.

      For example, if the embedded Cipher has been initialized for encryption, the CipherOutputStream will encrypt its data, before writing them out to the underlying output stream.

      This class adheres strictly to the semantics, especially the failure semantics, of its ancestor classes java.io.OutputStream and java.io.FilterOutputStream. This class has exactly those methods specified in its ancestor classes, and overrides them all, so that all data are additionally processed by the embedded cipher. Moreover, this class catches all exceptions that are not thrown by its ancestor classes.

      It is crucial for a programmer using this class not to use methods that are not defined or overridden in this class (such as a new method or constructor that is later added to one of the super classes), because the design and implementation of those methods are unlikely to have considered security impact with regard to CipherOutputStream.

      As an example of its usage, suppose cipher1 has been initialized for encryption. The code below demonstrates how to use a CipherOutputStream containing that cipher and a FileOutputStream in order to encrypt data to be written to an output stream:

          FileInputStream fis;
      FileOutputStream fos;
      CipherOutputStream cos;

      fis = new FileInputStream("/tmp/a.txt");
      fos = new FileOutputStream("/tmp/b.txt");
      cos = new CipherOutputStream(fos, cipher1);
      byte[] b = new byte[8];
      int i = fis.read(b);
      while (i != -1) {
      cos.write(b, 0, i);
      i = fis.read(b);
      }
      cos.flush();

      The above program reads the content from the file /tmp/a.txt, then encrypts and stores the result (the encrypted bytes) in /tmp/b.txt.

      The following example demonstrates how to easily connect several instances of CipherOutputStream and FileOutputStream. In this example, assume that cipher1 and cipher2 have been initialized for decryption and encryption (with corresponding keys), respectively:

          FileInputStream fis;
      FileOutputStream fos;
      CipherOutputStream cos1, cos2;

      fis = new FileInputStream("/tmp/a.txt");
      fos = new FileOutputStream("/tmp/b.txt");
      cos1 = new CipherOutputStream(fos, cipher1);
      cos2 = new CipherOutputStream(cos1, cipher2);
      byte[] b = new byte[8];
      int i = fis.read(b);
      while (i != -1) {
      cos2.write(b, 0, i);
      i = fis.read(b);
      }
      cos2.flush();

      The above program copies the content from file /tmp/a.txt to /tmp/b.txt, except that the content is first encrypted and then decrypted back before it is written to /tmp/b.txt.

      There is one important difference between the flush and close methods of this class, which becomes even more relevant if the encapsulated Cipher object implements a block cipher algorithm with padding turned on:

      flush flushes the underlying OutputStream by forcing any buffered output bytes that have already been processed by the encapsulated Cipher object to be written out. Any bytes buffered by the encapsulated Cipher object and waiting to be processed by it will not be written out.

      close closes the underlying OutputStream and releases any system resources associated with it. It invokes the doFinal method of the encapsulated Cipher object, causing any bytes buffered by it to be processed and written out to the underlying stream by calling its flush method.

  • The KeyGenerator Class

    A key generator is used to generate secret keys for symmetric algorithms.

    Creating a Key Generator

    Like other engine classes in the API, KeyGenerator objects are created using the getInstance factory methods of the KeyGenerator class. A factory method is a static method that returns an instance of a class, in this case, an instance of KeyGenerator which provides an implementation of the requested key generator.

    getInstance takes as its argument the name of a symmetric algorithm for which a secret key is to be generated. Optionally, a package provider name may be specified:

        public static KeyGenerator getInstance(String algorithm);

    public static KeyGenerator getInstance(String algorithm,
    String provider);

    If just an algorithm name is specified, the system will determine if there is an implementation of the requested key generator available in the environment, and if there is more than one, if there is a preferred one.

    If both an algorithm name and a package provider are specified, the system will determine if there is an implementation of the requested key generator in the package requested, and throw an exception if there is not.

    Initializing a KeyGenerator Object

    A key generator for a particular symmetric-key algorithm creates a symmetric key that can be used with that algorithm. It also associates algorithm-specific parameters (if any) with the generated key.

    There are two ways to generate a key: in an algorithm-independent manner, and in an algorithm-specific manner. The only difference between the two is the initialization of the object:

    • Algorithm-Independent Initialization

      All key generators share the concepts of a keysize and a source of randomness. There is an init method that takes these two universally shared types of arguments. There is also one that takes just a keysize argument, and uses a system-provided source of randomness, and one that takes just a source of randomness:

          public void init(SecureRandom random);

      public void init(int keysize);

      public void init(int keysize, SecureRandom random);

      Since no other parameters are specified when you call the above algorithm-independent init methods, it is up to the provider what to do about the algorithm-specific parameters (if any) to be associated with the generated key.

    • Algorithm-Specific Initialization

      For situations where a set of algorithm-specific parameters already exists, there are two init methods that have an AlgorithmParameterSpec argument. One also has a SecureRandom argument, while the source of randomness is system-provided for the other:

          public void init(AlgorithmParameterSpec params);

      public void init(AlgorithmParameterSpec params,
      SecureRandom random);

    In case the client does not explicitly initialize the KeyGenerator (via a call to an init method), each provider must supply (and document) a default initialization.

    Creating a Key

    The following method generates a secret key:
        public SecretKey generateKey();
  • The SecretKeyFactory Class

    This class represents a factory for secret keys.

    Key factories are used to convert keys (opaque cryptographic keys of type java.security.Key) into key specifications (transparent representations of the underlying key material in a suitable format), and vice versa.

    A javax.crypto.SecretKeyFactory object operates only on secret (symmetric) keys, whereas a java.security.KeyFactory object processes the public and private key components of a key pair.

    Objects of type java.security.Key, of which java.security.PublicKey, java.security.PrivateKey, and javax.crypto.SecretKey are subclasses, are opaque key objects, because you cannot tell how they are implemented. The underlying implementation is provider-dependent, and may be software or hardware based. Key factories allow providers to supply their own implementations of cryptographic keys.

    For example, if you have a key specification for a Diffie Hellman public key, consisting of the public value y, the prime modulus p, and the base g, and you feed the same specification to Diffie-Hellman key factories from different providers, the resulting PublicKey objects will most likely have different underlying implementations.

    A provider should document the key specifications supported by its secret key factory. For example, the SecretKeyFactory for DES keys supplied by the "SunJCE" provider supports DESKeySpec as a transparent representation of DES keys, the SecretKeyFactory for DES-EDE keys supports DESedeKeySpec as a transparent representation of DES-EDE keys, and the SecretKeyFactory for PBE supports PBEKeySpec as a transparent representation of the underlying password.

    The following is an example of how to use a SecretKeyFactory to convert secret key data into a SecretKey object, which can be used for a subsequent Cipher operation:

        // Note the following bytes are not realistic secret key data 
    // bytes but are simply supplied as an illustration of using data
    // bytes (key material) you already have to build a DESKeySpec.
    byte[] desKeyData = { (byte)0x01, (byte)0x02, (byte)0x03,
    (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08 };
    DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

    In this case, the underlying implementation of secretKey is based on the provider of keyFactory.

    An alternative, provider-independent way of creating a functionally equivalent SecretKey object from the same key material is to use the javax.crypto.spec.SecretKeySpec class, which implements the javax.crypto.SecretKey interface:

        byte[] desKeyData = { (byte)0x01, (byte)0x02, ...};
    SecretKeySpec secretKey = new SecretKeySpec(desKeyData, "DES");
  • The SealedObject Class

    This class enables a programmer to create an object and protect its confidentiality with a cryptographic algorithm.

    Given any object that implements the java.io.Serializable interface, one can create a SealedObject that encapsulates the original object, in serialized format (i.e., a "deep copy"), and seals (encrypts) its serialized contents, using a cryptographic algorithm such as DES, to protect its confidentiality. The encrypted content can later be decrypted (with the corresponding algorithm using the correct decryption key) and de-serialized, yielding the original object.

    A typical usage is illustrated in the following code segment: In order to seal an object, you create a SealedObject from the object to be sealed and a fully initialized Cipher object that will encrypt the serialized object contents. In this example, the String "This is a secret" is sealed using the DES algorithm. Note that any algorithm parameters that may be used in the sealing operation are stored inside of SealedObject:

        // create Cipher object
    // Note: sKey is assumed to refer to an already-generated
    // secret DES key.
    Cipher c = Cipher.getInstance("DES");
    c.init(Cipher.ENCRYPT_MODE, sKey);

    // do the sealing
    SealedObject so = new SealedObject("This is a secret", c);

    The original object that was sealed can be recovered in two different ways:

    • by using a Cipher object that has been initialized with the exact same algorithm, key, padding scheme, etc., that were used to seal the object:
          c.init(Cipher.DECRYPT_MODE, sKey);
      try {
      String s = (String)so.getObject(c);
      } catch (Exception e) {
      // do something
      };

      This approach has the advantage that the party who unseals the sealed object does not require knowledge of the decryption key. For example, after one party has initialized the cipher object with the required decryption key, it could hand over the cipher object to another party who then unseals the sealed object.

    • by using the appropriate decryption key (since DES is a symmetric encryption algorithm, we use the same key for sealing and unsealing):
          try {
      String s = (String)so.getObject(sKey);
      } catch (Exception e) {
      // do something
      };

      In this approach, the getObject method creates a cipher object for the appropriate decryption algorithm and initializes it with the given decryption key and the algorithm parameters (if any) that were stored in the sealed object. This approach has the advantage that the party who unseals the object does not need to keep track of the parameters (e.g., the IV) that were used to seal the object.

  • The KeyAgreement Class

    The KeyAgreement class provides the functionality of a key agreement protocol. The keys involved in establishing a shared secret are created by one of the key generators (KeyPairGenerator or KeyGenerator), a KeyFactory, or as a result from an intermediate phase of the key agreement protocol.

    Creating a KeyAgreement Object

    Each party involved in the key agreement has to create a KeyAgreement object. Like other engine classes in the API, KeyAgreement objects are created using the getInstance factory methods of the KeyAgreement class. A factory method is a static method that returns an instance of a class, in this case, an instance of KeyAgreement which provides the requested key agreement algorithm.

    getInstance takes as its argument the name of a key agreement algorithm. Optionally, a package provider name may be specified:

        public static KeyAgreement getInstance(String algorithm);

    public static KeyAgreement getInstance(String algorithm,
    String provider);

    If just an algorithm name is specified, the system will determine if there is an implementation of the requested key agreement available in the environment, and if there is more than one, if there is a preferred one.

    If both an algorithm name and a package provider are specified, the system will determine if there is an implementation of the requested key agreement in the package requested, and throw an exception if there is not.

    Initializing a KeyAgreement Object

    You initialize a KeyAgreement object with your private information. In the case of Diffie-Hellman, you initialize it with your Diffie-Hellman private key. Additional initialization information may contain a source of randomness and/or a set of algorithm parameters. Note that if the requested key agreement algorithm requires the specification of algorithm parameters, and only a key, but no parameters are provided to initialize the KeyAgreement object, the key must contain the required algorithm parameters. (For example, the Diffie-Hellman algorithm uses a prime modulus p and a base generator g as its parameters.)

    To initialize a KeyAgreement object, call one of its init methods:

        public void init(Key key);

    public void init(Key key, SecureRandom random);

    public void init(Key key, AlgorithmParameterSpec params);

    public void init(Key key, AlgorithmParameterSpec params,
    SecureRandom random);

    Executing a KeyAgreement Phase

    Every key agreement protocol consists of a number of phases that need to be executed by each party involved in the key agreement.

    To execute the next phase in the key agreement, call the doPhase method:

        public Key doPhase(Key key, boolean lastPhase);

    The key parameter contains the key to be processed by that phase. In most cases, this is the public key of one of the other parties involved in the key agreement, or an intermediate key that was generated by a previous phase. doPhase may return an intermediate key that you may have to send to the other parties of this key agreement, so they can process it in a subsequent phase.

    The lastPhase parameter specifies whether or not the phase to be executed is the last one in the key agreeement: A value of FALSE indicates that this is not the last phase of the key agreement (there are more phases to follow), and a value of TRUE indicates that this is the last phase of the key agreement and the key agreement is completed, i.e., generateSecret can be called next.

    In the example of Diffie-Hellman between two parties (see Appendix F), you call doPhase once, with lastPhase set to TRUE. In the example of Diffie-Hellman between three parties, you call doPhase twice: the first time with lastPhase set to FALSE, the 2nd time with lastPhase set to TRUE.

    Generating the Shared Secret

    After each party has executed all the required key agreement phases, it can compute the shared secret by calling one of the generateSecret methods:

        public byte[] generateSecret();

    public int generateSecret(byte[] sharedSecret, int offset);

    public SecretKey generateSecret(String algorithm);
  • The Mac Class

    The Mac class provides the functionality of a Message Authentication Code (MAC). Please refer to the code example in Appendix F.

    Creating a Mac Object

    Like other engine classes in the API, Mac objects are created using the getInstance factory methods of the Mac class. A factory method is a static method that returns an instance of a class, in this case, an instance of Mac which provides the requested MAC algorithm.

    getInstance takes as its argument the name of a MAC algorithm. Optionally, a package provider name may be specified:

        public static Mac getInstance(String algorithm);

    public static Mac getInstance(String algorithm,
    String provider);

    If just an algorithm name is specified, the system will determine if there is an implementation of the requested MAC algorithm available in the environment, and if there is more than one, if there is a preferred one.

    If both an algorithm name and a package provider are specified, the system will determine if there is an implementation of the requested MAC algorithm in the package requested, and throw an exception if there is not.

    Initializing a Mac Object

    A Mac object is always initialized with a (secret) key and may optionally be initialized with a set of parameters, depending on the underlying MAC algorithm.

    To initialize a Mac object, call one of its init methods:

        public void init(Key key);

    public void init(Key key, AlgorithmParameterSpec params);

    You can initialize your Mac object with any (secret-)key object that implements the javax.crypto.SecretKey interface. This could be an object returned by javax.crypto.KeyGenerator.generateKey(), or one that is the result of a key agreement protocol, as returned by javax.crypto.KeyAgreement.generateSecret(), or an instance of javax.crypto.spec.SecretKeySpec.

    With some MAC algorithms, the (secret-)key algorithm associated with the (secret-)key object used to initialize the Mac object does not matter (this is the case with the HMAC-MD5 and HMAC-SHA1 implementations of the SunJCE provider). With others, however, the (secret-)key algorithm does matter, and an InvalidKeyException is thrown if a (secret-)key object with an inappropriate (secret-)key algorithm is used.

    Computing a MAC

    A MAC can be computed in one step (single-part operation) or in multiple steps (multiple-part operation). A multiple-part operation is useful if you do not know in advance how long the data is going to be, or if the data is too long to be stored in memory all at once.

    To compute the MAC of some data in a single step, call the following doFinal method:

        public byte[] doFinal(byte[] input);

    To compute the MAC of some data in multiple steps, call one of the update methods:

        public void update(byte input);

    public void update(byte[] input);

    public void update(byte[] input, int inputOffset, int inputLen);

    A multiple-part operation must be terminated by the above doFinal method (if there is still some input data left for the last step), or by one of the following doFinal methods (if there is no input data left for the last step):

        public byte[] doFinal();

    public void doFinal(byte[] output, int outOffset);

How to Make Applications "Exempt" from Cryptographic Restrictions

[Note 1: This section should be ignored by most application developers. It is only for people whose applications may be exported to those few countries whose governments mandate cryptographic restrictions, if it desired that such applications have fewer cryptographic restrictions than those mandated. If you want to skip this section, you can go on to Installing JCE Providers for JDK 5.0.]
[Note 2: Throughout this section, the term "application" is meant to encompass both applications and applets.]

The JCE framework within JDK 5.0 includes an ability to enforce restrictions regarding the cryptographic algorithms and maximum cryptographic strengths available to applets/applications in different jurisdiction contexts (locations). Any such restrictions are specified in "jurisdiction policy files".

Due to import control restrictions by the governments of a few countries, the jurisdiction policy files shipped with the JDK 5.0 from Sun Microsystems specify that "strong" but limited cryptography may be used. An "unlimited strength" version of these files indicating no restrictions on cryptographic strengths is available for those living in eligible countries (which is most countries). But only the "strong" version can be imported into those countries whose governments mandate restrictions. The JCE framework will enforce the restrictions specified in the installed jurisdiction policy files.

It is possible that the governments of some or all such countries may allow certain applications to become exempt from some or all cryptographic restrictions. For example, they may consider certain types of applications as "special" and thus exempt. Or they may exempt any application that utilizes an "exemption mechanism," such as key recovery. Applications deemed to be exempt could get access to stronger cryptography than that allowed for non-exempt applications in such countries.

In order for an application to be recognized as "exempt" at runtime, it must meet the following conditions:

  • It must have a permission policy file bundled with it in a JAR file. The permission policy file specifies what cryptography-related permissions the application has, and under what conditions (if any).
  • The JAR file containing the application and the permission policy file must have been signed using a code-signing certificate issued after the application was accepted as exempt.

Below are sample steps required in order to make an application exempt from some or all cryptographic restrictions. This is a basic outline that includes information about what is required by JCE in order to recognize and treat applications as being exempt. You will need to know the exemption requirements of the particular country or countries in which you would like your application to be able to be run but whose governments require cryptographic restrictions. You will also need to know the requirements of a JCE framework vendor that has a process in place for handling exempt applications. Consult such a vendor for further information. (Note: The SunJCE provider does not supply an implementation of the ExemptionMechanismSpi class.)

  • Step 1: Write and Compile Your Application Code
  • Step 2: Create a Permission Policy File Granting Appropriate Cryptographic Permissions
  • Step 3: Prepare for Testing
  • Step 3a: Apply for Government Approval From the Government Mandating Restrictions.
  • Step 3b: Get a Code-Signing Certificate
  • Step 3c: Bundle the Application and Permission Policy File into a JAR file
  • Step 3d: Sign the JAR file
  • Step 3e: Set Up Your Environment Like That of a User in a Restricted Country
  • Step 3f: (only for apps using exemption mechanisms) Install a Provider Implementing the Exemption Mechanism Specified in the Permission Policy File
  • Step 4: Test Your Application
  • Step 5: Apply for U.S. Government Export Approval If Required
  • Step 6: Deploy Your Application

Special Code Requirements for Applications that Use Exemption Mechanisms

When an application has a permission policy file associated with it (in the same JAR file) and that permission policy file specifies an exemption mechanism, then when the Cipher getInstance method is called to instantiate a Cipher, the JCE code searches the installed providers for one that implements the specified exemption mechanism. If it finds such a provider, JCE instantiates an ExemptionMechanism API object associated with the provider's implementation, and then associates the ExemptionMechanism object with the Cipher returned by getInstance.

After instantiating a Cipher, and prior to initializing it (via a call to the Cipher init method), your code must call the following Cipher method:

    public ExemptionMechanism getExemptionMechanism()

This call returns the ExemptionMechanism object associated with the Cipher. You must then initialize the exemption mechanism implementation by calling the following method on the returned ExemptionMechanism:

     public final void init(Key key)

The argument you supply should be the same as the argument of the same types that you will subsequently supply to a Cipher init method.

Once you have initialized the ExemptionMechanism, you can proceed as usual to initialize and use the Cipher.

Permission Policy Files

In order for an application to be recognized at runtime as being "exempt" from some or all cryptographic restrictions, it must have a permission policy file bundled with it in a JAR file. The permission policy file specifies what cryptography-related permissions the application has, and under what conditions (if any).

Note: The permission policy file bundled with an application must be named cryptoPerms.

The format of a permission entry in a permission policy file that accompanies an exempt application is the same as the format for a jurisdiction policy file downloaded with the JDK 5.0, which is:

permission <crypto permission class name>[ <alg_name>
[[, <exemption mechanism name>][, <maxKeySize>
[, <AlgorithmParameterSpec class name>,
<parameters for constructing an AlgorithmParameterSpec object>]]]];

See Appendix D for more information about the jurisdiction policy file format.

Permission Policy Files for Exempt Applications

Some applications may be allowed to be completely unrestricted. Thus, the permission policy file that accompanies such an application usually just needs to contain the following:

grant {
// There are no restrictions to any algorithms.
permission javax.crypto.CryptoAllPermission;
};

If an application just uses a single algorithm (or several specific algorithms), then the permission policy file could simply mention that algorithm (or algorithms) explicitly, rather than granting CryptoAllPermission. For example, if an application just uses the Blowfish algorithm, the permission policy file doesn't have to grant CryptoAllPermission to all algorithms. It could just specify that there is no cryptographic restriction if the Blowfish algorithm is used. In order to do this, the permission policy file would look like the following:

grant {
permission javax.crypto.CryptoPermission "Blowfish";
};

Permission Policy Files for Applications Exempt Due to Exemption Mechanisms

If an application is considered "exempt" if an exemption mechanism is enforced, then the permission policy file that accompanies the application must specify one or more exemption mechanisms. At runtime, the application will be considered exempt if any of those exemption mechanisms is enforced. Each exemption mechanism must be specified in a permission entry that looks like the following:

    // No algorithm restrictions if specified
// exemption mechanism is enforced.
permission javax.crypto.CryptoPermission *,
"<ExemptionMechanismName>";

where <ExemptionMechanismName> specifies the name of an exemption mechanism. The list of possible exemption mechanism names includes:

  • KeyRecovery
  • KeyEscrow
  • KeyWeakening
As an example, suppose your application is exempt if either key recovery or key escrow is enforced. Then your permission policy file should contain the following:
grant {
// No algorithm restrictions if KeyRecovery is enforced.
permission javax.crypto.CryptoPermission *,
"KeyRecovery";
// No algorithm restrictions if KeyEscrow is enforced.
permission javax.crypto.CryptoPermission *,
"KeyEscrow";
};

Note: Permission entries that specify exemption mechanisms should not also specify maximum key sizes. The allowed key sizes are actually determined from the installed exempt jurisdiction policy files, as described in the next section.

How Bundled Permission Policy Files Affect Cryptographic Permissions

At runtime, when an application instantiates a Cipher (via a call to its getInstance method) and that application has an associated permission policy file, JCE checks to see whether the permission policy file has an entry that applies to the algorithm specified in the getInstance call. If it does, and the entry grants CryptoAllPermission or does not specify that an exemption mechanism must be enforced, it means there is no cryptographic restriction for this particular algorithm.

If the permission policy file has an entry that applies to the algorithm specified in the getInstance call and the entry does specify that an exemption mechanism must be enforced, then the exempt jurisdiction policy file(s) are examined. If the exempt permissions include an entry for the relevant algorithm and exemption mechanism, and that entry is implied by the permissions in the permission policy file bundled with the application, and if there is an implementation of the specified exemption mechanism available from one of the registered providers, then the maximum key size and algorithm parameter values for the Cipher are determined from the exempt permission entry.

If there is no exempt permission entry implied by the relevant entry in the permission policy file bundled with the application, or if there is no implementation of the specified exemption mechanism available from any of the registered providers, then the application is only allowed the standard default cryptographic permissions.


Installing JCE Providers for JDK 5.0

In order to be used, a cryptographic provider must be installed and registered, either statically or dynamically. Cryptographic providers for JCE in JDK 5.0 are installed and configured the same way as all other providers for the JavaTM 2 platform. More information about installing and configuring providers can be found in the Installing Providers section of the JavaTM Cryptography Architecture API Specification & Reference document.

You do not need to register the "SunJCE" provider because it is pre-registered. If you want to use other providers, read the following sections to see how to register them.

Installing a provider is done in two steps: installing the provider package classes, and configuring the provider. In some situations you will also need to set permissions for the provider prior to using it.

Installing the Provider Classes

The first thing you must do is make the provider classes available so that they can be found when requested. Provider classes are shipped as a signed JAR (Java ARchive) file.

There are two possible ways to install the provider classes:

  • Install the JAR file containing the provider classes as an "installed" or "bundled" extension.
  • Place the JAR file containing the provider classes in your class path.

The provider JAR file will be considered an installed extension if it is placed in the standard place for the JAR files of an installed extension:

<java-home>/lib/ext         [Solaris]
<java-home>\lib\ext [Windows]

Here <java-home> refers to the directory where the runtime software is installed, which is the top-level directory of the JavaTM 2 Runtime Environment (JRE) or the jre directory in the JavaTM 2 SDK (Java 2 SDK) software. For example, if you have JDK 5.0 installed on Solaris in a directory named /home/user1/JDK1.5.0, or on Microsoft Windows in a directory named C:\Java DK1.5.0, then you need to install the JAR file in the following directory:

/home/user1/JDK1.5.0/jre/lib/ext    [Solaris]
C:\JDK1.5.0\jre\lib\ext [Windows]

Similarly, if you have the JRE 5.0 installed on Solaris in a directory named /home/user1/jre1.5.0, or on Microsoft Windows in a directory named C:\jre1.5.0, you need to install the JAR file in the following directory:

/home/user1/jre1.5.0/lib/ext         [Solaris]
C:\jre1.5.0\lib\ext [Windows]

For more information, refer to these sections in the "Extension Mechanism Architecture" specification: Installed Extensions and Bundled Extensions.

Configuring the Provider

The next step is to add the provider to your list of approved providers. This is done statically by editing the security properties file

<java-home>/lib/security/java.security     [Solaris]
<java-home>\lib\security\java.security [Windows]

Here <java-home> refers to the directory where the JRE was installed. For example, if you have JDK 5.0 installed on Solaris in a directory named /home/user1/JDK1.5.0, or on Microsoft Windows in a directory named C:\JDK1.5.0, then you need to edit the following file:

/home/user1/JDK1.5.0/jre/lib/security/java.security  [Solaris]
C:\JDK1.5.0\jre\lib\security\java.security [Windows]

Similarly, if you have the Java 2 Runtime Environment, v 1.4 installed on Solaris in a directory named /home/user1/jre1.5.0, or on Microsoft Windows in a directory named C:\jre1.5.0, then you need to edit this file:

/home/user1/jre1.5.0/lib/security/java.security       [Solaris]
C:\jre1.5.0\lib\security\java.security [Windows]

For each provider, this file should have a statement of the following form:

    security.provider.n=masterClassName
    

This declares a provider, and specifies its preference order n. The preference order is the order in which providers are searched for requested algorithms when no specific provider is requested. The order is 1-based; 1 is the most preferred, followed by 2, and so on.

masterClassName must specify the fully qualified name of the provider's "master class". The provider vendor should supply you this name.

JDK 5.0 comes standard with a provider named "SUN", which is automatically configured as a static provider in the java.security properties file, as follows:

security.provider.1=sun.security.provider.Sun

(The "SUN" provider's master class is the Sun class in the sun.security.provider package.)

The JCE provider "SunJCE" and other security-related providers shipped with the Java 2 platform are also automatically configured as static providers.

To utilize another JCE provider, add a line registering the alternate provider, giving it whatever preference order you prefer (and making corresponding adjustments to the other providers' orders, if needed).

Suppose that the master class of a provider you want to register is the CryptoX class in the com.cryptox.provider package, and that you would like to make this provider the second preferred provider. To do so, add the following line to the java.security file below the line for the "SUN" provider, and increment the preference order numbers for all other providers whose numbers were greater than or equal to 2 before your addition:

    security.provider.2=com.cryptox.provider.CryptoX
Note: Providers may also be registered dynamically. To do so, a program can call either the addProvider or insertProviderAt method in the Security class. This type of registration is not persistent and can only be done by code which is granted the following permission:
java.security.SecurityPermission "insertProvider.{name}"
where {name} is replaced by the actual provider name. For example, if the provider name is "MyJCE" and if your code that dynamically registers this provider is in the MyApp.jar file in the /localWork directory, then here is a sample policy file grant statement granting that permission:
grant codeBase "file:/localWork/MyApp.jar" {
permission java.security.SecurityPermission
"insertProvider.MyJCE";
};

Setting Provider Permissions

Whenever JCE providers are not installed extensions, permissions must be granted for when applets or applications using JCE are run while a security manager is installed. There is typically a security manager installed whenever an applet is running, and a security manager may be installed for an application either via code in the application itself or via a command-line argument. Permissions do not need to be granted to installed extensions, since the default system policy configuration file grants all permissions to installed extensions.

The documentation from the vendor of each provider you will be using should include information as to which permissions it requires, and how to grant such permissions. For example, the following permissions may be needed by a provider if it is not an installed extension and a security manager is installed:

  • java.lang.RuntimePermission to get class protection domains. The provider may need to get its own protection domain in the process of doing self-integrity checking.
  • java.security.SecurityPermission "putProviderProperty.{name}" to set provider properties, where {name} is replaced by the actual provider name.

For example, a sample statement granting permissions to a provider whose name is "MyJCE" and whose code is in myjce_provider.jar appears below. Such a statement could appear in a policy file. In this example, the myjce_provider.jar file is assumed to be in the /localWork directory.

grant codeBase "file:/localWork/myjce_provider.jar" {
permission java.lang.RuntimePermission "getProtectionDomain";
permission java.security.SecurityPermission
"putProviderProperty.MyJCE";
};

JCE Keystore

The "SunJCE" provider supplies its own implementation of the java.security.KeyStore class in the JDK 5.0. Its implementation employs a much stronger protection of private keys (using password-based encryption with Triple DES) than the keystore implementation supplied by the "SUN" provider in the JDK 5.0 (Note that because the JDK 5.0 is distributed world-wide in binary and source format, it cannot employ any strong encryption mechanisms.)

In order to take advantage of the keystore implementation of the "SunJCE" provider, you specify "JCEKS" as the keystore type.

You may upgrade your keystore of type "JKS" - this is the name of the keystore type implemented by the "SUN" provider in the Java 2 SDK - to a JCE keystore of type "JCEKS" by changing the password of a private-key entry in your keystore.

To apply the cryptographically strong(er) key protection supplied by "SunJCE" to a private key named "signkey" in your default keystore, use the following command, which will prompt you for the old and new key passwords:

    keytool -keypasswd -alias signkey -storetype jceks

You may want to change the password back to its old value, using the same command.

See Security Tools for more information about keytool and about keystores and how they are managed.


Code Examples

This section is a short tutorial on how to use some of the major features of the JCE APIs in the JDK 5.0 Complete sample programs that exercise the APIs can be found in Appendix F of this document.

Using Encryption

This section takes the user through the process of generating a key, creating and initializing a cipher object, encrypting a file, and then decrypting it. Throughout this example, we use the Data Encryption Standard (DES).

Generating a Key

To create a DES key, we have to instantiate a KeyGenerator for DES. We do not specify a provider, because we do not care about a particular DES key generation implementation. Since we do not initialize the KeyGenerator, a system-provided source of randomness will be used to create the DES key:

    KeyGenerator keygen = KeyGenerator.getInstance("DES");
SecretKey desKey = keygen.generateKey();

After the key has been generated, the same KeyGenerator object can be re-used to create further keys.

Creating a Cipher

The next step is to create a Cipher instance. To do this, we use one of the getInstance factory methods of the Cipher class. We must specify the name of the requested transformation, which includes the following components, separated by slashes (/):

  • the algorithm name
  • the mode (optional)
  • the padding scheme (optional)

In this example, we create a DES (Data Encryption Standard) cipher in Electronic Codebook mode, with PKCS #5-style padding. We do not specify a provider, because we do not care about a particular implementation of the requested transformation.

The standard algorithm name for DES is "DES", the standard name for the Electronic Codebook mode is "ECB", and the standard name for PKCS #5-style padding is "PKCS5Padding":

    Cipher desCipher;

// Create the cipher
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

We use the generated desKey from above to initialize the Cipher object for encryption:

    // Initialize the cipher for encryption
desCipher.init(Cipher.ENCRYPT_MODE, desKey);

// Our cleartext
byte[] cleartext = "This is just an example".getBytes();

// Encrypt the cleartext
byte[] ciphertext = desCipher.doFinal(cleartext);

// Initialize the same cipher for decryption
desCipher.init(Cipher.DECRYPT_MODE, desKey);

// Decrypt the ciphertext
byte[] cleartext1 = desCipher.doFinal(ciphertext);

cleartext and cleartext1 are identical.

Using Password-Based Encryption

In this example, we prompt the user for a password from which we derive an encryption key.

It would seem logical to collect and store the password in an object of type java.lang.String. However, here's the caveat: Objects of type String are immutable, i.e., there are no methods defined that allow you to change (overwrite) or zero out the contents of a String after usage. This feature makes String objects unsuitable for storing security sensitive information such as user passwords. You should always collect and store security sensitive information in a char array instead.

For that reason, the javax.crypto.spec.PBEKeySpec class takes (and returns) a password as a char array.

The following method is an example of how to collect a user password as a char array:

    /**
* Reads user password from given input stream.
*/
public char[] readPasswd(InputStream in) throws IOException {
char[] lineBuffer;
char[] buf;
int i;

buf = lineBuffer = new char[128];

int room = buf.length;
int offset = 0;
int c;

loop: while (true) {
switch (c = in.read()) {
case -1:
case '\n':
break loop;

case '\r':
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) {
if (!(in instanceof PushbackInputStream)) {
in = new PushbackInputStream(in);
}
((PushbackInputStream)in).unread(c2);
} else
break loop;

default:
if (--room < 0) {
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
Arrays.fill(lineBuffer, ' ');
lineBuffer = buf;
}
buf[offset++] = (char) c;
break;
}
}

if (offset == 0) {
return null;
}

char[] ret = new char[offset];
System.arraycopy(buf, 0, ret, 0, offset);
Arrays.fill(buf, ' ');

return ret;
}

In order to use Password-Based Encryption (PBE) as defined in PKCS #5, we have to specify a salt and an iteration count. The same salt and iteration count that are used for encryption must be used for decryption:

    PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;

// Salt
byte[] salt = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};

// Iteration count
int count = 20;

// Create PBE parameter set
pbeParamSpec = new PBEParameterSpec(salt, count);

// Prompt user for encryption password.
// Collect user password as char array (using the
// "readPasswd" method from above), and convert
// it into a SecretKey object, using a PBE key
// factory.
System.out.print("Enter encryption password: ");
System.out.flush();
pbeKeySpec = new PBEKeySpec(readPasswd(System.in));
keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

// Our cleartext
byte[] cleartext = "This is another example".getBytes();

// Encrypt the cleartext
byte[] ciphertext = pbeCipher.doFinal(cleartext);

Using Key Agreement

Please refer to Appendix F for sample programs exercising the Diffie-Hellman key exchange between 2 and 3 parties, respectively.


Appendix A: Standard Names

The JCE API requires and utilizes a set of standard names for algorithms, algorithm modes, and padding schemes. This specification establishes the following names as standard names. It supplements the list of standard names defined in Appendix A in the JavaTM Cryptography Architecture API Specification & Reference. Note that algorithm names are treated case-insensitively.

In some cases naming conventions are suggested for forming names that are not explicitly listed, to facilitate name consistency across provider implementations. Such suggestions use items in angle brackets (such as <digest> and <encryption>) as placeholders to be replaced by specific message digest, encryption algorithm, and other names.

Cipher

Algorithm

The following names can be specified as the algorithm component in a transformation when requesting an instance of Cipher:

  • AES: Advanced Encryption Standard as specified by NIST in a draft FIPS. Based on the Rijndael algorithm by Joan Daemen and Vincent Rijmen, AES is a 128-bit block cipher supporting keys of 128, 192, and 256 bits.
  • ARCFOUR/RC4: A stream cipher developed by Ron Rivest. For more information, see K. Kaukonen and R. Thayer, "A Stream Cipher Encryption Algorithm 'Arcfour'", Internet Draft (expired), draft-kaukonen-cipher-arcfour-03.txt.
  • Blowfish: The block cipher designed by Bruce Schneier.
  • DES: The Digital Encryption Standard as described in FIPS PUB 46-2.
  • DESede: Triple DES Encryption (DES-EDE).
  • ECIES (Elliptic Curve Integrated Encryption Scheme)
  • PBEWith<digest>And<encryption> or PBEWith<prf>And<encryption>: The password-based encryption algorithm (PKCS #5), using the specified message digest (<digest>) or pseudo-random function (<prf>) and encryption algorithm (<encryption>). Examples:
    • PBEWithMD5AndDES: The password-based encryption algorithm as defined in: RSA Laboratories, "PKCS #5: Password-Based Encryption Standard," version 1.5, Nov 1993. Note that this algorithm implies CBC as the cipher mode and PKCS5Padding as the padding scheme and cannot be used with any other cipher modes or padding schemes.
    • PBEWithHmacSHA1AndDESede: The password-based encryption algorithm as defined in: RSA Laboratories, "PKCS #5: Password-Based Cryptography Standard," version 2.0, March 1999.
  • RC2, RC4, and RC5: Variable-key-size encryption algorithms developed by Ron Rivest for RSA Data Security, Inc.
  • RSA: The RSA encryption algorithm as defined in PKCS #1.

Mode

The following names can be specified as the mode component in a transformation when requesting an instance of Cipher:

  • NONE: No mode.
  • CBC: Cipher Block Chaining Mode, as defined in FIPS PUB 81.
  • CFB: Cipher Feedback Mode, as defined in FIPS PUB 81.
  • ECB: Electronic Codebook Mode, as defined in: The National Institute of Standards and Technology (NIST) Federal Information Processing Standard (FIPS) PUB 81, "DES Modes of Operation," U.S. Department of Commerce, Dec 1980.
  • OFB: Output Feedback Mode, as defined in FIPS PUB 81.
  • PCBC: Propagating Cipher Block Chaining, as defined by Kerberos V4.

Padding

The following names can be specified as the padding component in a transformation when requesting an instance of Cipher:

  • ISO10126Padding. This padding for block ciphers is described in 5.2 Block Encryption Algorithms in the W3C's "XML Encryption Syntax and Processing" document.
  • NoPadding: No padding.
  • OAEPWith<digest>And<mgf>Padding: Optimal Asymmetric Encryption Padding scheme defined in PKCS #1, where <digest> should be replaced by the message digest and <mgf> by the mask generation function. Example: OAEPWithMD5AndMGF1Padding.
  • PKCS5Padding: The padding scheme described in: RSA Laboratories, "PKCS #5: Password-Based Encryption Standard," version 1.5, November 1993.
  • SSL3Padding: The padding scheme defined in the SSL Protocol Version 3.0, November 18, 1996, section 5.2.3.2 (CBC block cipher):
        block-ciphered struct {
    opaque content[SSLCompressed.length];
    opaque MAC[CipherSpec.hash_size];
    uint8 padding[GenericBlockCipher.padding_length];
    uint8 padding_length;
    } GenericBlockCipher;

    The size of an instance of a GenericBlockCipher must be a multiple of the block cipher's block length.

    The padding length, which is always present, contributes to the padding, which implies that if:

        sizeof(content) + sizeof(MAC) % block_length = 0,
    padding has to be (block_length - 1) bytes long, because of the existence of padding_length.

    This make the padding scheme similar (but not quite) to PKCS5Padding, where the padding length is encoded in the padding (and ranges from 1 to block_length). With the SSL scheme, the sizeof(padding) is encoded in the always present padding_length and therefore ranges from 0 to block_length-1.

    Note that this padding mechanism is not supported by the "SunJCE" provider.

KeyAgreement

The following algorithm names can be specified when requesting an instance of KeyAgreement:

  • DiffieHellman: Diffie-Hellman Key Agreement as defined in PKCS #3: Diffie-Hellman Key-Agreement Standard, RSA Laboratories, version 1.4, November 1993.
  • ECDH (Elliptic Curve Diffie-Hellman) as described in RFC 3278: "Use of Elliptic Curve Cryptography (ECC) Algorithms in Cryptographic Message Syntax (CMS)."
  • ECMQV (Elliptic Curve Menezes-Qu-Vanstone) as described in ECC Cipher Suites For TLS (January 2004 draft).

KeyGenerator

The following algorithm names can be specified when requesting an instance of KeyGenerator:

  • AES
  • ARCFOUR/RC4
  • Blowfish
  • DES
  • DESede
  • HmacMD5
  • HmacSHA1
  • HmacSHA256
  • HmacSHA384
  • HmacSHA512
  • RC2

KeyPairGenerator

The following algorithm names can be specified when requesting an instance of KeyPairGenerator:

  • DiffieHellman

SecretKeyFactory

The following algorithm names can be specified when requesting an instance of SecretKeyFactory:

  • DES
  • DESede
  • PBEWith<digest>And<encryption> or PBEWith<prf>And<encryption>: Secret-key factory for use with PKCS #5 password-based encryption, where <digest> is a message digest, <prf> is a pseudo-random function, and <encryption> is an encryption algorithm. Examples: PBEWithMD5AndDES (PKCS #5, v 1.5) and PBEWithHmacSHA1AndDESede (PKCS #5, v 2.0). Note: These both use only the low order 8 bits of each password character.

KeyFactory

The following algorithm names can be specified when requesting an instance of KeyFactory:

  • DiffieHellman

AlgorithmParameterGenerator

The following algorithm names can be specified when requesting an instance of AlgorithmParameterGenerator:

  • DiffieHellman

AlgorithmParameters

The following algorithm names can be specified when requesting an instance of AlgorithmParameters:

  • AES
  • Blowfish
  • DES
  • DESede
  • DiffieHellman
  • OAEP
  • PBE
  • PBEWith<digest>And<encryption>
  • RC2

MAC

The following algorithm names can be specified when requesting an instance of Mac:

  • HmacMD5: The HMAC-MD5 keyed-hashing algorithm as defined in RFC 2104: "HMAC: Keyed-Hashing for Message Authentication" (February 1997).
  • HmacSHA1: The HMAC-SHA1 keyed-hashing algorithm as defined in RFC 2104: "HMAC: Keyed-Hashing for Message Authentication" (February 1997).
  • HmacSHA256: The HmacSHA256 algorithm as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-256 as the message digest algorithm.
  • HmacSHA384: The HmacSHA384 algorithm as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-384 as the message digest algorithm.
  • HmacSHA512: The HmacSHA512 algorithm as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-512 as the message digest algorithm.
  • PBEWith<mac>: MAC for use with PKCS #5 v 2.0 password-based message authentication standard, where <mac> is a Message Authentication Code algorithm name. Example: PBEWithHmacSHA1.

Keystore Types

The following types can be specified when requesting an instance of KeyStore:

Exemption Mechanisms

The following exemption mechanism names can be specified in the permission policy file that accompanies an application considered "exempt" from cryptographic restrictions:

  • KeyEscrow: An encryption system with a backup decryption capability that allows authorized persons (users, officers of an organization, and government officials), under certain prescribed conditions, to decrypt ciphertext with the help of information supplied by one or more trusted parties who hold special data recovery keys.
  • KeyRecovery: A method of obtaining the secret key used to lock encrypted data. One use is as a means of providing fail-safe access to a corporation's own encrypted information in times of disaster.
  • KeyWeakening: A method in which a part of the key can be escrowed or recovered.

Appendix B: SunJCE Default Keysizes

The SunJCE provider uses the following default keysizes:

  • KeyGenerator
    • DES: 56 bits
    • Triple DES: 112 bits
    • Blowfish: 56 bits
    • HmacMD5: 64 bytes
    • HmacSHA1: 64 bytes
  • KeyPairGenerator
    • Diffie-Hellman: 1024 bits
  • AlgorithmParameterGenerator
    • Diffie-Hellman: 1024 bits

Appendix C: SunJCE Keysize Restrictions

The SunJCE provider enforces the following restrictions on the keysize passed to the initialization methods of the following classes:

  • KeyGenerator

    Restrictions (by algorithm):

    • DES: keysize must be equal to 56
    • Triple DES: keysize must be equal to 112 or 168

      Note: A keysize of 112 will generate a Triple DES key with 2 intermediate keys, and a keysize of 168 will generate a Triple DES key with 3 intermediate keys.

    • Blowfish: keysize must be a multiple of 8, and can only range from 32 to 448, inclusive
  • KeyPairGenerator

    Restrictions (by algorithm):

    • Diffie-Hellman: keysize must be a multiple of 64, and can only range from 512 to 1024, inclusive
  • AlgorithmParameterGenerator

    Restrictions (by algorithm):

    • Diffie-Hellman: keysize must be a multiple of 64, and can only range from 512 to 1024, inclusive

Appendix D: Jurisdiction Policy File Format

JCE represents its jurisdiction policy files as J2SE-style policy files with corresponding permission statements. As described in Default Policy Implementation and Policy File Syntax, a J2SE policy file specifies what permissions are allowed for code from specified code sources. A permission represents access to a system resource. In the case of JCE, the "resources" are cryptography algorithms, and code sources do not need to be specified, because the cryptographic restrictions apply to all code.

A jurisdiction policy file consists of a very basic "grant entry" containing one or more "permission entries."

grant {
<permission entries>;
};

The format of a permission entry in a jurisdiction policy file is:

permission <crypto permission class name>[ <alg_name>
[[, <exemption mechanism name>][, <maxKeySize>
[, <AlgorithmParameterSpec class name>,
<parameters for constructing an
AlgorithmParameterSpec object>]]]];

A sample jurisdiction policy file that includes restricting the "Blowfish" algorithm to maximum key sizes of 64 bits is:

grant {
permission javax.crypto.CryptoPermission "Blowfish", 64;
. . .;
};

A permission entry must begin with the word permission. The <crypto permission class name> in the template above would actually be a specific permission class name, such as javax.crypto.CryptoPermission. A crypto permission class reflects the ability of an application/applet to use certain algorithms with certain key sizes in certain environments. There are two crypto permission classes: CryptoPermission and CryptoAllPermission. The special CryptoAllPermission class implies all cryptography-related permissions, that is, it specifies that there are no cryptography-related restrictions.

The <alg_name>, when utilized, is a quoted string specifying the standard name (see Appendix A) of a cryptography algorithm, such as "DES" or "RSA".

The <exemption mechanism name>, when specified, is a quoted string indicating an exemption mechanism which, if enforced, enables a reduction in cryptographic restrictions. Exemption mechanism names that can be used include "KeyRecovery" "KeyEscrow", and "KeyWeakening".

<maxKeySize> is an integer specifying the maximum key size (in bits) allowed for the specified algorithm.

For some algorithms it may not be sufficient to specify the algorithm strength in terms of just a key size. For example, in the case of the "RC5" algorithm, the number of rounds must also be considered. For algorithms whose strength needs to be expressed as more than a key size, the permission entry should also specify an AlgorithmParameterSpec class name (such as javax.crypto.spec.RC5ParameterSpec) and a list of parameters for constructing the specified AlgorithmParameterSpec object.

Items that appear in a permission entry must appear in the specified order. An entry is terminated with a semicolon.

Case is unimportant for the identifiers (grant, permission) but is significant for the <crypto permission class name> or for any string that is passed in as a value.

Note: An "*" can be used as a wildcard for any permission entry option. For example, an "*" (without the quotes) for an <alg_name> option means "all algorithms."


Appendix E: Maximum Key Sizes Allowed by "Strong" Jurisdiction Policy Files

Due to import control restrictions, the jurisdiction policy files shipped with JDK 5.0 allow "strong" but limited cryptography to be used. Here are the maximum key sizes allowed by this "strong" version of the jurisdiction policy files:

Algorithm

Maximum Key Size

DES

64

DESede

*

RC2

128

RC4

128

RC5

128

RSA

2048

* (all others)

128


Appendix F: Sample Programs

  • Diffie-Hellman Key Exchange between 2 Parties

    /*
    * Copyright 1997-2001 by Sun Microsystems, Inc.,
    * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
    * All rights reserved.
    *
    * This software is the confidential and proprietary information
    * of Sun Microsystems, Inc. ("Confidential Information"). You
    * shall not disclose such Confidential Information and shall use
    * it only in accordance with the terms of the license agreement
    * you entered into with Sun.
    */

    import java.io.*;
    import java.math.BigInteger;
    import java.security.*;
    import java.security.spec.*;
    import java.security.interfaces.*;
    import javax.crypto.*;
    import javax.crypto.spec.*;
    import javax.crypto.interfaces.*;
    import com.sun.crypto.provider.SunJCE;

    /**
    * This program executes the Diffie-Hellman key agreement protocol
    * between 2 parties: Alice and Bob.
    *
    * By default, preconfigured parameters (1024-bit prime modulus and base
    * generator used by SKIP) are used.
    * If this program is called with the "-gen" option, a new set of
    * parameters is created.
    */

    public class DHKeyAgreement2 {

    private DHKeyAgreement2() {}

    public static void main(String argv[]) {
    try {
    String mode = "USE_SKIP_DH_PARAMS";

    DHKeyAgreement2 keyAgree = new DHKeyAgreement2();

    if (argv.length > 1) {
    keyAgree.usage();
    throw new Exception("Wrong number of command options");
    } else if (argv.length == 1) {
    if (!(argv[0].equals("-gen"))) {
    keyAgree.usage();
    throw new Exception("Unrecognized flag: " + argv[0]);
    }
    mode = "GENERATE_DH_PARAMS";
    }

    keyAgree.run(mode);
    } catch (Exception e) {
    System.err.println("Error: " + e);
    System.exit(1);
    }
    }

    private void run(String mode) throws Exception {

    DHParameterSpec dhSkipParamSpec;

    if (mode.equals("GENERATE_DH_PARAMS")) {
    // Some central authority creates new DH parameters
    System.out.println
    ("Creating Diffie-Hellman parameters (takes VERY long) ...");
    AlgorithmParameterGenerator paramGen
    = AlgorithmParameterGenerator.getInstance("DH");
    paramGen.init(512);
    AlgorithmParameters params = paramGen.generateParameters();
    dhSkipParamSpec = (DHParameterSpec)params.getParameterSpec
    (DHParameterSpec.class);
    } else {
    // use some pre-generated, default DH parameters
    System.out.println("Using SKIP Diffie-Hellman parameters");
    dhSkipParamSpec = new DHParameterSpec(skip1024Modulus,
    skip1024Base);
    }

    /*
    * Alice creates her own DH key pair, using the DH parameters from
    * above
    */
    System.out.println("ALICE: Generate DH keypair ...");
    KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
    aliceKpairGen.initialize(dhSkipParamSpec);
    KeyPair aliceKpair = aliceKpairGen.generateKeyPair();

    // Alice creates and initializes her DH KeyAgreement object
    System.out.println("ALICE: Initialization ...");
    KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
    aliceKeyAgree.init(aliceKpair.getPrivate());

    // Alice encodes her public key, and sends it over to Bob.
    byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();

    /*
    * Let's turn over to Bob. Bob has received Alice's public key
    * in encoded format.
    * He instantiates a DH public key from the encoded key material.
    */
    KeyFactory bobKeyFac = KeyFactory.getInstance("DH");
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec
    (alicePubKeyEnc);
    PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec);

    /*
    * Bob gets the DH parameters associated with Alice's public key.
    * He must use the same parameters when he generates his own key
    * pair.
    */
    DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();

    // Bob creates his own DH key pair
    System.out.println("BOB: Generate DH keypair ...");
    KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
    bobKpairGen.initialize(dhParamSpec);
    KeyPair bobKpair = bobKpairGen.generateKeyPair();

    // Bob creates and initializes his DH KeyAgreement object
    System.out.println("BOB: Initialization ...");
    KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
    bobKeyAgree.init(bobKpair.getPrivate());

    // Bob encodes his public key, and sends it over to Alice.
    byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();

    /*
    * Alice uses Bob's public key for the first (and only) phase
    * of her version of the DH
    * protocol.
    * Before she can do so, she has to instanticate a DH public key
    * from Bob's encoded key material.
    */
    KeyFactory aliceKeyFac = KeyFactory.getInstance("DH");
    x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc);
    PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec);
    System.out.println("ALICE: Execute PHASE1 ...");
    aliceKeyAgree.doPhase(bobPubKey, true);

    /*
    * Bob uses Alice's public key for the first (and only) phase
    * of his version of the DH
    * protocol.
    */
    System.out.println("BOB: Execute PHASE1 ...");
    bobKeyAgree.doPhase(alicePubKey, true);

    /*
    * At this stage, both Alice and Bob have completed the DH key
    * agreement protocol.
    * Both generate the (same) shared secret.
    */
    byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
    int aliceLen = aliceSharedSecret.length;

    byte[] bobSharedSecret = new byte[aliceLen];
    int bobLen;
    try {
    // show example of what happens if you
    // provide an output buffer that is too short
    bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 1);
    } catch (ShortBufferException e) {
    System.out.println(e.getMessage());
    }
    // provide output buffer of required size
    bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 0);

    System.out.println("Alice secret: " +
    toHexString(aliceSharedSecret));
    System.out.println("Bob secret: " +
    toHexString(bobSharedSecret));

    if (!java.util.Arrays.equals(aliceSharedSecret, bobSharedSecret))
    throw new Exception("Shared secrets differ");
    System.out.println("Shared secrets are the same");

    /*
    * Now let's return the shared secret as a SecretKey object
    * and use it for encryption. First, we generate SecretKeys for the
    * "DES" algorithm (based on the raw shared secret data) and
    * then we use DES in ECB mode
    * as the encryption algorithm. DES in ECB mode does not require any
    * parameters.
    *
    * Then we use DES in CBC mode, which requires an initialization
    * vector (IV) parameter. In CBC mode, you need to initialize the
    * Cipher object with an IV, which can be supplied using the
    * javax.crypto.spec.IvParameterSpec class. Note that you have to use
    * the same IV for encryption and decryption: If you use a different
    * IV for decryption than you used for encryption, decryption will
    * fail.
    *
    * Note: If you do not specify an IV when you initialize the
    * Cipher object for encryption, the underlying implementation
    * will generate a random one, which you have to retrieve using the
    * javax.crypto.Cipher.getParameters() method, which returns an
    * instance of java.security.AlgorithmParameters. You need to transfer
    * the contents of that object (e.g., in encoded format, obtained via
    * the AlgorithmParameters.getEncoded() method) to the party who will
    * do the decryption. When initializing the Cipher for decryption,
    * the (reinstantiated) AlgorithmParameters object must be passed to
    * the Cipher.init() method.
    */
    System.out.println("Return shared secret as SecretKey object ...");
    // Bob
    // Note: The call to bobKeyAgree.generateSecret above reset the key
    // agreement object, so we call doPhase again prior to another
    // generateSecret call
    bobKeyAgree.doPhase(alicePubKey, true);
    SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");

    // Alice
    // Note: The call to aliceKeyAgree.generateSecret above reset the key
    // agreement object, so we call doPhase again prior to another
    // generateSecret call
    aliceKeyAgree.doPhase(bobPubKey, true);
    SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");

    /*
    * Bob encrypts, using DES in ECB mode
    */
    Cipher bobCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey);

    byte[] cleartext = "This is just an example".getBytes();
    byte[] ciphertext = bobCipher.doFinal(cleartext);

    /*
    * Alice decrypts, using DES in ECB mode
    */
    Cipher aliceCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey);
    byte[] recovered = aliceCipher.doFinal(ciphertext);

    if (!java.util.Arrays.equals(cleartext, recovered))
    throw new Exception("DES in CBC mode recovered text is " +
    "different from cleartext");
    System.out.println("DES in ECB mode recovered text is " +
    "same as cleartext");

    /*
    * Bob encrypts, using DES in CBC mode
    */
    bobCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey);

    cleartext = "This is just an example".getBytes();
    ciphertext = bobCipher.doFinal(cleartext);
    // Retrieve the parameter that was used, and transfer it to Alice in
    // encoded format
    byte[] encodedParams = bobCipher.getParameters().getEncoded();

    /*
    * Alice decrypts, using DES in CBC mode
    */
    // Instantiate AlgorithmParameters object from parameter encoding
    // obtained from Bob
    AlgorithmParameters params = AlgorithmParameters.getInstance("DES");
    params.init(encodedParams);
    aliceCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey, params);
    recovered = aliceCipher.doFinal(ciphertext);

    if (!java.util.Arrays.equals(cleartext, recovered))
    throw new Exception("DES in CBC mode recovered text is " +
    "different from cleartext");
    System.out.println("DES in CBC mode recovered text is " +
    "same as cleartext");
    }

    /*
    * Converts a byte to hex digit and writes to the supplied buffer
    */
    private void byte2hex(byte b, StringBuffer buf) {
    char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
    '9', 'A', 'B', 'C', 'D', 'E', 'F' };
    int high = ((b & 0xf0) >> 4);
    int low = (b & 0x0f);
    buf.append(hexChars[high]);
    buf.append(hexChars[low]);
    }

    /*
    * Converts a byte array to hex string
    */
    private String toHexString(byte[] block) {
    StringBuffer buf = new StringBuffer();

    int len = block.length;

    for (int i = 0; i < len; i++) {
    byte2hex(block[i], buf);
    if (i < len-1) {
    buf.append(":");
    }
    }
    return buf.toString();
    }

    /*
    * Prints the usage of this test.
    */
    private void usage() {
    System.err.print("DHKeyAgreement usage: ");
    System.err.println("[-gen]");
    }

    // The 1024 bit Diffie-Hellman modulus values used by SKIP
    private static final byte skip1024ModulusBytes[] = {
    (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58,
    (byte)0x4E, (byte)0x49, (byte)0xDB, (byte)0xCD,
    (byte)0x20, (byte)0xB4, (byte)0x9D, (byte)0xE4,
    (byte)0x91, (byte)0x07, (byte)0x36, (byte)0x6B,
    (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D,
    (byte)0x45, (byte)0x1D, (byte)0x0F, (byte)0x7C,
    (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C,
    (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6,
    (byte)0xF3, (byte)0xC9, (byte)0x23, (byte)0xC0,
    (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B,
    (byte)0x18, (byte)0x8D, (byte)0x8E, (byte)0xBB,
    (byte)0x55, (byte)0x8C, (byte)0xB8, (byte)0x5D,
    (byte)0x38, (byte)0xD3, (byte)0x34, (byte)0xFD,
    (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43,
    (byte)0xA3, (byte)0x1D, (byte)0x18, (byte)0x6C,
    (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C,
    (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C,
    (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40,
    (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C,
    (byte)0x84, (byte)0xA7, (byte)0x0A, (byte)0x72,
    (byte)0xD6, (byte)0x86, (byte)0xC4, (byte)0x03,
    (byte)0x19, (byte)0xC8, (byte)0x07, (byte)0x29,
    (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C,
    (byte)0xD9, (byte)0x96, (byte)0x9F, (byte)0xAB,
    (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B,
    (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08,
    (byte)0x3D, (byte)0x66, (byte)0xA4, (byte)0x5D,
    (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C,
    (byte)0xBD, (byte)0x89, (byte)0x4B, (byte)0x22,
    (byte)0x19, (byte)0x26, (byte)0xBA, (byte)0xAB,
    (byte)0xA2, (byte)0x5E, (byte)0xC3, (byte)0x55,
    (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7
    };

    // The SKIP 1024 bit modulus
    private static final BigInteger skip1024Modulus
    = new BigInteger(1, skip1024ModulusBytes);

    // The base used with the SKIP 1024 bit modulus
    private static final BigInteger skip1024Base = BigInteger.valueOf(2);
    }

  • Diffie-Hellman Key Exchange between 3 Parties

    /*
    * Copyright 1997-2001 by Sun Microsystems, Inc.,
    * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
    * All rights reserved.
    *
    * This software is the confidential and proprietary information
    * of Sun Microsystems, Inc. ("Confidential Information"). You
    * shall not disclose such Confidential Information and shall use
    * it only in accordance with the terms of the license agreement
    * you entered into with Sun.
    */

    import java.io.*;
    import java.math.BigInteger;
    import java.security.*;
    import java.security.spec.*;
    import java.security.interfaces.*;
    import javax.crypto.*;
    import javax.crypto.spec.*;
    import javax.crypto.interfaces.*;
    import com.sun.crypto.provider.SunJCE;

    /**
    * This program executes the Diffie-Hellman key agreement protocol
    * between 3 parties: Alice, Bob, and Carol.
    *
    * We use the same 1024-bit prime modulus and base generator that are
    * used by SKIP.
    */

    public class DHKeyAgreement3 {

    private DHKeyAgreement3() {}

    public static void main(String argv[]) {
    try {
    DHKeyAgreement3 keyAgree = new DHKeyAgreement3();
    keyAgree.run();
    } catch (Exception e) {
    System.err.println("Error: " + e);
    System.exit(1);
    }
    }

    private void run() throws Exception {

    DHParameterSpec dhSkipParamSpec;

    System.out.println("Using SKIP Diffie-Hellman parameters");
    dhSkipParamSpec = new DHParameterSpec(skip1024Modulus, skip1024Base);

    // Alice creates her own DH key pair
    System.out.println("ALICE: Generate DH keypair ...");
    KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
    aliceKpairGen.initialize(dhSkipParamSpec);
    KeyPair aliceKpair = aliceKpairGen.generateKeyPair();

    // Bob creates his own DH key pair
    System.out.println("BOB: Generate DH keypair ...");
    KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
    bobKpairGen.initialize(dhSkipParamSpec);
    KeyPair bobKpair = bobKpairGen.generateKeyPair();

    // Carol creates her own DH key pair
    System.out.println("CAROL: Generate DH keypair ...");
    KeyPairGenerator carolKpairGen = KeyPairGenerator.getInstance("DH");
    carolKpairGen.initialize(dhSkipParamSpec);
    KeyPair carolKpair = carolKpairGen.generateKeyPair();


    // Alice initialize
    System.out.println("ALICE: Initialize ...");
    KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
    aliceKeyAgree.init(aliceKpair.getPrivate());

    // Bob initialize
    System.out.println("BOB: Initialize ...");
    KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
    bobKeyAgree.init(bobKpair.getPrivate());

    // Carol initialize
    System.out.println("CAROL: Initialize ...");
    KeyAgreement carolKeyAgree = KeyAgreement.getInstance("DH");
    carolKeyAgree.init(carolKpair.getPrivate());


    // Alice uses Carol's public key
    Key ac = aliceKeyAgree.doPhase(carolKpair.getPublic(), false);

    // Bob uses Alice's public key
    Key ba = bobKeyAgree.doPhase(aliceKpair.getPublic(), false);

    // Carol uses Bob's public key
    Key cb = carolKeyAgree.doPhase(bobKpair.getPublic(), false);


    // Alice uses Carol's result from above
    aliceKeyAgree.doPhase(cb, true);

    // Bob uses Alice's result from above
    bobKeyAgree.doPhase(ac, true);

    // Carol uses Bob's result from above
    carolKeyAgree.doPhase(ba, true);


    // Alice, Bob and Carol compute their secrets
    byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
    System.out.println("Alice secret: " + toHexString(aliceSharedSecret));

    byte[] bobSharedSecret = bobKeyAgree.generateSecret();
    System.out.println("Bob secret: " + toHexString(bobSharedSecret));

    byte[] carolSharedSecret = carolKeyAgree.generateSecret();
    System.out.println("Carol secret: " + toHexString(carolSharedSecret));


    // Compare Alice and Bob
    if (!java.util.Arrays.equals(aliceSharedSecret, bobSharedSecret))
    throw new Exception("Alice and Bob differ");
    System.out.println("Alice and Bob are the same");

    // Compare Bob and Carol
    if (!java.util.Arrays.equals(bobSharedSecret, carolSharedSecret))
    throw new Exception("Bob and Carol differ");
    System.out.println("Bob and Carol are the same");
    }


    /*
    * Converts a byte to hex digit and writes to the supplied buffer
    */
    private void byte2hex(byte b, StringBuffer buf) {
    char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
    '9', 'A', 'B', 'C', 'D', 'E', 'F' };
    int high = ((b & 0xf0) >> 4);
    int low = (b & 0x0f);
    buf.append(hexChars[high]);
    buf.append(hexChars[low]);
    }

    /*
    * Converts a byte array to hex string
    */
    private String toHexString(byte[] block) {
    StringBuffer buf = new StringBuffer();

    int len = block.length;

    for (int i = 0; i < len; i++) {
    byte2hex(block[i], buf);
    if (i < len-1) {
    buf.append(":");
    }
    }
    return buf.toString();
    }

    /*
    * Prints the usage of this test.
    */
    private void usage() {
    System.err.print("DHKeyAgreement usage: ");
    System.err.println("[-gen]");
    }

    // The 1024 bit Diffie-Hellman modulus values used by SKIP
    private static final byte skip1024ModulusBytes[] = {
    (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58,
    (byte)0x4E, (byte)0x49, (byte)0xDB, (byte)0xCD,
    (byte)0x20, (byte)0xB4, (byte)0x9D, (byte)0xE4,
    (byte)0x91, (byte)0x07, (byte)0x36, (byte)0x6B,
    (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D,
    (byte)0x45, (byte)0x1D, (byte)0x0F, (byte)0x7C,
    (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C,
    (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6,
    (byte)0xF3, (byte)0xC9, (byte)0x23, (byte)0xC0,
    (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B,
    (byte)0x18, (byte)0x8D, (byte)0x8E, (byte)0xBB,
    (byte)0x55, (byte)0x8C, (byte)0xB8, (byte)0x5D,
    (byte)0x38, (byte)0xD3, (byte)0x34, (byte)0xFD,
    (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43,
    (byte)0xA3, (byte)0x1D, (byte)0x18, (byte)0x6C,
    (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C,
    (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C,
    (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40,
    (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C,
    (byte)0x84, (byte)0xA7, (byte)0x0A, (byte)0x72,
    (byte)0xD6, (byte)0x86, (byte)0xC4, (byte)0x03,
    (byte)0x19, (byte)0xC8, (byte)0x07, (byte)0x29,
    (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C,
    (byte)0xD9, (byte)0x96, (byte)0x9F, (byte)0xAB,
    (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B,
    (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08,
    (byte)0x3D, (byte)0x66, (byte)0xA4, (byte)0x5D,
    (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C,
    (byte)0xBD, (byte)0x89, (byte)0x4B, (byte)0x22,
    (byte)0x19, (byte)0x26, (byte)0xBA, (byte)0xAB,
    (byte)0xA2, (byte)0x5E, (byte)0xC3, (byte)0x55,
    (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7
    };

    // The SKIP 1024 bit modulus
    private static final BigInteger skip1024Modulus
    = new BigInteger(1, skip1024ModulusBytes);

    // The base used with the SKIP 1024 bit modulus
    private static final BigInteger skip1024Base = BigInteger.valueOf(2);
    }

  • Blowfish Example

    /*
    * Copyright 1997-2001 by Sun Microsystems, Inc.,
    * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
    * All rights reserved.
    *
    * This software is the confidential and proprietary information
    * of Sun Microsystems, Inc. ("Confidential Information"). You
    * shall not disclose such Confidential Information and shall use
    * it only in accordance with the terms of the license agreement
    * you entered into with Sun.
    */

    import java.security.*;
    import javax.crypto.*;
    import javax.crypto.spec.*;

    /**
    * This program generates a Blowfish key, retrieves its raw bytes, and
    * then reinstantiates a Blowfish key from the key bytes.
    * The reinstantiated key is used to initialize a Blowfish cipher for
    * encryption.
    */

    public class BlowfishKey {

    public static void main(String[] args) throws Exception {

    KeyGenerator kgen = KeyGenerator.getInstance("Blowfish");
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "Blowfish");

    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted =
    cipher.doFinal("This is just an example".getBytes());
    }
    }

  • HMAC-MD5 Example

    /*
    * Copyright 1997-2001 by Sun Microsystems, Inc.,
    * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
    * All rights reserved.
    *
    * This software is the confidential and proprietary information
    * of Sun Microsystems, Inc. ("Confidential Information"). You
    * shall not disclose such Confidential Information and shall use
    * it only in accordance with the terms of the license agreement
    * you entered into with Sun.
    */

    import java.security.*;
    import javax.crypto.*;

    /**
    * This program demonstrates how to generate a secret-key object for
    * HMAC-MD5, and initialize an HMAC-MD5 object with it.
    */

    public class initMac {

    public static void main(String[] args) throws Exception {

    // Generate secret key for HMAC-MD5
    KeyGenerator kg = KeyGenerator.getInstance("HmacMD5");
    SecretKey sk = kg.generateKey();

    // Get instance of Mac object implementing HMAC-MD5, and
    // initialize it with the above secret key
    Mac mac = Mac.getInstance("HmacMD5");
    mac.init(sk);
    byte[] result = mac.doFinal("Hi There".getBytes());
    }
    }

Copyright ¨ 1996-2004 Sun Microsystems, Inc. All Rights Reserved.

Please send comments to: java-security@java.sun.com.


@http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/JCERefGuide.html
2007/03/06 18:59 2007/03/06 18:59
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

코닥 포트라 ( kodak portra ) 160vc와 함께 한 10개월 - 작례

일러두기
  • 코닥포트라 필름에 대해 다양한 계절과 광선에서의 결과물을 보여드리기 위해 가능한 많은 작례를 개재했습니다.
  • 모든 촬영은 Minolta @7, tokina 19-35, km 17-35, minolta 50 1.7, minolta 100mm macro, 5400hs, 5600hs, 반사판등 을 이용하였으며, 기억나는대로 촬영 조건을 기술하도록 노력 했습니다.
  • 스캔은 후지 FDi SLP 1000 혹은 코스트코의 노리츠로 받았습니다.
  • 이미지 크기가 큰쪽이 FDi스캔본의 50% 리사이즈, 크기가 작은 쪽이 노리츠 스캔본의 50%리사이즈 입니다.
  • 웹상에 개시할 때는 보통 스캔시 발생하는 노이즈 때문에 노이즈 제거와 약간의 컬러밸런스를 조절 하지만 이 사용기에서 스캔받은 사진의 리사이즈 외에 다른 작업은 하지 않았음을 밝혀둡니다.
    [사실 이부분을 어떻게 처리 할지로 고민을 좀 했었습니다. 네거티브 컬러필름이란게 관용도가 넓다보니.. 스캔받은 파일이 꼭 원본이라고 우길수도 없으니 말입니다.. 다른 필름과 같은 장면을 촬영해 비교해보는 방법이 그나마 객관적인 비교가 되겠지만.. 이미 찍은 사진이기도 하고.. 판단은 글을 보시는 여러분께 맡기는게 좋을것 같아 그렇게 진행하였습니다.]
  • 사진은 제 포토 갤러리에 있는 이미지를 사용하였기때문에 눈에 거슬리는 WaterMark가 사진 하단에 표시되는점은 양해 부탁 드립니다.
  • 각 절기별로 포트라의 색감을 잘 볼 수 있을만한 이미지는 스캔받은 원본을 링크하여 별도 표기 하여 스캔했을 때 발생하는 노이즈나 여타의 색감등을 확인 하실 수 있도록 했습니다.
  • 제 촬영 스타일 상 인물 사진이 거의 90%이상입니다. 모델이 되어 주신분들의 허락을 득하였지만 모델이 되어주신분의 초상권을 최우선으로 생각하며 모델이 되어주신분은은 언제든지 본인의 이미지를 삭제 요청을 하실 수 있습니다.
  • 위 글과 이어지는 내용인데.. 코스 촬영분이 많습니다. 코스튬플레이를 혐오하시거나 그런 류의 사진을 싫어하신다면 이글을 보지 않으시는게 좋겠습니다.
  • 마지막으로 이 글과 이 글의 모든 사진은 크리에이티브 커먼즈 코리아 [저작자표시-비영리-변경금지] 2.0 대한민국 라이센스를 따릅니다.


  • 사실, 이 사용기는 이번에 코닥온라인에서 진행하는 코닥 포트라/프로 필름 체험기를 위해 작성 하고 있었으나
    체험단에 선정되지 못하여 글을 올려야 하나 말아야하나로 살짝 고민을 하였지만 기왕 작성한 글 버리는것보단
    낫지 않을까 하는 생각으로 게시를 합니다. [코닥 필름 체험단 여러분과는 아무런 이해관계없이 진행되는글임을 밝혀둡니다.]

    비록 체험단에 선정되지는 못하였지만 이번 기회를 통하여 제가 사랑해마지 않는 Kodak Portra 160VC 란 필름을 소개 할 수 있게 되어 나름대로 뿌듯합니다.

    모 동호회 회원분들은 제가 갤러리에 올린 사진과 원본 리사이즈사진간의 차이를 비교 해 보시는 재미도 있을것 같군요.(^^;;)

    필름 사용자분들이라면 임 많은분들이 이 필름에 대해 아시겠지만 처음부터 디카 혹은 DSLR로 시작하신 분중 일부는
    이 필름에 대해 모르실 수도 있으니 본격적인 이야기에 앞서 Kodak Portra 160VC 필름에 대해 잠깐 언급하고 넘어가겠습니다.
    Portra 는 kodak에서 제조되고있는 고급형 필름으로 감도는 160으로 숫자뒤에 VC,NC와 같은 코드가 붙습니다.
    'NC'라는 코드가 붙어 Natural Color라는 의미의로 자연스런 발색을 그 특징으로 한다고 합니다.
    이번에 사용한 'VC'는 Vivid Color의 약자로 Color Saturation이 강한 필름입니다.

    코닥 포트라 시리즈 - 이미지 출저: kodak4u


    코닥 사이트에서는 포트라를

    진보된 결합기술은 생생한 칼라를 제공하면서도 동일한 분광감도곡선을
    보여주는 두 종류의 포트라 필름을 탄생시켰다.
    더 나아가, 필름 감도들간 분광 감광도가 동일하여
    모든 포트라 필름들은 동일한 정도로 정확하게 색상을 재현한다.
    이로써 사진가들은 다양한 선택권을 갖으며,
    어느 포트라 필름을 사용하여 촬영하든
    놀라우리만치 일관성 있는 결과물을 보장 받는다.
    고객들은 테스트 사진(proof)과 완성된 사진,
    혹은 앨범, 벽에 걸린, 아름답게 조화를 이루는 사진들로
    만들어진 액자 속의 사진이 서로 일치되는 것을 느낄 수 있을 것이다.


    라고 제품정보에 기술하고 있습니다.


    포트라는 작년 5월경부터 제 주력필름으로 사용하기 시작하였습니다.
    포트라 이전에는 적당한 가격에 상당한 결과물을 뽑아내 주는 Fuji Reala 100 을
    가장 애용 했읍니다.

    제가 카메라를 들고 사진이란걸 찍어보기 시작한게 2004년 5월쯤부터니까
    사진을 그리 오래 했다고도 할 수 없고 사진을 잘 이해하고 있다고도 할 수 없는 초보 중의 초보입니다.
    처음 X-300 으로 시작해서 X-570을거쳐 지금의 @7에 정착하게 되었는데요.

    저도 처음에는 필름종류가 이렇게나 다양할 줄 몰랐습니다.
    후지 오토오토나 코닥 골드 100과같은 소위 말하는 국민 필름으로 제 주변 사람들과의 소소한 일상을
    담기 시작했습니다. 당시만 해도 코닥필름에 대해 약간의 선입견이 있었는데
    주제에 들은 풍월은 있어가지고 '코닥은 서양인 피부를 기준으로 맞춰 나와서 동양인에게는 안어울려..'
    라든지.. 실제로 코닥 골드 인화물을 봤을때의 그 찐한색감(그때는 떡져있다고 느겼을 정도였습니다.) 같은 것이었습니다.

    이런저런 주제로몇 사진에 찍으면서
    '아.. 풍경사진 너무 어렵구나...'라는걸 느끼면서 풍경보단
    인물사진에 집중하기 시작했습니다.

    여기서 소개할 작례들의 거의 대부분이 인물사진밖에 없는 이유도 그때문입니다.
    그나마 풍경을 담은 사진을의 필름은 포트라를 사용한게 없더군요..

    인물 사진에 치우치기 시작하면서 자연스레 리얼라를 애용하게 됩니다.
    리얼라.. 참 좋은 필름입니다. 친구들 예식사진, 웨딩 스냅 촬영, 코스튬플레이 등.. 많은
    사진 남겨준 필름입니다. 약간의 단점이 있다면 많이 알려진 바대로 저광량에서는
    제능력을 십분발휘하지 못한다는 점이 조금 아쉬울뿐 가격대비 훌륭한 결과물을
    뽑아 주었습니다.

    그렇게 사진 생활을 쭉 해오던 중.. 불현듯 코닥의 고가필름은 어떨까?
    코닥 골드 100이랑은 어떻게 다르지? 하는 생각이 들어 가끔 애용하는 모샵에서
    포트라 5롤을 구매하게됩니다.. 그 때 5롤 가격이 25000원.. 지금껏 제가 써오던
    필름과는 차원을 달리하는 몸값..( 135포멧에서 입니다.. 중형, 대형앞에선 명함도 못내밀겠죠 ^^;;)
    도대체 뭐가 이리 비싼거야...

    포트라로 처음 찍어본 사진이 5월말 늦봄 햇살아래서 진행되었던 코스프레입니다.

    결과물을 보고 상당히 놀라지 않을수가 없었습니다..

    1





    2

    [주변이 밝긴 했지만 유독 얼굴쪽에 강한 광선이 떨어지고 있었습니다. 얼굴 스팟측광으로 0.7ev 브라켓 촬영중 0ev 컷.]

    위 두 사진에 절 포트라라는 마수에 걸려 들었습니다.처음 스캔받은 이 사진을 보고
    '이걸 정말 내가 찍은거야?' 란 생각을 했더랬습니다.

    이 때 찍은 다른 컷들로 포트라의 발색을 확인 해 보세요.

    3





    4





    5

    [에나멜 재질의 광택이 잘 살아 있습니다.]




    6
    [원본보기]




    7





    8

    [그늘 속에서의 붉은색 발색입니다.]




    9

    [모델의 뒷편에서 따사로운 햇살이 떨어지고 있었으며 모델 정면에서 반사판을, 그리고 플래시를 가미해 촬영 하였습니다.]


    10

    [약간 언더입니다. 옷감과 뒷 배경의 색상과 재질을 잘 표현하고 있습니다.]



    이어지는 3컷은 6월 중순의 햇살아래 선유도에서의 사진입니다.



    11

    [의상과 회색벽 때문인지 상당히 차분한 발색을 보이고 있습니다.]




    12
    [원본보기]
    [50mm 랜즈로 거의 반사적으로 잡은 컷입니다. 덕분에 얼굴이 화면중앙에 배치된 구도가..언더로 찍으면 이렇게 표현 되기도 합니다.]




    13



    다음으로 작년 한해동안 사진을 찍으면서 가장 더위에 시달렸던 7월 말의 사진입니다.
    희뿌연 구름이 잔뜩 끼었으며 5미터를 채 걷기도 전에 셔츠가 다 젖을정도로 찌는 날이었습니다.

    14
    [원본보기]
    오후 3시에서 4시경  사진입니다. 찌는 폭염의 날에 3-4시면 해가 쨍쨍할 시간인데
    그림자가 전혀 안보일정도의 구름낀 날이었습니다.




    15

    [ 옅은 산란광의 대기와 벽돌건물의 영향으로 상당히 저채도의 결과물을 보여 주고 있습니다.]



    다음으로 8월중순에 있었던 스튜디오 촬영을 보시겠습니다.
    친구 웨딩 촬영 때 스냅으로 스튜디오 촬영한것 말고 능동적인 입장에서 스튜디오 촬영은 처음이었습니다.
    몇가지 주의사항정도를 숙지한 후 촬영한거라 부족한 점이 많습니다.
    하지만 스튜디오처럼 광량이 풍부한 곳에서 사진을 담으면 왠만하면 봐줄만한 사진이 나온다는것과
    스튜디오 크기가 좀 크지 않다면 70미리 화각 이내가 촬영에 적당하다는것을 배웠습니다.
    사실 이날은 100mm로만 촬영할 심산이었으나 혹시나 하는 마음에 50mm를 챙겨 갔더랬는데
    50mm를 안가져 갔더라면 얼굴 클로즈 업 샷만 찍을 뻔 했습니다.

    16





    17





    18





    19



    어느덧 계절은 여름의끝자락-가을의 시작인 환절기입니다.
    친구녀석 아들 돌잔치 후 간만에 모인김에 선유도에 바람 맞으러 갔더랬습니다. 이하 4장의 사진은 km 17-35로 촬영한 사진 입니다.

    20

    [뉘엇이 넘어가는 노을 빛을 받은 친구녀석 내외입니다.]



    21
    [원본보기]
    [애기 너무 귀엽지 않습니까?]



    22

    [살짝 해떨어진 직후 평균측광에 노출 고정 후 플래시 슬로우 싱크 사진 입니다. 우연이지만 꽤 재미있는 사진이 나왔죠..]



    23

    [해가 완전히 진 후입니다. 난간에 카메라를 놓고 위와 동일한 방법으로 촬영 하였습니다.
    한강 둔치쪽의 유령이 보인느 군요. ^^  이로 미루어 보아 상당한 셔터 개방시간이었음을 짐작 하실 수 있습니다.]



    위 돌잔치 있은 바로 다음날 양재 입니다.
    햇빛도 풍부하고 더위도 많이 누그러 들어 촬영에 힘이들지 않았던 좋은 날이죠..

    24





    25
    [원본보기]
    [살짝 백태가 끼었네요 ^^]



    26

    [대개 이시기에 양재 시민의 숲 속에 들어가면 해가 떨어지는곳과 숲안은 보시는 바와같이
    극명한 노출차가 생깁니다. 중앙중점으로 인물에 노출고정후 촬영.]



    27

    [그늘 속에서라도 반사판과 플래시의 도움으로 위와같은 화면을 잡을 수 있습니다.]



    28

    [머리위로 떨어지는 맑은 빛이 나뭇잎을 더욱 투명하게 표현 하고 있습니다.]


    [아래는 군데군데 빛이 떨어지는 그늘에서 촬영한 결과물들입니다.]

    29





    30





    31





    32





    33




    일년 중 가장 해가 좋은 시기라면 비갠 후의 봄날과 이맘때쯤이 아난가 생각합니다.
    9월 말경이고 맑은 날씨로 유명한 대전[지난 3년동안 출장갔다하면 대전만 갔는데 장마철 빼고 구름낀 날을 보기가
    힘들 정도의 도시였습니다.]의 모 교정에서 3번째 만남을 가졌던 보니양입니다.
    이날은 유난히 역광/반영광하에서 반사판과 플래시촬영이 많았더랬습니다.
    결과물은? 완전 빙고를 외치게 하는 컷들이 대부분 이었습니다.

    34





    35





    36
    [원본보기]




    37





    38

    [암부에서는 스캐닝 노이즈가 알록달록 합니다. 최신기종인 FDi SLP 3000시리즈 에서는 어떻게 스캔이 될지 궁금해 지더군요..]



    39

    [기둥 안쪽과 바깥의 노출차는 그냥봐도 극복하기 어렵게 보일 정도였습니다. 바깥이나 안 둘중하나는
    포기할 심산으로 전체 평균 츨광 후 플래시 발광입니다. 17mm영역이구요 5600hs의 와이드 어댑터를 적용하지않고 않고 찍어서 동굴 현상이 잘 나타나고 있습니다. ]



    40

    [이날 촬영으로. 역시 좋은빛이 좋은 사진을 만들어준다는 단순한 진리를 다시한번 온몸으로 느낄 수 있었습니다.]

    이후 사진찍기 좋은 10월 11월은 회사 프로젝트와 세컨드잡의 압박으로 도저히 시간을 뺄 수 없는 지경에 이르고..
    전 일에 뭍혀 폐인생활을 하게 됩니다.

    그리고 나서게된 12월 24일 코스행사..
    솔직히 크리스마스 이브랑 크리스마스날까지 코스 촬영을 가야하는 제신세가 좀 처량 했던게 사실입니다.
    커플생활이 끝나고 나선 무슨무슨날.. 이러면 무덤덤하게 보내고 싶은데 저도 사람인지라.. 마음이 동하게 되는건 어쩔수가 없더라구요..
    그냥 집에서 조용히 보 낼까하다가.. 그동안 셔터도 못 누르고 있었고,
    코스행사 못나가본지도 꽤 된지라.. 뾰로퉁한 심정으로.. 발걸음을 옮겼습니다. 예.. 거기서 아래 코스어를 만나게 됩니다.
    그냥 멀리서 봐도 의상을 제작하는데 얼마나 고생했을지 눈에 선했습니다. 그리고, 그 고생에 부응하는 퀄리티..
    빛이 쨍하고 배경이 이뻤다면.. 하는 아쉬움이 많이 남는 촬영이었습니다.
    행여나 거대한 헬맷안으로 빛이 안들어갈까 노심초사 하면서 촬영을 했더랬습니다.

    43





    44





    45
    [원본보기]




    41

    [요건 덤! 입니다. 동조 촬영중에 플래시 위치를 잘못 파악해서 촬영했더니..
    파인더 안에서는 안보였는데 아슬아슬하게 엣지에 걸렸더군요..ㅎㅎ]



    42





    드디어 대망의 2007년 첫 출사입니다. 1월 말이구요 빛은 선명한 편이었지만 다들 아시겠지만 꽤 쌀쌀했습니다.
    우연히! 정말 우연히 2년정도 전에 모 클럽에서 알게된 친구를 여기서 만나게 되는데 어찌나 반갑던지..
    그때는 고등학생이었는데 이젠 어엿한 대학생이 되는 친구입니다.

    46





    47





    48





    49
    [원본보기]
    [하늘빛에서 날은 상당히 좋았음을 아실 수 있을 겁니다.]



    50





    아래부터는 2월초에 있었던 모동호회 출사사진입니다.
    올림필공원과 근처에있던 스튜디오에서 촬영을 진행 하였습니다.

    51





    52





    53





    54





    55
    [원본보기]




    56





    57





    58

    [상당히 독특한 결과물이 나왔습니다. 마치 그린거같은 얼굴 질감인데.. 사진에 보시는것 처럼 앉아있는 대리석 기둥에
    빛이 떨어져 상당한 밝기로 빛나고 있었는데 여기서 플래시를 터트리면 어떤 결과물이 나올지 궁금해 하며 셔터를 눌렀던 컷입니다.
    종종 이런 결과물을 보여주는 것도 상당히 마음에 듭니다.]



    59





    아래로는 지난 2월에 있었던 사내 사진동호회 출사사진입니다.
    장소는 선유도 였으며 전날 비가오고 당일 오후 2시까지 구름이 잔뜩끼어 좋은 사진이 나올지 걱정을 많이 하였는데 다행히
    오후 부터 날이개서 순조롭게 촬영을 진행할 수 있었습니다.

    60





    61
    [원본보기]




    62





    63





    64





    65





    66





    67





    다음부터는 보통 일상에서의 사진들입니다.

    68

    [17-35mm]



    69

    [17-35mm]



    70

    [100mm]



    71

    [17mm, 내장 플래시입니다.]



    72

    [19-35mm]



    73

    [17-35mm]



    대부분의 사진들이 50mm와 100mm에 인물 클로즈업이라 조금 심심한면이 없잖아 있었으리라 생각합니다.
    그런 사진들 끝까지 보아주셔서 감사합니다.
    서비의 Portra 160vc에 대한 단상
  • 발색이 아주 좋습니다.
  • 색상 표현력이 풍부합니다. 이로인해 동일 현상소에서 스캔받은 여타 필름결과물과 비교하여 후보정 가능 범위가 넓어집니다.
  • 극명한 노출차속에서도 마음을 졸이지 않아도 됩니다.
  • 결과물에서 노이즈를 살짝 제거한 원본을 바라보고 있으면.. 후보정 기술을 배워보고 싶어집니다. 뛰어난 원본으로 제 사진 표현력이 한층 넓어질 수 있지않을까 하는 기대를 갖게 해 줍니다.
  • 정말로 멋진 결과물을 얻게되는 날이면 현상소 스캔 사이즈가 미워집니다. 더 크게 스캔 해주시면 안될까요? 네?
  • 한가지 분명한 점은, 사진을 잘 모르는 사람에게도 Portra 160VC는 깊은 인상을 남기는 결과물을 보여줍니다.
  • 마지막으로, 비쌉니다.. 하지만 돈값은 합니다.(조금만 저렴해주면 안되겠니?)


  • 끝으로 본 사용기에 사진을 올리 수 있도록 허락 해 주신 분들과 이글을 보아주신 여러분께 감사의 말씀 드립니다.

    All Photos are under Creative Commons License

    Creative Commons License

    이 저작물은 크리에이티브 커먼즈 코리아 [저작자표시-비영리-변경금지] 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

    View English 한글보기 日本語


    2007/03/05 00:25 2007/03/05 00:25
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
    1. 2007/03/05 11:19
      주력필름 Tracked from 신변잡기
    1. 블로그의 트랙백을 통해 들어왔습니다. 포트라 160VC 저도 참 좋아라하는 필름인데.. 스캔해 보면 저와 같은 색감이 나오지 않아서 실망도 많이하게 되더군요.
      인물사진은 될 수 있으면 인화까지 하는데.. 포트라는 인화를 해보면 더 마음에 들더군요^^;;;;

    2. 정말 비싸긴 하지만 돈값은 하는 것 같아요.
      좋은 사진 즐겁게 감상하고 갑니다.

    3. 포트라 정말 좋은 필름이죠...가격이 비싸서 마구 쓰지는 못하지만요...
      특히 포트라 160nc를 정말 좋아하거든요...^^

      저는 6*7 을 주로 사용하는데요...가격은..120이 135보다 약간..아주 약간 쌉니다...그런데...한롤으로 10장뿐이 못쓴다는 슬픔이 있습니다..ㅜㅜ

    4. 제 친구가 160nc로 촬영한 사진을 봤는데 너무 끌리더군요..
      국내에서도 이제 135포맷의 nc구하기가 쉬워졌으니 저도 한번 사용 해 볼 요량입니다.

    NetBeans를 2007년의 “Best Java IDE Innovator”로 지명 - InfoWorld

    NetBeans already had the most complete collaboration features among IDE platforms. This year it added important new modules such as Matisse, the most advanced Java GUI designer available today, and complete support for Java EE 5. NetBeans is likely all that developers of enterprise Java applications will need.  라네요..

    기사보러가기
    2007/03/02 17:42 2007/03/02 17:42
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    NetBeans IDE Guide for JBuilder Users

    If you have used JBuilder to develop Java applications in the past but are looking to move to NetBeans IDE, you can easily get started. Here is a general guide to the things you need to do to start NetBeans IDE, import your JBuilder projects into NetBeans IDE, and continue work on your projects.

    Downloading NetBeans IDE

    Download NetBeans IDE from http://www.netbeans.info/downloads/index.php.

    Once you have downloaded NetBeans IDE, you can start work on importing existing projects from the JBuilder environment into NetBeans IDE.

    A Note on the NetBeans IDE Project System

    All NetBeans IDE projects are all based around the Ant build tool, which makes NetBeans projects easily portable to other environments. However, you do not necessarily need to know anything about Ant to use NetBeans IDE. When you create standard IDE projects, you can handle all project configuration through the IDE's user interface. The IDE maintains the Ant script for you.

    Conceptually, there are two types of projects:

    • Standard projects. When you create a standard IDE project, the IDE also creates a build script that controls how the project is compiled, run, debugged, and so on. This build script is used when you run standard commands from the IDE (like Build Project) and can also be run from outside of the IDE. Standard projects are those created with any IDE project template except the "With Existing Ant Script" templates.
    • Free-form projects. When you create a free-form project (a project created with one of the "With Existing Ant Script" templates), you specify an already existing build script to be used for standard IDE commands. The New Project wizard guides you through mapping IDE commands to the appropriate build targets. For some IDE features, such as debugging, you also need to create special Ant targets to get the feature to work.

    Importing and Running General Java Projects

    To import a general Java application into NetBeans IDE, follow these general steps:

    Downloading the JBuilder Project Importer Module

    You can download the JBuilder Project Importer Module to import projects that you have developed with JBuilder 2005 into NetBeans IDE. (For NetBeans IDE 5.5, this module can also import projects developed with JBuilder 2006). This module eliminates or greatly reduces the amount of work you have to do get your projects working in NetBeans IDE as they worked in JBuilder.

    To download the JBuilder Project Importer module:

    1. Start NetBeans IDE.
    2. In NetBeans IDE, choose Tools | Update Center.
    3. In the Update Center wizard, select the JBuilder Project Importer module and complete the wizard.

    Importing the JBuilder Java SE Project Into NetBeans IDE

    Once you have the importer module added, you can import Java SE projects from JBuilder with a simple wizard.

    To import a general Java project into NetBeans IDE:

    1. In NetBeans IDE, choose File | Import Project | JBuilder Java Project.
    2. In the wizard, specify the JBuilder project file (Project to Import field) and the folder where you want the NetBeans IDE project metadata to be created (Destination Folder field).

      In the NetBeans IDE 5.5 version of the project importer, you also are presented with JBuilder User Home and JBuilder Installation Folder. Filling in these fields (where appropriate) makes it easier for the IDE to handle any dependencies that the project has on other projects or libraries.

      The IDE leaves the project sources where they are so that you can still work with them in JBuilder.

    Building and Running Your Application

    To build your application, right-click the project's node in in the Projects window and choose Build Project.

    To run your application in the IDE, right-click the project's node in in the Projects window and choose Run Project.

    Note:When you build and run applications in NetBeans IDE, the output also includes output from the Ant script that the project is based on. If you are not specifically concerned with the working of the Ant script, you can ignore that part of the output.

    For more information on importing projects into NetBeans IDE 5.0, see http://www.netbeans.org/kb/50/import_j2se.html

    Importing Web Projects and Enterprise Projects

    NetBeans IDE does not have a special feature to convert JBuilder web and enterprise projects into projects in NetBeans IDE. However, importing existing projects into NetBeans IDE is fairly straightforward.

    To import a web or enterprise application project, follow these general steps:

    Registering the Server with the IDE

    Before setting up a project in the IDE, make sure that the server that you want to develop for is registered in the IDE. Otherwise you will not be able to complete project setup.

    The bundled Tomcat Web Server is registered with the IDE automatically. If you installed the NetBeans IDE 5.0/Sun Java System Application Server bundle, a local instance of the application server is registered automatically. If you want to deploy to an instance of an unbundled application server, such as the Sun Java System Application Server, JBoss, or WebLogic, you have to register a local instance with the IDE.

    To register an application server instance with the IDE:

    1. Choose Tools > Server Manager from the main window.
    2. Click Add Server. Select the server type and give a name to the instance. Then click Next.
    3. Specify the server information, the location of the local instance of the application server, and the domain to which you want to deploy.

    Setting up a NetBeans IDE Project for a Web or Enterprise Application

    You can use either of the following techniques for setting up your project in NetBeans IDE:

    • Create a new NetBeans IDE standard project using the sources from the JBuilder project.
    • Use the Export to Ant wizard in JBuilder and then create a NetBeans IDE free-form project using that build script.

    When converting JBuilder projects to NetBeans IDE, the way you convert the projects depends largely on these questions:

    • How complex is the project in terms of dependencies, server configuration, database access, and so on?
    • What technologies does the project use?
    • To what extent does the project need to be maintained? Is it likely that the project will need major reworking or extenstion?
    • To what extent do you use the IDE for building tasks and to what extent do you rely on command-line tools or other tools?

    If you have a project that you have just started developing or which has not yet become too complex, you will probably want to convert the project into a standard NetBeans IDE project using a "With Existing Sources" template. Doing so gives you full integration with all of NetBeans IDE's features.

    If you have a project that is very complex and/or which you do not anticipate extensively modifying, you might find that it is most practical to use a NetBeans IDE free-form project (using a "With Existing Ant Script" template). Creating a free-form project enables you to easily build and modify the project based on an Ant script exported from JBuilder. The IDE uses the Ant script you designate to handle standard project commands, such as building and running the project.

    The advantage of this approach is that you do not have to reconfigure your project from scratch. However, if you want full IDE integration using this approach, you might need to some manual configuration to make some features work (such as debugging, code completion, and some other editing feataures). See Advanced Free-Form Project Configuration Guide

    Importing a project as a standard NetBeans project

    To import a web or enterprise project into NetBeans IDE as a standard project:

    1. In NetBeans IDE, choose File | New Project.
    2. Select the appropriate category (Web or Enterprise).
    3. Select the appropriate template and click next. The possible templates are Web Application With Existing Sources, EJB Module With Existing Sources, and Enterprise Application With Existing Sources.
    4. Complete the wizard.

    Importing a project as a free-form NetBeans project

    To import a web or enterprise project into NetBeans IDE as a free-form project:

    1. In JBuilder, select the project's node in the Project window.
    2. Choose File | New.
    3. In the Object Gallery, click Build. Then select Export to Ant and click OK.
    4. Complete the Export to Ant wizard.
    5. In NetBeans IDE, choose File | New Project.
    6. Select the appropriate category (Web or Enterprise).
    7. Select the appropriate template and click next. The possible templates are Web Application With Existing Ant Script and EJB Module With Existing Ant Script. There is no free-form project template for Enterprise Application (EAR) projects.
    8. On the Name and Location page of the wizard, specify the location of the build script that you have just exported and complete the other fields on the page.
    9. Complete the rest of the wizard.

    Configuring the Project in NetBeans IDE

    After creating the NetBeans IDE project, you might need to use the Project Properties dialog box to configure the way the project is built and run.

    You can access the Project Properties dialog box by right-clicking the project's main node in the Project window and choosing Properties.

    Building and Running Your Application

    To build your application, right-click the project's node in in the Projects window and choose Build Project.

    To run your application in the IDE, right-click the project's node in in the Projects window and choose Run Project.

    Note: When you build and run applications in NetBeans IDE, the output also includes output from the Ant script that the project is based on. If you are not specifically concerned with the working of the Ant script, you can ignore that part of the output.

    For more general information on importing web projects into NetBeans IDE 5.0, see http://www.netbeans.org/kb/50/import_web.html

    For more general information on importing enterprise projects into NetBeans IDE 5.0, see http://www.netbeans.org/kb/50/import_j2ee.html

    Reopening Projects in NetBeans IDE

    Projects in the IDE are represented by a folder rather than a file. If you close a project, you can open it again by choosing the File | Open Project command and navigating to the folder containing the project's build script. Project folders are marked with the icon.

    @http://www.netbeans.org/kb/articles/import-jbuilder.html

    2007/03/02 17:37 2007/03/02 17:37
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    어.. 비오네..

    2007/03/02 16:44

    서비 낙서장

    비오는 주말 오후라니..

    원래 비오는 날을 무지 싫어하는데..
    이렇게 나름대로 운치있게 내려주니
    나쁘진 않네.

    뭐.. 바쁘지 않은 회사일과.. 주말.. 봄.. 이런 저런 요소들
    때문이긴 하겠지만.

    역시, 사람은 변하기 때문이겠지?
    2007/03/02 16:44 2007/03/02 16:44
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
    1. 2007/03/03 09:40
      어.. 비오네.. Tracked from 서비의 다락방