/// <summary> /// Create a Subject Public Key Info object for a given public key. /// </summary> /// <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RSAKeyParameters or ECPublicKeyParameters</param> /// <returns>A subject public key info object.</returns> /// <exception cref="Exception">Throw exception if object provided is not one of the above.</exception> public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo(AsymmetricKeyParameter key) { if (key.isPrivate()) { throw (new Exception("Private key passed - public key expected.")); } if (key is ElGamalPublicKeyParameters) { ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)key; SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( new AlgorithmIdentifier( OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter( _key.getParameters().getP(), _key.getParameters().getG() ).toASN1Object()), new DERInteger(_key.getY())); return(info); } if (key is DSAPublicKeyParameters) { DSAPublicKeyParameters _key = (DSAPublicKeyParameters)key; SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( new AlgorithmIdentifier( X9ObjectIdentifiers.id_dsa, new DSAParameter(_key.getParameters().getP(), _key.getParameters().getQ(), _key.getParameters().getG()).toASN1Object()), new DERInteger(_key.getY()) ); return(info); } if (key is DHPublicKeyParameters) { DHPublicKeyParameters _key = (DHPublicKeyParameters)key; SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( new AlgorithmIdentifier(X9ObjectIdentifiers.dhpublicnumber, new DHParameter(_key.getParameters().getP(), _key.getParameters().getG(), _key.getParameters().getJ()).toASN1Object()), new DERInteger(_key.getY())); return(info); } // End of DH if (key is RSAKeyParameters) { RSAKeyParameters _key = (RSAKeyParameters)key; if (_key.isPrivate()) { throw (new Exception("Private RSA Key provided.")); } SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, new DERNull()), new RSAPublicKeyStructure(_key.getModulus(), _key.getExponent()).toASN1Object()); return(info); } // End of RSA. if (key is ECPublicKeyParameters) { ECPublicKeyParameters _key = (ECPublicKeyParameters)key; X9ECParameters ecP = new X9ECParameters( _key.getParameters().getCurve(), _key.getParameters().getG(), _key.getParameters().getN(), _key.getParameters().getH(), _key.getParameters().getSeed()); X962Parameters x962 = new X962Parameters(ecP); ASN1OctetString p = (ASN1OctetString)(new X9ECPoint(_key.getQ()).toASN1Object()); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, x962.toASN1Object()), p.getOctets()); return(info); } // End of EC throw (new Exception("Class provided no convertable:" + key.GetType())); }
/** * Process a single block using the basic RSA algorithm. * * @param in the input array. * @param inOff the offset into the input buffer where the data starts. * @param inLen the length of the data to be processed. * @return the result of the RSA process. * @exception DataLengthException the input block is too large. */ public byte[] processBlock( byte[] inBytes, int inOff, int inLen) { if (inLen > (getInputBlockSize() + 1)) { throw new DataLengthException("input too large for RSA cipher.\n"); } else if (inLen == (getInputBlockSize() + 1) && (inBytes[inOff] & 0x80) != 0) { throw new DataLengthException("input too large for RSA cipher.\n"); } byte[] block; if (inOff != 0 || inLen != inBytes.Length) { block = new byte[inLen]; Array.Copy(inBytes, inOff, block, 0, inLen); } else { block = inBytes; } BigInteger input = new BigInteger(1, block); byte[] output; if (typeof(RSAPrivateCrtKeyParameters).IsInstanceOfType(key)) { // // we have the extra factors, use the Chinese Remainder Theorem - the author // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for // advice regarding the expression of this. // RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key; BigInteger p = crtKey.getP(); BigInteger q = crtKey.getQ(); BigInteger dP = crtKey.getDP(); BigInteger dQ = crtKey.getDQ(); BigInteger qInv = crtKey.getQInv(); BigInteger mP, mQ, h, m; // mP = ((input mod p) ^ dP)) mod p mP = (input.remainder(p)).modPow(dP, p); // mQ = ((input mod q) ^ dQ)) mod q mQ = (input.remainder(q)).modPow(dQ, q); // h = qInv * (mP - mQ) mod p h = mP.subtract(mQ); h = h.multiply(qInv); h = h.mod(p); // mod (in Java) returns the positive residual // m = h * q + mQ m = h.multiply(q); m = m.add(mQ); output = m.toByteArray(); } else { output = input.modPow( key.getExponent(), key.getModulus()).toByteArray(); } if (forEncryption) { if (output[0] == 0 && output.Length > getOutputBlockSize()) // have ended up with an extra zero byte, copy down. { byte[] tmp = new byte[output.Length - 1]; Array.Copy(output, 1, tmp, 0, tmp.Length); return(tmp); } if (output.Length < getOutputBlockSize()) // have ended up with less bytes than normal, lengthen { byte[] tmp = new byte[getOutputBlockSize()]; Array.Copy(output, 0, tmp, tmp.Length - output.Length, output.Length); return(tmp); } } else { if (output[0] == 0) // have ended up with an extra zero byte, copy down. { byte[] tmp = new byte[output.Length - 1]; Array.Copy(output, 1, tmp, 0, tmp.Length); return(tmp); } } return(output); }