src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java
changeset 52946 752e57845ad2
parent 47216 71c04702a3d5
equal deleted inserted replaced
52945:de85ab85fbc7 52946:752e57845ad2
     1 /*
     1 /*
     2  * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    30 
    30 
    31 import java.security.*;
    31 import java.security.*;
    32 import java.security.interfaces.*;
    32 import java.security.interfaces.*;
    33 import java.security.spec.*;
    33 import java.security.spec.*;
    34 
    34 
    35 import sun.security.util.DerInputStream;
    35 import sun.security.util.*;
    36 import sun.security.util.DerOutputStream;
       
    37 import sun.security.util.DerValue;
       
    38 import sun.security.util.ECParameters;
       
    39 import sun.security.util.ECUtil;
       
    40 import sun.security.x509.AlgorithmId;
    36 import sun.security.x509.AlgorithmId;
    41 import sun.security.pkcs.PKCS8Key;
    37 import sun.security.pkcs.PKCS8Key;
    42 
    38 
    43 /**
    39 /**
    44  * Key implementation for EC private keys.
    40  * Key implementation for EC private keys.
    66 public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
    62 public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
    67 
    63 
    68     private static final long serialVersionUID = 88695385615075129L;
    64     private static final long serialVersionUID = 88695385615075129L;
    69 
    65 
    70     private BigInteger s;       // private value
    66     private BigInteger s;       // private value
       
    67     private byte[] arrayS;      // private value as a little-endian array
    71     private ECParameterSpec params;
    68     private ECParameterSpec params;
    72 
    69 
    73     /**
    70     /**
    74      * Construct a key from its encoding. Called by the ECKeyFactory.
    71      * Construct a key from its encoding. Called by the ECKeyFactory.
    75      */
    72      */
    83      */
    80      */
    84     ECPrivateKeyImpl(BigInteger s, ECParameterSpec params)
    81     ECPrivateKeyImpl(BigInteger s, ECParameterSpec params)
    85             throws InvalidKeyException {
    82             throws InvalidKeyException {
    86         this.s = s;
    83         this.s = s;
    87         this.params = params;
    84         this.params = params;
    88         // generate the encoding
    85         makeEncoding(s);
       
    86 
       
    87     }
       
    88 
       
    89     ECPrivateKeyImpl(byte[] s, ECParameterSpec params)
       
    90             throws InvalidKeyException {
       
    91         this.arrayS = s.clone();
       
    92         this.params = params;
       
    93         makeEncoding(s);
       
    94     }
       
    95 
       
    96     private void makeEncoding(byte[] s) throws InvalidKeyException {
    89         algid = new AlgorithmId
    97         algid = new AlgorithmId
    90             (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
    98         (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
    91         try {
    99         try {
    92             DerOutputStream out = new DerOutputStream();
   100             DerOutputStream out = new DerOutputStream();
    93             out.putInteger(1); // version 1
   101             out.putInteger(1); // version 1
    94             byte[] privBytes = ECUtil.trimZeroes(s.toByteArray());
   102             byte[] privBytes = s.clone();
       
   103             ArrayUtil.reverse(privBytes);
    95             out.putOctetString(privBytes);
   104             out.putOctetString(privBytes);
    96             DerValue val =
   105             DerValue val =
    97                 new DerValue(DerValue.tag_Sequence, out.toByteArray());
   106                 new DerValue(DerValue.tag_Sequence, out.toByteArray());
    98             key = val.toByteArray();
   107             key = val.toByteArray();
    99         } catch (IOException exc) {
   108         } catch (IOException exc) {
   100             // should never occur
   109             // should never occur
   101             throw new InvalidKeyException(exc);
   110             throw new InvalidKeyException(exc);
   102         }
   111         }
   103     }
   112     }
   104 
   113 
       
   114     private void makeEncoding(BigInteger s) throws InvalidKeyException {
       
   115         algid = new AlgorithmId
       
   116         (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
       
   117         try {
       
   118             byte[] sArr = s.toByteArray();
       
   119             // convert to fixed-length array
       
   120             int numOctets = (params.getOrder().bitLength() + 7) / 8;
       
   121             byte[] sOctets = new byte[numOctets];
       
   122             int inPos = Math.max(sArr.length - sOctets.length, 0);
       
   123             int outPos = Math.max(sOctets.length - sArr.length, 0);
       
   124             int length = Math.min(sArr.length, sOctets.length);
       
   125             System.arraycopy(sArr, inPos, sOctets, outPos, length);
       
   126 
       
   127             DerOutputStream out = new DerOutputStream();
       
   128             out.putInteger(1); // version 1
       
   129             out.putOctetString(sOctets);
       
   130             DerValue val =
       
   131                 new DerValue(DerValue.tag_Sequence, out.toByteArray());
       
   132             key = val.toByteArray();
       
   133         } catch (IOException exc) {
       
   134             // should never occur
       
   135             throw new InvalidKeyException(exc);
       
   136         }
       
   137     }
       
   138 
   105     // see JCA doc
   139     // see JCA doc
   106     public String getAlgorithm() {
   140     public String getAlgorithm() {
   107         return "EC";
   141         return "EC";
   108     }
   142     }
   109 
   143 
   110     // see JCA doc
   144     // see JCA doc
   111     public BigInteger getS() {
   145     public BigInteger getS() {
       
   146         if (s == null) {
       
   147             byte[] arrCopy = arrayS.clone();
       
   148             ArrayUtil.reverse(arrCopy);
       
   149             s = new BigInteger(1, arrCopy);
       
   150         }
   112         return s;
   151         return s;
       
   152     }
       
   153 
       
   154     public byte[] getArrayS() {
       
   155         if (arrayS == null) {
       
   156             byte[] arr = getS().toByteArray();
       
   157             ArrayUtil.reverse(arr);
       
   158             int byteLength = (params.getOrder().bitLength() + 7) / 8;
       
   159             arrayS = new byte[byteLength];
       
   160             int length = Math.min(byteLength, arr.length);
       
   161             System.arraycopy(arr, 0, arrayS, 0, length);
       
   162         }
       
   163         return arrayS.clone();
   113     }
   164     }
   114 
   165 
   115     // see JCA doc
   166     // see JCA doc
   116     public ECParameterSpec getParams() {
   167     public ECParameterSpec getParams() {
   117         return params;
   168         return params;
   131             int version = data.getInteger();
   182             int version = data.getInteger();
   132             if (version != 1) {
   183             if (version != 1) {
   133                 throw new IOException("Version must be 1");
   184                 throw new IOException("Version must be 1");
   134             }
   185             }
   135             byte[] privData = data.getOctetString();
   186             byte[] privData = data.getOctetString();
   136             s = new BigInteger(1, privData);
   187             ArrayUtil.reverse(privData);
       
   188             arrayS = privData;
   137             while (data.available() != 0) {
   189             while (data.available() != 0) {
   138                 DerValue value = data.getDerValue();
   190                 DerValue value = data.getDerValue();
   139                 if (value.isContextSpecific((byte)0)) {
   191                 if (value.isContextSpecific((byte) 0)) {
   140                     // ignore for now
   192                     // ignore for now
   141                 } else if (value.isContextSpecific((byte)1)) {
   193                 } else if (value.isContextSpecific((byte) 1)) {
   142                     // ignore for now
   194                     // ignore for now
   143                 } else {
   195                 } else {
   144                     throw new InvalidKeyException("Unexpected value: " + value);
   196                     throw new InvalidKeyException("Unexpected value: " + value);
   145                 }
   197                 }
   146             }
   198             }