Download lecture notes

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
An example using the SUN provider
The provider SUN is supplied in Java 2SDK.
 SUN provides both
an implementation of the NIST Digital Signature Algorithm
(DSA), and
 an implementation of the MD5 and NIST SHA-1 message
digest algorithms.
Class MessageDigest :
looking at code that generates a message digest from a message.
MessageDigest messagedigest = MessageDigest. getInstance("SHA");
MessageDigest messagedigest = MessageDigest.getInstance("SHA", "SUN");
getInstance() method can be used in two different way.
 The first requires only the algorithm to be specified.
The second requires both the algorithm and the provider
to be specified.
Both return an instance of a class that implements the
SHA algorithm.
 Next, we pass the message through the message-digest
generator.
int n = 0;
byte [ ] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
messagedigest.update(rgb, 0, n);
}
 This code works well for large messages of unknown length.
 The update() method also accepts a single byte as an argument for
messages of a few bytes in length, and
 a byte array for messages of a fixed or predictable size.
 The final step involves generating the message digest
itself.
rgb = messagedigest.digest();
The resulting digest is encoded in an array of bytes.
Message Digest Algorithm
 A message digest algorithm computes a
(typically shorter) fixed-size string from a
message called the message digest (also known
as a digital fingerprint).
 Any change to the original message will result in
