15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2012 The Android Open Source Project 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * you may not use this file except in compliance with the License. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS, 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the License for the specific language governing permissions and 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * limitations under the License. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package org.conscrypt; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.IOException; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.NotSerializableException; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.ObjectInputStream; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.ObjectOutputStream; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.math.BigInteger; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.security.InvalidKeyException; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.security.interfaces.RSAPrivateCrtKey; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.security.interfaces.RSAPrivateKey; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.security.spec.InvalidKeySpecException; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.security.spec.RSAPrivateCrtKeySpec; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class OpenSSLRSAPrivateCrtKey extends OpenSSLRSAPrivateKey implements RSAPrivateCrtKey { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final long serialVersionUID = 3785291944868707197L; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BigInteger publicExponent; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BigInteger primeP; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BigInteger primeQ; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BigInteger primeExponentP; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BigInteger primeExponentQ; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BigInteger crtCoefficient; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSSLRSAPrivateCrtKey(OpenSSLKey key) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(key); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSSLRSAPrivateCrtKey(OpenSSLKey key, byte[][] params) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(key, params); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public OpenSSLRSAPrivateCrtKey(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(init(rsaKeySpec)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static OpenSSLKey init(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BigInteger modulus = rsaKeySpec.getModulus(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BigInteger privateExponent = rsaKeySpec.getPrivateExponent(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (modulus == null) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new InvalidKeySpecException("modulus == null"); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (privateExponent == null) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new InvalidKeySpecException("privateExponent == null"); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OpenSSL uses the public modulus to do RSA blinding. If 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the public modulus is not available, the call to 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * EVP_PKEY_new_RSA will turn off blinding for this key 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instance. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger publicExponent = rsaKeySpec.getPublicExponent(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeP = rsaKeySpec.getPrimeP(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeQ = rsaKeySpec.getPrimeQ(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeExponentP = rsaKeySpec.getPrimeExponentP(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeExponentQ = rsaKeySpec.getPrimeExponentQ(); 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) final BigInteger crtCoefficient = rsaKeySpec.getCrtCoefficient(); 80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) modulus.toByteArray(), 83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) publicExponent == null ? null : publicExponent.toByteArray(), 84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) privateExponent.toByteArray(), 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeP == null ? null : primeP.toByteArray(), 86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeQ == null ? null : primeQ.toByteArray(), 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeExponentP == null ? null : primeExponentP.toByteArray(), 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeExponentQ == null ? null : primeExponentQ.toByteArray(), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crtCoefficient == null ? null : crtCoefficient.toByteArray())); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (Exception e) { 91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) throw new InvalidKeySpecException(e); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static OpenSSLKey getInstance(RSAPrivateCrtKey rsaPrivateKey) throws InvalidKeyException { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the key is not encodable (PKCS11-like key), then wrap it and use 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * JNI upcalls to satisfy requests. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rsaPrivateKey.getFormat() == null) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wrapPlatformKey(rsaPrivateKey); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) BigInteger modulus = rsaPrivateKey.getModulus(); 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BigInteger privateExponent = rsaPrivateKey.getPrivateExponent(); 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (modulus == null) { 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch throw new InvalidKeyException("modulus == null"); 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (privateExponent == null) { 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch throw new InvalidKeyException("privateExponent == null"); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OpenSSL uses the public modulus to do RSA blinding. If 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the public modulus is not available, the call to 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * EVP_PKEY_new_RSA will turn off blinding for this key 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instance. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger publicExponent = rsaPrivateKey.getPublicExponent(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeP = rsaPrivateKey.getPrimeP(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeQ = rsaPrivateKey.getPrimeQ(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeExponentP = rsaPrivateKey.getPrimeExponentP(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger primeExponentQ = rsaPrivateKey.getPrimeExponentQ(); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final BigInteger crtCoefficient = rsaPrivateKey.getCrtCoefficient(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modulus.toByteArray(), 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) publicExponent == null ? null : publicExponent.toByteArray(), 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) privateExponent.toByteArray(), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) primeP == null ? null : primeP.toByteArray(), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) primeQ == null ? null : primeQ.toByteArray(), 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) primeExponentP == null ? null : primeExponentP.toByteArray(), 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) primeExponentQ == null ? null : primeExponentQ.toByteArray(), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crtCoefficient == null ? null : crtCoefficient.toByteArray())); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (Exception e) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new InvalidKeyException(e); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) @Override 142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) synchronized void readParams(byte[][] params) { 143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) super.readParams(params); 144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // params[0] read in super.readParams 145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (params[1] != null) { 146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) publicExponent = new BigInteger(params[1]); 147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // params[2] read in super.readParams 149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (params[3] != null) { 150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeP = new BigInteger(params[3]); 151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (params[4] != null) { 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeQ = new BigInteger(params[4]); 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (params[5] != null) { 156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeExponentP = new BigInteger(params[5]); 157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (params[6] != null) { 159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) primeExponentQ = new BigInteger(params[6]); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 161 if (params[7] != null) { 162 crtCoefficient = new BigInteger(params[7]); 163 } 164 } 165 166 @Override 167 public BigInteger getPublicExponent() { 168 ensureReadParams(); 169 return publicExponent; 170 } 171 172 @Override 173 public BigInteger getPrimeP() { 174 ensureReadParams(); 175 return primeP; 176 } 177 178 @Override 179 public BigInteger getPrimeQ() { 180 ensureReadParams(); 181 return primeQ; 182 } 183 184 @Override 185 public BigInteger getPrimeExponentP() { 186 ensureReadParams(); 187 return primeExponentP; 188 } 189 190 @Override 191 public BigInteger getPrimeExponentQ() { 192 ensureReadParams(); 193 return primeExponentQ; 194 } 195 196 @Override 197 public BigInteger getCrtCoefficient() { 198 ensureReadParams(); 199 return crtCoefficient; 200 } 201 202 @Override 203 public boolean equals(Object o) { 204 if (o == this) { 205 return true; 206 } 207 208 if (o instanceof OpenSSLRSAPrivateKey) { 209 OpenSSLRSAPrivateKey other = (OpenSSLRSAPrivateKey) o; 210 return getOpenSSLKey().equals(other.getOpenSSLKey()); 211 } 212 213 if (o instanceof RSAPrivateCrtKey) { 214 ensureReadParams(); 215 RSAPrivateCrtKey other = (RSAPrivateCrtKey) o; 216 217 if (getOpenSSLKey().isEngineBased()) { 218 return getModulus().equals(other.getModulus()) 219 && publicExponent.equals(other.getPublicExponent()); 220 } else { 221 return getModulus().equals(other.getModulus()) 222 && publicExponent.equals(other.getPublicExponent()) 223 && getPrivateExponent().equals(other.getPrivateExponent()) 224 && primeP.equals(other.getPrimeP()) && primeQ.equals(other.getPrimeQ()) 225 && primeExponentP.equals(other.getPrimeExponentP()) 226 && primeExponentQ.equals(other.getPrimeExponentQ()) 227 && crtCoefficient.equals(other.getCrtCoefficient()); 228 } 229 } else if (o instanceof RSAPrivateKey) { 230 ensureReadParams(); 231 RSAPrivateKey other = (RSAPrivateKey) o; 232 233 if (getOpenSSLKey().isEngineBased()) { 234 return getModulus().equals(other.getModulus()); 235 } else { 236 return getModulus().equals(other.getModulus()) 237 && getPrivateExponent().equals(other.getPrivateExponent()); 238 } 239 } 240 241 return false; 242 } 243 244 @Override 245 public final int hashCode() { 246 int hashCode = super.hashCode(); 247 if (publicExponent != null) { 248 hashCode ^= publicExponent.hashCode(); 249 } 250 return hashCode; 251 } 252 253 @Override 254 public String toString() { 255 final StringBuilder sb = new StringBuilder("OpenSSLRSAPrivateCrtKey{"); 256 257 final boolean engineBased = getOpenSSLKey().isEngineBased(); 258 if (engineBased) { 259 sb.append("key="); 260 sb.append(getOpenSSLKey()); 261 sb.append('}'); 262 } 263 264 ensureReadParams(); 265 sb.append("modulus="); 266 sb.append(getModulus().toString(16)); 267 sb.append(','); 268 269 if (publicExponent != null) { 270 sb.append("publicExponent="); 271 sb.append(publicExponent.toString(16)); 272 sb.append(','); 273 } 274 275 if (!engineBased) { 276 sb.append("privateExponent="); 277 sb.append(getPrivateExponent().toString(16)); 278 sb.append(','); 279 } 280 281 if (primeP != null) { 282 sb.append("primeP="); 283 sb.append(primeP.toString(16)); 284 sb.append(','); 285 } 286 287 if (primeQ != null) { 288 sb.append("primeQ="); 289 sb.append(primeQ.toString(16)); 290 sb.append(','); 291 } 292 293 if (primeExponentP != null) { 294 sb.append("primeExponentP="); 295 sb.append(primeExponentP.toString(16)); 296 sb.append(','); 297 } 298 299 if (primeExponentQ != null) { 300 sb.append("primeExponentQ="); 301 sb.append(primeExponentQ.toString(16)); 302 sb.append(','); 303 } 304 305 if (crtCoefficient != null) { 306 sb.append("crtCoefficient="); 307 sb.append(crtCoefficient.toString(16)); 308 sb.append(','); 309 } 310 311 return sb.toString(); 312 } 313 314 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 315 stream.defaultReadObject(); 316 317 key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 318 modulus.toByteArray(), 319 publicExponent == null ? null : publicExponent.toByteArray(), 320 privateExponent.toByteArray(), 321 primeP == null ? null : primeP.toByteArray(), 322 primeQ == null ? null : primeQ.toByteArray(), 323 primeExponentP == null ? null : primeExponentP.toByteArray(), 324 primeExponentQ == null ? null : primeExponentQ.toByteArray(), 325 crtCoefficient == null ? null : crtCoefficient.toByteArray())); 326 fetchedParams = true; 327 } 328 329 private void writeObject(ObjectOutputStream stream) throws IOException { 330 if (getOpenSSLKey().isEngineBased()) { 331 throw new NotSerializableException("engine-based keys can not be serialized"); 332 } 333 334 ensureReadParams(); 335 stream.defaultWriteObject(); 336 } 337} 338