Home | History | Annotate | Download | only in jsse
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.apache.harmony.xnet.provider.jsse;
     18 
     19 import java.math.BigInteger;
     20 import java.security.InvalidKeyException;
     21 import java.security.interfaces.DSAParams;
     22 import java.security.interfaces.DSAPrivateKey;
     23 import java.security.spec.DSAPrivateKeySpec;
     24 import java.security.spec.InvalidKeySpecException;
     25 
     26 public class OpenSSLDSAPrivateKey implements DSAPrivateKey {
     27     private static final long serialVersionUID = 6524734576187424628L;
     28 
     29     private final OpenSSLKey key;
     30 
     31     private OpenSSLDSAParams params;
     32 
     33     OpenSSLDSAPrivateKey(OpenSSLKey key) {
     34         this.key = key;
     35     }
     36 
     37     OpenSSLKey getOpenSSLKey() {
     38         return key;
     39     }
     40 
     41     OpenSSLDSAPrivateKey(DSAPrivateKeySpec dsaKeySpec) throws InvalidKeySpecException {
     42         try {
     43             key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
     44                     dsaKeySpec.getP().toByteArray(),
     45                     dsaKeySpec.getQ().toByteArray(),
     46                     dsaKeySpec.getG().toByteArray(),
     47                     null,
     48                     dsaKeySpec.getX().toByteArray()));
     49         } catch (Exception e) {
     50             throw new InvalidKeySpecException(e);
     51         }
     52     }
     53 
     54     private void ensureReadParams() {
     55         if (params == null) {
     56             params = new OpenSSLDSAParams(key);
     57         }
     58     }
     59 
     60     static OpenSSLKey getInstance(DSAPrivateKey dsaPrivateKey) throws InvalidKeyException {
     61         try {
     62             DSAParams dsaParams = dsaPrivateKey.getParams();
     63             return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
     64                     dsaParams.getP().toByteArray(),
     65                     dsaParams.getQ().toByteArray(),
     66                     dsaParams.getG().toByteArray(),
     67                     null,
     68                     dsaPrivateKey.getX().toByteArray()));
     69         } catch (Exception e) {
     70             throw new InvalidKeyException(e);
     71         }
     72     }
     73 
     74     @Override
     75     public DSAParams getParams() {
     76         ensureReadParams();
     77         return params;
     78     }
     79 
     80     @Override
     81     public String getAlgorithm() {
     82         return "DSA";
     83     }
     84 
     85     @Override
     86     public String getFormat() {
     87         /*
     88          * If we're using an OpenSSL ENGINE, there's no guarantee we can export
     89          * the key. Returning {@code null} tells the caller that there's no
     90          * encoded format.
     91          */
     92         if (key.isEngineBased()) {
     93             return null;
     94         }
     95 
     96         return "PKCS#8";
     97     }
     98 
     99     @Override
    100     public byte[] getEncoded() {
    101         /*
    102          * If we're using an OpenSSL ENGINE, there's no guarantee we can export
    103          * the key. Returning {@code null} tells the caller that there's no
    104          * encoded format.
    105          */
    106         if (key.isEngineBased()) {
    107             return null;
    108         }
    109 
    110         return NativeCrypto.i2d_PKCS8_PRIV_KEY_INFO(key.getPkeyContext());
    111     }
    112 
    113     @Override
    114     public BigInteger getX() {
    115         ensureReadParams();
    116         return params.getX();
    117     }
    118 
    119     public int getPkeyContext() {
    120         return key.getPkeyContext();
    121     }
    122 
    123     @Override
    124     public boolean equals(Object o) {
    125         if (o == this) {
    126             return true;
    127         }
    128 
    129         if (o instanceof OpenSSLDSAPrivateKey) {
    130             OpenSSLDSAPrivateKey other = (OpenSSLDSAPrivateKey) o;
    131 
    132             /*
    133              * We can shortcut the true case, but it still may be equivalent but
    134              * different copies.
    135              */
    136             if (key.equals(other.getOpenSSLKey())) {
    137                 return true;
    138             }
    139         }
    140 
    141         if (!(o instanceof DSAPrivateKey)) {
    142             return false;
    143         }
    144 
    145         ensureReadParams();
    146 
    147         final BigInteger x = params.getX();
    148         if (x == null) {
    149             /*
    150              * If our X is null, we can't tell if these two private keys are
    151              * equivalent. This usually happens if this key is ENGINE-based. If
    152              * the other key was ENGINE-based, we should have caught it in the
    153              * OpenSSLDSAPrivateKey case.
    154              */
    155             return false;
    156         }
    157 
    158         final DSAPrivateKey other = (DSAPrivateKey) o;
    159         return x.equals(other.getX()) && params.equals(other.getParams());
    160     }
    161 
    162     @Override
    163     public int hashCode() {
    164         ensureReadParams();
    165 
    166         int hash = 1;
    167 
    168         final BigInteger x = getX();
    169         if (x != null) {
    170             hash = hash * 3 + x.hashCode();
    171         }
    172 
    173         hash = hash * 7 + params.hashCode();
    174 
    175         return hash;
    176     }
    177 
    178     @Override
    179     public String toString() {
    180         final StringBuilder sb = new StringBuilder("OpenSSLDSAPrivateKey{");
    181 
    182         if (key.isEngineBased()) {
    183             sb.append("key=");
    184             sb.append(key);
    185             sb.append('}');
    186             return sb.toString();
    187         }
    188 
    189         ensureReadParams();
    190         sb.append("X=");
    191         sb.append(params.getX().toString(16));
    192         sb.append(',');
    193         sb.append("params=");
    194         sb.append(params.toString());
    195         sb.append('}');
    196 
    197         return sb.toString();
    198     }
    199 }
    200