a different message digest, providing a way to
verify the integrity (that is, check the fingerprint)
of the original message.
The message digest algorithm creates a message digest from a message.
The Complete Source Code
for a program that
Generates a Message
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
Public class MessageDigestGenerator
{
public void generateMessageDigest( InputStream inputstreamMessage,
OutputStream outputstreamMessageDigest)
throws NoSuchAlgorithmException,
IOException
{
MessageDigest messagedigest = MessageDigest.getInstance("SHA");
int n = 0;
byte [ ] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
messagedigest.update(rgb, 0, n);
}
rgb = messagedigest.digest();
outputstreamMessageDigest.write(rgb);
}
public static void main(String [] rgstring)
{
try
{
FileInputStream fileinputstream = new FileInputStream(rgstring[0]);
FileOutputStream fileoutputstream = new FileOutputStream(rgstring[1]);
new MessageDigestGenerator(). generateMessageDigest (fileinputstream,
fileoutputstream);
fileinputstream.close();
fileoutputstream.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
Classes InputStream & OutputStream
 public abstract class InputStream extends Object
This abstract class is the superclass of all classes
representing an input stream of bytes.
Applications that need to define a subclass of
InputStream must always provide a method that
returns the next byte of input.
 public abstract class OutputStream extends Object
This abstract class is the superclass of all classes
representing an output stream of bytes.
An output stream accepts output bytes and sends
them to some sink.
Applications that need to define a subclass of
OutputStream must always provide at least a method
that writes one byte of output.
InputStream class: read method detailed
 int read (byte[] b)
Reads some number of bytes from the input stream and stores them
into the buffer array b.
The number of bytes actually read is returned as an integer.
This method blocks until input data is available, end of file is
detected, or an exception is thrown.
 If b is null, a NullPointerException is thrown
.If the length of b is zero, then no bytes are read and 0 is returned;
otherwise, there is an attempt to read at least one byte.
 If no byte is available because the stream is at end of file, the value 1 is returned;
otherwise, at least one byte is read and stored into b.
 Parameter: b - the buffer into which the data is read.
 Returns: the total number of bytes read into the buffer, or -1 is
there is no more data because the end of the stream has been
reached.
 Throws: IOException - if an I/O error occurs.
NullPointerException- if b is null.
OutputStream class: write method detailed
 void write (byte[] b)
Writes b.length bytes from the specified byte array to this
output stream.
The general contract for write(b) is that it should have exactly
the same effect as the call
write(b, 0, b.length).
 Parameters: b - the data.
 Throws: IOException if an I/O error occurs.
o Class IOException
o java.lang.Object
o java.lang.Throwable
o java.lang.Exception
java.io.IOException
Class FileInputStream
 public class FileInputStream extends
InputStream
A FileInputStream obtains input bytes from a
file in a file system.
 What files are available depends on the host
environment.
FileInputStream is meant for reading streams
of raw bytes such as image data.
For reading streams of characters, consider
using FileReader.
FileInputStream Constructor
 public FileInputStream(String name) throws
FileNotFoundException
Creates a FileInputStream by opening a connection to an
actual file, the file named by the path name name in the
file system.
A new FileDescriptor object is created to represent this file
connection.
 First, if there is a security manager, its checkRead
method is called with the name argument as its argument.
If the named file does not exist, is a directory rather than a
regular file, or for some other reason cannot be opened
for reading then a FileNotFoundException is thrown.
Class FileOutputStream
 public class FileOutputStream extends
OutputStream
A file output stream is an output stream for writing data to a File
or to a FileDescriptor.
Whether or not a file is available or may be created depends
upon the underlying platform.
Some platforms, in particular, allow a file to be opened for writing
by only one FileOutputStream (or other file-writing object) at a
time.
In such situations the constructors in this class will fail if the file
involved is already open.
• FileOutputStream is meant for writing streams of
raw bytes such as image data.
• For writing streams of characters, consider using
FileWriter.
FileOutputStream Constructor
 public FileOutputStream(String name) throws
FileNotFoundException
 Creates an output file stream to write to the file with the specified
name.
 A new FileDescriptor object is created to represent this file connection.
 First, if there is a security manager, its checkWrite method is called
with name as its argument.
 Parameters: name - the system-dependent filename
 Throws: FileNotFoundException
if the file exists but is a directory rather than a regular file,
if the file does not exist but cannot be created, or
if the file cannot be opened for any other reason
SecurityException
if a security manager exists and its checkWrite method denies write
access to the file.
Key in Cryptographic Circles
 A key is a piece of information used to encrypt and/or decrypt
information
 There are two types of key-based cryptography:
secret-key and public-key.




Secret-key cryptography uses a single key that both
encrypts and decrypts the information to be protected.
Both the sender and the receiver must share the secretkey.
Secret-key cryptography is also known as symmetric
cryptography.
Public-key cryptography uses two keys:
a public key and a private key.
One key decrypts information encrypted with the other.
Only the private key must be protected.
Public key cryptography is used for authentication.
Class KeyPairGenerator
 To generate a digital signature (and encrypt data),
we need keys.
 Key generation, in its algorithm-independent form,
is not substantially similar to creating and using a
message digest.
KeyPairGenerator keypairgenerator =
KeyPairGenerator.getInstance ("DSA");
 this code creates an instance of a class that
generates DSA-compatible keys.
 A second (if necessary) argument specifies the
provider.
 After a key-pair generator instance is created, it must be
initialized.
 We can initialize key-pair generators in one of two ways:
algorithm-independent or algorithm-dependent.
Which method we use depends on the amount of control we want
over the final result.
keypairgenerator.initialize(1024, new SecureRandom());
 Keys based on different algorithms differ in how they're
generated, but they have one parameter in common -- the
key's strength.
 Strength is a relative term that corresponds roughly to how
hard the key will be to "break."
 If we use the algorithm-independent initializer, we can
specify only the strength -- any algorithm-dependent values
assume reasonable defaults.
DSAKeyPairGenerator dsakeypairgenerator = (DSAKeyPairGenerator)
keypairgenerator;
DSAParams dsaparams = new DSAParams()
{
private BigInteger p = BigInteger(...);
private BigInteger q = BigInteger(...);
private BigInteger g = BigInteger(...);
public BigInteger getP()
{
return p;
}
public BigInteger getQ()
{
return q;
}
public BigInteger getG()
{
return g;
}
};
dsakeypairgenerator.initialize(dsaparams, new SecureRandom());
 While the defaults are usually good enough, if we need more
control, it is available.
 Let's assume we used the engine to create a generator of
DSA-compatible keys, as in the code above.
 The engine loaded and instantiated an instance of a class
that implements the DSAKeyPairGenerator interface.
 If we cast the generic key-pair generator we received to
DSAKeyPairGenerator, we then gain access to the algorithmdependent method of initialization.
 To initialize a DSA key-pair generator, we need three values:
the prime P, the subprime Q, and the base G.
 These values are captured in an inner class instance that is
passed to the initialize() method.
• The SecureRandom class provides a secure source of
random numbers used in the key-pair generation.
return keypairgenerator.generateKeyPair();
 The final step involves generating the key pair itself.
The Complete Source Code for a
program that Generates a Key Pair.
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
public class KeyTools {
public static void writeToFile(Key key, File file) throws IOException {
FileOutputStream fileoutputstream = new FileOutputStream(file);
ObjectOutputStream objectoutputstream = new
ObjectOutputStream(fileoutputstream);
objectoutputstream.writeObject(key);
objectoutputstream.close(); }
public static Key readFromFile(File file)
throws ClassNotFoundException,
IOException
{
FileInputStream fileinputstream = new FileInputStream(file);
ObjectInputStream objectinputstream = new
ObjectInputStream (fileinputstream);
Key key = (Key)objectinputstream.readObject();
objectinputstream.close();
return key;
}
public static void writeToStream(Key key, OutputStream outputstream)
throws IOException
{
new ObjectOutputStream (outputstream) .writeObject(key);
}
public static Key readFromStream (InputStream inputstream)
throws ClassNotFoundException,IOException
{
return (Key) new ObjectInputStream (inputstream). readObject();
}
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException
{
KeyPairGenerator keypairgenerator = KeyPairGenerator.getInstance("DSA");
keypairgenerator.initialize(1024, new SecureRandom());
return
keypairgenerator.generateKeyPair();
}
public static void main(String [] rgstring)
{
try
{
File filePublic = new File(rgstring[0]);
File filePrivate = new File(rgstring[1]);
KeyPair keypair = generateKeyPair();
writeToFile(keypair.getPublic(), filePublic);
writeToFile(keypair.getPrivate(), filePrivate);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
Class ObjectOutputStream
 An ObjectOutputStream writes primitive data types and
graphs of Java objects to an OutputStream.
public class ObjectOutputStream extends OutputStream
 For example to write an object that can be read by the
example in ObjectInputStream:
FileOutputStream fos = new FileOutputStream("t.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeInt(12345);
oos.writeObject ("Today");
oos.writeObject(new Date());
oos.close();
 Only objects that support the java.io.Serializable interface
can be written to streams.
 The class of each serializable object is encoded including
the class name and signature of the class, the values of the
object's fields and arrays, and the closure of any other
objects referenced from the initial objects.
 The method writeObject is used to write an object to the
stream.
 Any object, including Strings and arrays, is written with
writeObject.
 Multiple objects or primitives can be written to the stream.
 The objects must be read back from the corresponding
ObjectInputstream with the same types and in the same
order as they were written
Digital Signature
 A digital signature is also generated from a
message.
 It differs from a message digest because the
private key of the message generator is
incorporated into the computation.
 The result is a message that has been "signed" by
the one who holds the private key.
 The computation is carried out in such a way that
anyone can use the message generator's public key
to verify that the entity signed it.
 A good digital signature algorithm guarantees that
the digital signature can't be forged (assuming the
private key is secret),
that the signature is good for only the message from which it was
generated,
 that the message cannot be changed without invalidating the
signature
that the message's authenticity can be verified.
The digital signature algorithm creates a digital signature from a message
and a private key.
Class Signature
 The creation and use of an instance of the Signature class is also similiar
to the two previous examples.
 The differences lie in how the instance is used either
 to sign or
 to verify a message.
Signature signature = Signature.getInstance ("DSA");
 Firstly, we use the engine to get an instance of the appropriate type.
 What we do next depends on whether or not we are signing or
verifying a message.
signature.initSign (privatekey);
 In order to sign a message, we must first initialize the signature
instance with the private key of the entity that is signing the message.
signature.initVerify(publickey);
 In order to verify a message, we must initialize the signature instance
with the public key of the entity that claims it signed the message.
int n = 0;
byte [] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
signature.update(rgb, 0, n);
}
 Next, regardless of whether or not we are signing or verifying, we must
pass the message through the signature generator.
 This process is similiar to the earlier example of generating a message
digest.
 The final step consists of generating the signature or verifying a signature.
rgb = signature.sign();
 If we are signing a message, the sign() method returns the signature.
signature.verify (rgbSignature);
 If we are verifying the signature previously generated from a message,
 we must use the verify() method.
 It takes as a parameter the previously generated signature and
determines whether or not it is still valid.
The Complete Source Code for
a program that Signs a Message
import java.security.Signature;
import java.security.PrivateKey;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class Sign
{
public static byte [ ] generateSignature (PrivateKey privatekey, InputStream
inputstreamMessage)
throws NoSuchAlgorithmException, nvalidKeyException, SignatureException,
IOException
{
Signature signature = Signature.getInstance("DSA");
signature.initSign (privatekey);
int n = 0;
byte [ ] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
signature.update (rgb, 0, n);
}
rgb = signature.sign();
return rgb; }
public static void main(String [] rgstring)
{
try
{
File filePrivate = new File(rgstring[0]);
File fileMessage = new File(rgstring[1]);
File fileSignature = new File(rgstring[2]);
PrivateKey privatekey = (PrivateKey)KeyTools.readFromFile(filePrivate);
FileInputStream fileinputstream = new FileInputStream(fileMessage);
byte [] rgb = generateSignature(privatekey, fileinputstream);
fileinputstream.close();
SignatureTools.writeToFile(rgb, fileSignature);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
The Complete Source Code for a
program that Verifies a Message.
import java.security.Signature;
import java.security.PublicKey;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Verify{
public static boolean verifySignature (PublicKey publickey,
Input Stream inputstreamMessage, byte [] rgbSignature)
throws NoSuchAlgorithmException, InvalidKeyException,
SignatureException,IOException
{
Signature signature = Signature.getInstance("DSA");
signature.initVerify(publickey);
int n = 0;
byte [] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
signature.update(rgb, 0, n);
}
return signature.verify(rgbSignature);
}
public static void main(String [] rgstring)
{ try
{
File filePublic = new File(rgstring[0]);
File fileMessage = new File(rgstring[1]);
File fileSignature = new File(rgstring[2]);
PublicKey publickey = (PublicKey)KeyTools.readFromFile(filePublic);
FileInputStream fileinputstream = new FileInputStream(fileMessage);
byte [] rgb = SignatureTools.readFromFile(fileSignature);
if (verifySignature (publickey, fileinputstream, rgb))
{
System.out.println ("true");
}
else
{
System.out.println ("false");
}
fileinputstream.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}} }
The JCA conveniently hides all the low-level implementation
and algorithm-specific details, allowing you to work at a
higher, more abstract level.
Of course, one of the risks of such an abstract approach is the
increased likelihood that we won't recognize erroneous
output resulting from bugs.
Given the role of cryptography, this can be a significant
problem.
Consider the "off-by-one" bug in the update line below:
int n = 0;
byte [] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
messagedigest.update(rgb, 0, n - 1);
}
 SUN version 1.5 sun.security.provider.Sun
 SunRsaSign version 1.5
sun.security.rsa.SunRsaSign
 SunJSSE version 1.5
com.sun.net.ssl.internal.ssl.Provider
 SunJCE version 1.5
com.sun.crypto.provider.SunJCE
 SunJGSS version 1.0
sun.security.jgss.SunProvider
 SunSASL version 1.5
com.sun.security.sasl.Provider
 SunDeploy-MSCrypto 1.5 version
com.sun.deploy.security.MSCryptoProvider
package sun.security.provider;
import java.io.*;
import java.util.*; import java.security.*;
public final class Sun extends Provider {
private static final String INFO = "SUN " + "(DSA key/parameter generation;
DSA signing; " + "SHA-1, MD5 digests; SecureRandom; X.509 certificates;
JKS keystore)";
public Sun() { /* We are the SUN provider */
super("SUN", 1.2, INFO);
AccessController.doPrivileged(new java.security.PrivilegedAction() {
public Object run() {
/* * Signature engines */
put("Signature.SHA1withDSA", "sun.security.provider.DSA");
put("Alg.Alias.Signature.DSA", "SHA1withDSA");
put("Alg.Alias.Signature.DSS", "SHA1withDSA");
put("Alg.Alias. Signature. SHA/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "SHA1withDSA");
put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
* Key Pair Generator engines */
put(“ KeyPairGenerator.DSA", "sun.security.provider.DSAKeyPairGenerator");
put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
/* * Digest engines */
put("MessageDigest.MD5", "sun.security.provider.MD5");
put( "MessageDigest.SHA", "sun.security.provider.SHA");
put("Alg.Alias.MessageDigest.SHA-1", "SHA");
put("Alg.Alias.MessageDigest.SHA1", "SHA");
/* * Algorithm Parameter Generator engines */
put ("AlgorithmParameterGenerator.DSA",
"sun.security.provider.DSAParameterGenerator");
/* * Algorithm Parameter engines */
put("AlgorithmParameters.DSA", "sun.security.provider.DSAParameters");
put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12", "DSA");
put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA");
/* * Key factories */
put(“ KeyFactory.DSA", "sun.security.provider.DSAKeyFactory");
put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA");
put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
/* * SecureRandom */
put("SecureRandom.SHA1PRNG", "sun.security.provider.SecureRandom");
/* * Certificates */
put("CertificateFactory.X509", "sun.security.provider.X509Factory");
put("Alg.Alias.CertificateFactory.X.509", "X509");
/* * KeyStore */
put ("KeyStore. JKS", "sun.security.provider.JavaKeyStore");
/* * KeySize */
put("Signature.SHA1withDSA KeySize", "1024");
put("KeyPairGenerator.DSA KeySize", "1024"); put("AlgorithmParameterGenerator.DSA
KeySize", "1024");
/* * Implementation type: software or hardware */
put("Signature.SHA1withDSA ImplementedIn", "Software");
put("KeyPairGenerator.DSA ImplementedIn", "Software");
put("MessageDigest.MD5 ImplementedIn", "Software");
put("MessageDigest.SHA ImplementedIn", "Software");
put("AlgorithmParameterGenerator.DSA ImplementedIn", "Software");
put("AlgorithmParameters.DSA ImplementedIn", "Software");
put("KeyFactory.DSA ImplementedIn", "Software");
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
put("CertificateFactory.X509 ImplementedIn", "Software");
put(“ KeyStore.JKS ImplementedIn", "Software");
return null; } } )
Example: Java Security Providers
 The following Java2 applet enumerates all the
Java Security Providers available to the j2re and
their associated properties and values.
 These property values specify the
engine.algorithms and the classes that implement
them, as well as other properties.
 The public method of the applet is accessed by a
scripted call to the method from JavaScript.
 The method returns the data in a formatted table
string.
 A JavaScript function embeds the table of results
into a simple html page in another scripted window.
import java.io.*;
import java.util.*;
import java.awt.* ;
import java.security.*;
public class SecProviders extends java.applet.Applet {
public void init() { } // end init()
public String getSecurityProviders() {
StringBuffer strbuff = new StringBuffer(10000) ;
//typical size of buffer to hold html string output
try {
Provider p[] = Security.getProviders();
strbuff.append("<table border=1 cellpadding =3>");
for (int i = 0; i < p.length; i++) {
strbuff.append("<tr><td bgcolor =blue colspan =2><font size=+1
color=yellow><b>" + p[i] + "&nbsp; &nbsp; &nbsp; &nbsp;" +
p[i]. getClass(). getName() + "</b></font></tr>\r\n") ;
for (Enumeration e = p[i].keys();
e.hasMoreElements();) {
String key = (String) e.nextElement() ;
strbuff.append("<tr><td>" + key + "</td><td>" +
p[i].getProperty(key) + "</td></tr>\r\n") ;
}
}
strbuff.append("</table>\r\n") ;
return strbuff.toString();
}
catch (Exception e) {
return e.toString();
}
}
}
The subclasses of the Provider
class
For each service implemented by the provider, there must be a property
whose name is the type of service:
 Signature.algName [one or more spaces] attrName
 MessageDigest.algName [one or more spaces] attrName
 KeyPairGenerator.algName [one/more spaces] attrName
 SecureRandom.algName [one /spaces] attrName
 KeyFactory.algName [one / spaces] attrName
 CertificateFactory.certType [one or more spaces] attrName
 KeyStore.storeType [one or more spaces] attrName
 AlgorithmParameterGenerator.algName [one / spaces]
attrName
 AlgorithmParameters.algName [one / more spaces]
attrName
Java Security Provider Examples
 The default provider "SUN" implements the SHA1withDSA
Digital Signature Algorithm in software.
 In the master class for the provider "SUN", it sets the
"Signature.SHA1withDSA ImplementedIn" to have the value
"Software" via the following:
put ("Signature.SHA1withDSA ImplementedIn", "Software")
 The default provider "SUN" implements the Digital Signature
Algorithm (whose standard name is "SHA1withDSA") in a
class named DSA in the sun.security.provider package.
• Its subclass of Provider sets the Signature.SHA1withDSA
property to have the value "sun.security.provider.DSA" via
the following:
put("Signature.SHA1withDSA", "sun.security.provider.DSA")
getProviders
method
 public static Provider[ ] getProviders()
Returns an array containing all the installed
providers. The order of the providers in the
array is their preference order.
Returns an array of all the installed providers.
getProvider
method
 public static Provider getProvider(String name)
Returns the provider installed with the specified
name, if any.
Returns null if no provider with the specified name
is installed.
 Parameters: name - the name of the provider to get.
 Returns: he provider of the specified name.
get Providers
method
 public static Provider [] getProviders (Map filter)
Returns an array containing all installed providers that
satisfy the specified selection criteria, or
 Returns null if no such providers have been installed.
The returned providers are ordered according to their
preference order

 Parameters: filter - the criteria for selecting providers. The filter is caseinsensitive.
 Returns: all the installed providers that satisfy the selection criteria, or null if
no such providers have been installed.
 Throws: InvalidParameterException - if the filter is not in the required format
 The selection criteria are represented by a map.
 Each map entry represents a selection criterion.
 A provider is selected iff it satisfies all selection criteria.
The key entry
 The key for any entry in such a map must be in one of the following two
formats:
<crypto_service>.<algorithm_or_type>
MessageDigest.SHA-384 , MessageDigest.MD5 ,
 The cryptographic service name must not contain any dots.
 The value associated with the key must be an empty string.
 A provider satisfies this selection criterion iff the provider implements the
specified algorithm or type for the specified cryptographic service.
<crypto_service>.<algorithm_or_type> <attribute_name>
Provider.id className , Provider.id version , KeyStore.JKS ImplementedIn ,
MessageDigest.SHA ImplementedIn , KeyFactory.DSA ImplementedIn
 The cryptographic service name must not contain any dots.
 The value associated with the key must be a non-empty string.
 A provider satisfies this selection criterion iff the provider implements the
specified algorithm or type for the specified cryptographic service and its
implementation meets the constraint expressed by the specified attribute
name/value pair.