1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * TODO 20 * 1. The class extends the PublicKeyImpl class in "org.apache.harmony.security" package. 21 * 22 * 2. The class uses methods in the auxiliary non-public "ThreeIntegerSequence" class 23 * defined along with the "DSAPrivateKeyImpl" class. 24 * 25 * 3. See a compatibility with RI comments 26 * in the below "DSAPublicKeyImpl(X509EncodedKeySpec keySpec)" constructor. 27 */ 28 29 package org.apache.harmony.security.provider.crypto; 30 31 import java.io.IOException; 32 import java.io.NotActiveException; 33 import java.math.BigInteger; 34 import java.security.interfaces.DSAParams; 35 import java.security.interfaces.DSAPublicKey; 36 import java.security.spec.DSAParameterSpec; 37 import java.security.spec.DSAPublicKeySpec; 38 import java.security.spec.InvalidKeySpecException; 39 import java.security.spec.X509EncodedKeySpec; 40 import org.apache.harmony.security.PublicKeyImpl; 41 import org.apache.harmony.security.asn1.ASN1Integer; 42 import org.apache.harmony.security.utils.AlgNameMapper; 43 import org.apache.harmony.security.x509.AlgorithmIdentifier; 44 import org.apache.harmony.security.x509.SubjectPublicKeyInfo; 45 46 /** 47 * The class provides DSAPublicKey functionality by extending a class implementing PublicKey 48 * and implementing methods defined in both interfaces, DSAKey and DSAPublicKey 49 */ 50 public class DSAPublicKeyImpl extends PublicKeyImpl implements DSAPublicKey { 51 52 /** 53 * @serial 54 */ 55 private static final long serialVersionUID = -2279672131310978336L; 56 57 private BigInteger y, g, p, q; 58 59 private transient DSAParams params; 60 61 /** 62 * Creates object from DSAPublicKeySpec. 63 * 64 * @param keySpec - a DSAPublicKeySpec object 65 */ 66 public DSAPublicKeyImpl(DSAPublicKeySpec keySpec) { 67 68 super("DSA"); 69 70 SubjectPublicKeyInfo spki; 71 72 p = keySpec.getP(); 73 q = keySpec.getQ(); 74 g = keySpec.getG(); 75 76 ThreeIntegerSequence threeInts = new ThreeIntegerSequence(p 77 .toByteArray(), q.toByteArray(), g.toByteArray()); 78 79 AlgorithmIdentifier ai = new AlgorithmIdentifier(AlgNameMapper 80 .map2OID("DSA"), 81 threeInts.getEncoded()); 82 83 y = keySpec.getY(); 84 85 spki = new SubjectPublicKeyInfo(ai, ASN1Integer.getInstance().encode( 86 y.toByteArray())); 87 setEncoding(spki.getEncoded()); 88 89 params = (DSAParams) (new DSAParameterSpec(p, q, g)); 90 } 91 92 /** 93 * Creates object from X509EncodedKeySpec. 94 * 95 * @param keySpec - a X509EncodedKeySpec object 96 * 97 * @throws InvalidKeySpecException - if key data cannot be obtain from encoded format 98 */ 99 public DSAPublicKeyImpl(X509EncodedKeySpec keySpec) 100 throws InvalidKeySpecException { 101 102 super("DSA"); 103 104 AlgorithmIdentifier ai; 105 ThreeIntegerSequence threeInts = null; 106 107 SubjectPublicKeyInfo subjectPublicKeyInfo = null; 108 109 byte[] encoding = keySpec.getEncoded(); 110 111 String alg, algName; 112 113 try { 114 subjectPublicKeyInfo = (SubjectPublicKeyInfo) SubjectPublicKeyInfo.ASN1 115 .decode(encoding); 116 } catch (IOException e) { 117 throw new InvalidKeySpecException("Failed to decode keySpec encoding: " + e); 118 } 119 120 try { 121 y = new BigInteger((byte[]) ASN1Integer.getInstance().decode( 122 subjectPublicKeyInfo.getSubjectPublicKey())); 123 } catch (IOException e) { 124 throw new InvalidKeySpecException("Failed to decode parameters: " + e); 125 } 126 127 ai = subjectPublicKeyInfo.getAlgorithmIdentifier(); 128 129 try { 130 threeInts = (ThreeIntegerSequence) ThreeIntegerSequence.ASN1 131 .decode(ai.getParameters()); 132 } catch (IOException e) { 133 throw new InvalidKeySpecException("Failed to decode parameters: " + e); 134 } 135 p = new BigInteger(threeInts.p); 136 q = new BigInteger(threeInts.q); 137 g = new BigInteger(threeInts.g); 138 params = (DSAParams) (new DSAParameterSpec(p, q, g)); 139 140 setEncoding(encoding); 141 142 /* 143 * the following code implements RI behavior 144 */ 145 alg = ai.getAlgorithm(); 146 algName = AlgNameMapper.map2AlgName(alg); 147 setAlgorithm(algName == null ? alg : algName); 148 } 149 150 /** 151 * @return 152 * a value of a public key (y). 153 */ 154 public BigInteger getY() { 155 return y; 156 } 157 158 /** 159 * @return 160 * DSA key parameters (p, q, g). 161 */ 162 public DSAParams getParams() { 163 return params; 164 } 165 166 private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException { 167 in.defaultReadObject(); 168 params = new DSAParameterSpec(p, q, g); 169 } 170 171 } 172