1 7 8 package java.security; 9 10 import java.security.spec.AlgorithmParameterSpec ; 11 import java.util.*; 12 import java.util.concurrent.ConcurrentHashMap ; 13 import java.io.*; 14 import java.security.cert.Certificate ; 15 import java.security.cert.X509Certificate ; 16 17 import java.nio.ByteBuffer ; 18 19 import java.security.Provider.Service; 20 21 import javax.crypto.Cipher; 22 import javax.crypto.CipherSpi; 23 import javax.crypto.IllegalBlockSizeException; 24 import javax.crypto.BadPaddingException; 25 import javax.crypto.NoSuchPaddingException; 26 27 import sun.security.util.Debug; 28 import sun.security.jca.*; 29 import sun.security.jca.GetInstance.Instance; 30 31 110 111 public abstract class Signature extends SignatureSpi { 112 113 private static final Debug debug = 114 Debug.getInstance("jca", "Signature"); 115 116 121 private String algorithm; 122 123 Provider provider; 125 126 130 protected final static int UNINITIALIZED = 0; 131 132 136 protected final static int SIGN = 2; 137 138 142 protected final static int VERIFY = 3; 143 144 147 protected int state = UNINITIALIZED; 148 149 158 protected Signature(String algorithm) { 159 this.algorithm = algorithm; 160 } 161 162 private final static String RSA_SIGNATURE = "NONEwithRSA"; 164 165 private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding"; 167 168 private final static List<ServiceId> rsaIds = Arrays.asList( 170 new ServiceId[] { 171 new ServiceId("Signature", "NONEwithRSA"), 172 new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"), 173 new ServiceId("Cipher", "RSA/ECB"), 174 new ServiceId("Cipher", "RSA//PKCS1Padding"), 175 new ServiceId("Cipher", "RSA"), 176 } 177 ); 178 179 198 public static Signature getInstance(String algorithm) 199 throws NoSuchAlgorithmException { 200 List list; 201 if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { 202 list = GetInstance.getServices(rsaIds); 203 } else { 204 list = GetInstance.getServices("Signature", algorithm); 205 } 206 Iterator t = list.iterator(); 207 if (t.hasNext() == false) { 208 throw new NoSuchAlgorithmException 209 (algorithm + " Signature not available"); 210 } 211 NoSuchAlgorithmException failure; 213 do { 214 Service s = (Service)t.next(); 215 if (isSpi(s)) { 216 return new Delegate(s, t, algorithm); 217 } else { 218 try { 220 Instance instance = 221 GetInstance.getInstance(s, SignatureSpi .class); 222 return getInstance(instance, algorithm); 223 } catch (NoSuchAlgorithmException e) { 224 failure = e; 225 } 226 } 227 } while (t.hasNext()); 228 throw failure; 229 } 230 231 private static Signature getInstance(Instance instance, String algorithm) { 232 Signature sig; 233 if (instance.impl instanceof Signature ) { 234 sig = (Signature )instance.impl; 235 } else { 236 SignatureSpi spi = (SignatureSpi )instance.impl; 237 sig = new Delegate(spi, algorithm); 238 } 239 sig.provider = instance.provider; 240 return sig; 241 } 242 243 private final static Map <String ,Boolean > signatureInfo; 244 245 static { 246 signatureInfo = new ConcurrentHashMap <String ,Boolean >(); 247 Boolean TRUE = Boolean.TRUE; 248 signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE); 250 signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE); 251 signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE); 252 signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE); 253 signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE); 254 signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE); 255 signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE); 256 signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE); 257 signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE); 258 signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE); 259 } 260 261 private static boolean isSpi(Service s) { 262 if (s.getType().equals("Cipher")) { 263 return true; 265 } 266 String className = s.getClassName(); 267 Boolean result = signatureInfo.get(className); 268 if (result == null) { 269 try { 270 Object instance = s.newInstance(null); 271 boolean r = (instance instanceof SignatureSpi ) 275 && (instance instanceof Signature == false); 276 if ((debug != null) && (r == false)) { 277 debug.println("Not a SignatureSpi " + className); 278 debug.println("Delayed provider selection may not be " 279 + "available for algorithm " + s.getAlgorithm()); 280 } 281 result = Boolean.valueOf(r); 282 signatureInfo.put(className, result); 283 } catch (Exception e) { 284 return false; 286 } 287 } 288 return result.booleanValue(); 289 } 290 291 318 public static Signature getInstance(String algorithm, String provider) 319 throws NoSuchAlgorithmException , NoSuchProviderException { 320 if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { 321 if ((provider == null) || (provider.length() == 0)) { 323 throw new IllegalArgumentException ("missing provider"); 324 } 325 Provider p = Security.getProvider(provider); 326 if (p == null) { 327 throw new NoSuchProviderException 328 ("no such provider: " + provider); 329 } 330 return getInstanceRSA(p); 331 } 332 Instance instance = GetInstance.getInstance 333 ("Signature", SignatureSpi .class, algorithm, provider); 334 return getInstance(instance, algorithm); 335 } 336 337 364 public static Signature getInstance(String algorithm, Provider provider) 365 throws NoSuchAlgorithmException { 366 if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { 367 if (provider == null) { 369 throw new IllegalArgumentException ("missing provider"); 370 } 371 return getInstanceRSA(provider); 372 } 373 Instance instance = GetInstance.getInstance 374 ("Signature", SignatureSpi .class, algorithm, provider); 375 return getInstance(instance, algorithm); 376 } 377 378 private static Signature getInstanceRSA(Provider p) 381 throws NoSuchAlgorithmException { 382 Service s = p.getService("Signature", RSA_SIGNATURE); 384 if (s != null) { 385 Instance instance = GetInstance.getInstance(s, SignatureSpi .class); 386 return getInstance(instance, RSA_SIGNATURE); 387 } 388 try { 390 Cipher c = Cipher.getInstance(RSA_CIPHER, p); 391 return new Delegate(new CipherAdapter(c), RSA_SIGNATURE); 392 } catch (GeneralSecurityException e) { 393 throw new NoSuchAlgorithmException ("no such algorithm: " 396 + RSA_SIGNATURE + " for provider " + p.getName(), e); 397 } 398 } 399 400 405 public final Provider getProvider() { 406 chooseFirstProvider(); 407 return this.provider; 408 } 409 410 void chooseFirstProvider() { 411 } 413 414 424 public final void initVerify(PublicKey publicKey) 425 throws InvalidKeyException { 426 engineInitVerify(publicKey); 427 state = VERIFY; 428 } 429 430 447 public final void initVerify(Certificate certificate) 448 throws InvalidKeyException { 449 if (certificate instanceof java.security.cert.X509Certificate ) { 453 X509Certificate cert = (X509Certificate )certificate; 457 Set critSet = cert.getCriticalExtensionOIDs(); 458 459 if (critSet != null && !critSet.isEmpty() 460 && critSet.contains("2.5.29.15")) { 461 boolean[] keyUsageInfo = cert.getKeyUsage(); 462 if ((keyUsageInfo != null) && (keyUsageInfo[0] == false)) 464 throw new InvalidKeyException ("Wrong key usage"); 465 } 466 } 467 468 PublicKey publicKey = certificate.getPublicKey(); 469 engineInitVerify(publicKey); 470 state = VERIFY; 471 } 472 473 483 public final void initSign(PrivateKey privateKey) 484 throws InvalidKeyException { 485 engineInitSign(privateKey); 486 state = SIGN; 487 } 488 489 501 public final void initSign(PrivateKey privateKey, SecureRandom random) 502 throws InvalidKeyException { 503 engineInitSign(privateKey, random); 504 state = SIGN; 505 } 506 507 525 public final byte[] sign() throws SignatureException { 526 if (state == SIGN) { 527 return engineSign(); 528 } 529 throw new SignatureException ("object not initialized for " + 530 "signing"); 531 } 532 533 561 public final int sign(byte[] outbuf, int offset, int len) 562 throws SignatureException { 563 if (outbuf == null) { 564 throw new IllegalArgumentException ("No output buffer given"); 565 } 566 if (outbuf.length - offset < len) { 567 throw new IllegalArgumentException 568 ("Output buffer too small for specified offset and length"); 569 } 570 if (state != SIGN) { 571 throw new SignatureException ("object not initialized for " + 572 "signing"); 573 } 574 return engineSign(outbuf, offset, len); 575 } 576 577 595 public final boolean verify(byte[] signature) throws SignatureException { 596 if (state == VERIFY) { 597 return engineVerify(signature); 598 } 599 throw new SignatureException ("object not initialized for " + 600 "verification"); 601 } 602 603 630 public final boolean verify(byte[] signature, int offset, int length) 631 throws SignatureException { 632 if (state == VERIFY) { 633 if ((signature == null) || (offset < 0) || (length < 0) || 634 (offset + length > signature.length)) { 635 throw new IllegalArgumentException ("Bad arguments"); 636 } 637 638 return engineVerify(signature, offset, length); 639 } 640 throw new SignatureException ("object not initialized for " + 641 "verification"); 642 } 643 644 652 public final void update(byte b) throws SignatureException { 653 if (state == VERIFY || state == SIGN) { 654 engineUpdate(b); 655 } else { 656 throw new SignatureException ("object not initialized for " 657 + "signature or verification"); 658 } 659 } 660 661 670 public final void update(byte[] data) throws SignatureException { 671 update(data, 0, data.length); 672 } 673 674 685 public final void update(byte[] data, int off, int len) 686 throws SignatureException { 687 if (state == SIGN || state == VERIFY) { 688 engineUpdate(data, off, len); 689 } else { 690 throw new SignatureException ("object not initialized for " 691 + "signature or verification"); 692 } 693 } 694 695 708 public final void update(ByteBuffer data) throws SignatureException { 709 if ((state != SIGN) && (state != VERIFY)) { 710 throw new SignatureException ("object not initialized for " 711 + "signature or verification"); 712 } 713 if (data == null) { 714 throw new NullPointerException (); 715 } 716 engineUpdate(data); 717 } 718 719 724 public final String getAlgorithm() { 725 return this.algorithm; 726 } 727 728 735 public String toString() { 736 String initState = ""; 737 switch (state) { 738 case UNINITIALIZED: 739 initState = "<not initialized>"; 740 break; 741 case VERIFY: 742 initState = "<initialized for verifying>"; 743 break; 744 case SIGN: 745 initState = "<initialized for signing>"; 746 break; 747 } 748 return "Signature object: " + getAlgorithm() + initState; 749 } 750 751 776 @Deprecated 777 public final void setParameter(String param, Object value) 778 throws InvalidParameterException { 779 engineSetParameter(param, value); 780 } 781 782 792 public final void setParameter(AlgorithmParameterSpec params) 793 throws InvalidAlgorithmParameterException { 794 engineSetParameter(params); 795 } 796 797 811 public final AlgorithmParameters getParameters() { 812 return engineGetParameters(); 813 } 814 815 838 @Deprecated 839 public final Object getParameter(String param) 840 throws InvalidParameterException { 841 return engineGetParameter(param); 842 } 843 844 852 public Object clone() throws CloneNotSupportedException { 853 if (this instanceof Cloneable ) { 854 return super.clone(); 855 } else { 856 throw new CloneNotSupportedException (); 857 } 858 } 859 860 873 874 private static class Delegate extends Signature { 875 876 private SignatureSpi sigSpi; 879 880 private final Object lock; 882 883 private Service firstService; 886 887 private Iterator serviceIterator; 890 891 Delegate(SignatureSpi sigSpi, String algorithm) { 893 super(algorithm); 894 this.sigSpi = sigSpi; 895 this.lock = null; } 897 898 Delegate(Service service, Iterator iterator, String algorithm) { 900 super(algorithm); 901 this.firstService = service; 902 this.serviceIterator = iterator; 903 this.lock = new Object (); 904 } 905 906 914 public Object clone() throws CloneNotSupportedException { 915 chooseFirstProvider(); 916 if (sigSpi instanceof Cloneable ) { 917 SignatureSpi sigSpiClone = (SignatureSpi )sigSpi.clone(); 918 Signature that = 922 new Delegate(sigSpiClone, ((Signature )this).algorithm); 923 that.provider = ((Signature )this).provider; 924 return that; 925 } else { 926 throw new CloneNotSupportedException (); 927 } 928 } 929 930 private static SignatureSpi newInstance(Service s) 931 throws NoSuchAlgorithmException { 932 if (s.getType().equals("Cipher")) { 933 try { 935 Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider()); 936 return new CipherAdapter(c); 937 } catch (NoSuchPaddingException e) { 938 throw new NoSuchAlgorithmException (e); 939 } 940 } else { 941 Object o = s.newInstance(null); 942 if (o instanceof SignatureSpi == false) { 943 throw new NoSuchAlgorithmException 944 ("Not a SignatureSpi: " + o.getClass().getName()); 945 } 946 return (SignatureSpi )o; 947 } 948 } 949 950 private static int warnCount = 10; 952 953 958 void chooseFirstProvider() { 959 if (sigSpi != null) { 960 return; 961 } 962 synchronized (lock) { 963 if (sigSpi != null) { 964 return; 965 } 966 if (debug != null) { 967 int w = --warnCount; 968 if (w >= 0) { 969 debug.println("Signature.init() not first method " 970 + "called, disabling delayed provider selection"); 971 if (w == 0) { 972 debug.println("Further warnings of this type will " 973 + "be suppressed"); 974 } 975 new Exception ("Call trace").printStackTrace(); 976 } 977 } 978 Exception lastException = null; 979 while ((firstService != null) || serviceIterator.hasNext()) { 980 Service s; 981 if (firstService != null) { 982 s = firstService; 983 firstService = null; 984 } else { 985 s = (Service)serviceIterator.next(); 986 } 987 if (isSpi(s) == false) { 988 continue; 989 } 990 try { 991 sigSpi = newInstance(s); 992 provider = s.getProvider(); 993 firstService = null; 995 serviceIterator = null; 996 return; 997 } catch (NoSuchAlgorithmException e) { 998 lastException = e; 999 } 1000 } 1001 ProviderException e = new ProviderException 1002 ("Could not construct SignatureSpi instance"); 1003 if (lastException != null) { 1004 e.initCause(lastException); 1005 } 1006 throw e; 1007 } 1008 } 1009 1010 private void chooseProvider(int type, Key key, SecureRandom random) 1011 throws InvalidKeyException { 1012 synchronized (lock) { 1013 if (sigSpi != null) { 1014 init(sigSpi, type, key, random); 1015 return; 1016 } 1017 Exception lastException = null; 1018 while ((firstService != null) || serviceIterator.hasNext()) { 1019 Service s; 1020 if (firstService != null) { 1021 s = firstService; 1022 firstService = null; 1023 } else { 1024 s = (Service)serviceIterator.next(); 1025 } 1026 if (s.supportsParameter(key) == false) { 1028 continue; 1029 } 1030 if (isSpi(s) == false) { 1032 continue; 1033 } 1034 try { 1035 SignatureSpi spi = newInstance(s); 1036 init(spi, type, key, random); 1037 provider = s.getProvider(); 1038 sigSpi = spi; 1039 firstService = null; 1040 serviceIterator = null; 1041 return; 1042 } catch (Exception e) { 1043 if (lastException == null) { 1047 lastException = e; 1048 } 1049 } 1050 } 1051 if (lastException instanceof InvalidKeyException ) { 1053 throw (InvalidKeyException )lastException; 1054 } 1055 if (lastException instanceof RuntimeException ) { 1056 throw (RuntimeException )lastException; 1057 } 1058 String k = (key != null) ? key.getClass().getName() : "(null)"; 1059 throw new InvalidKeyException 1060 ("No installed provider supports this key: " 1061 + k, lastException); 1062 } 1063 } 1064 1065 private final static int I_PUB = 1; 1066 private final static int I_PRIV = 2; 1067 private final static int I_PRIV_SR = 3; 1068 1069 private void init(SignatureSpi spi, int type, Key key, 1070 SecureRandom random) throws InvalidKeyException { 1071 switch (type) { 1072 case I_PUB: 1073 spi.engineInitVerify((PublicKey )key); 1074 break; 1075 case I_PRIV: 1076 spi.engineInitSign((PrivateKey )key); 1077 break; 1078 case I_PRIV_SR: 1079 spi.engineInitSign((PrivateKey )key, random); 1080 break; 1081 default: 1082 throw new AssertionError ("Internal error: " + type); 1083 } 1084 } 1085 1086 protected void engineInitVerify(PublicKey publicKey) 1087 throws InvalidKeyException { 1088 if (sigSpi != null) { 1089 sigSpi.engineInitVerify(publicKey); 1090 } else { 1091 chooseProvider(I_PUB, publicKey, null); 1092 } 1093 } 1094 1095 protected void engineInitSign(PrivateKey privateKey) 1096 throws InvalidKeyException { 1097 if (sigSpi != null) { 1098 sigSpi.engineInitSign(privateKey); 1099 } else { 1100 chooseProvider(I_PRIV, privateKey, null); 1101 } 1102 } 1103 1104 protected void engineInitSign(PrivateKey privateKey, SecureRandom sr) 1105 throws InvalidKeyException { 1106 if (sigSpi != null) { 1107 sigSpi.engineInitSign(privateKey, sr); 1108 } else { 1109 chooseProvider(I_PRIV_SR, privateKey, sr); 1110 } 1111 } 1112 1113 protected void engineUpdate(byte b) throws SignatureException { 1114 chooseFirstProvider(); 1115 sigSpi.engineUpdate(b); 1116 } 1117 1118 protected void engineUpdate(byte[] b, int off, int len) 1119 throws SignatureException { 1120 chooseFirstProvider(); 1121 sigSpi.engineUpdate(b, off, len); 1122 } 1123 1124 protected void engineUpdate(ByteBuffer data) { 1125 chooseFirstProvider(); 1126 sigSpi.engineUpdate(data); 1127 } 1128 1129 protected byte[] engineSign() throws SignatureException { 1130 chooseFirstProvider(); 1131 return sigSpi.engineSign(); 1132 } 1133 1134 protected int engineSign(byte[] outbuf, int offset, int len) 1135 throws SignatureException { 1136 chooseFirstProvider(); 1137 return sigSpi.engineSign(outbuf, offset, len); 1138 } 1139 1140 protected boolean engineVerify(byte[] sigBytes) 1141 throws SignatureException { 1142 chooseFirstProvider(); 1143 return sigSpi.engineVerify(sigBytes); 1144 } 1145 1146 protected boolean engineVerify(byte[] sigBytes, int offset, int length) 1147 throws SignatureException { 1148 chooseFirstProvider(); 1149 return sigSpi.engineVerify(sigBytes, offset, length); 1150 } 1151 1152 protected void engineSetParameter(String param, Object value) 1153 throws InvalidParameterException { 1154 chooseFirstProvider(); 1155 sigSpi.engineSetParameter(param, value); 1156 } 1157 1158 protected void engineSetParameter(AlgorithmParameterSpec params) 1159 throws InvalidAlgorithmParameterException { 1160 chooseFirstProvider(); 1161 sigSpi.engineSetParameter(params); 1162 } 1163 1164 protected Object engineGetParameter(String param) 1165 throws InvalidParameterException { 1166 chooseFirstProvider(); 1167 return sigSpi.engineGetParameter(param); 1168 } 1169 1170 protected AlgorithmParameters engineGetParameters() { 1171 chooseFirstProvider(); 1172 return sigSpi.engineGetParameters(); 1173 } 1174 } 1175 1176 private static class CipherAdapter extends SignatureSpi { 1178 1179 private final Cipher cipher; 1180 1181 private ByteArrayOutputStream data; 1182 1183 CipherAdapter(Cipher cipher) { 1184 this.cipher = cipher; 1185 } 1186 1187 protected void engineInitVerify(PublicKey publicKey) 1188 throws InvalidKeyException { 1189 cipher.init(Cipher.DECRYPT_MODE, publicKey); 1190 if (data == null) { 1191 data = new ByteArrayOutputStream(128); 1192 } else { 1193 data.reset(); 1194 } 1195 } 1196 1197 protected void engineInitSign(PrivateKey privateKey) 1198 throws InvalidKeyException { 1199 cipher.init(Cipher.ENCRYPT_MODE, privateKey); 1200 data = null; 1201 } 1202 1203 protected void engineInitSign(PrivateKey privateKey, 1204 SecureRandom random) throws InvalidKeyException { 1205 cipher.init(Cipher.ENCRYPT_MODE, privateKey, random); 1206 data = null; 1207 } 1208 1209 protected void engineUpdate(byte b) throws SignatureException { 1210 engineUpdate(new byte[] {b}, 0, 1); 1211 } 1212 1213 protected void engineUpdate(byte[] b, int off, int len) 1214 throws SignatureException { 1215 if (data != null) { 1216 data.write(b, off, len); 1217 return; 1218 } 1219 byte[] out = cipher.update(b, off, len); 1220 if ((out != null) && (out.length != 0)) { 1221 throw new SignatureException 1222 ("Cipher unexpectedly returned data"); 1223 } 1224 } 1225 1226 protected byte[] engineSign() throws SignatureException { 1227 try { 1228 return cipher.doFinal(); 1229 } catch (IllegalBlockSizeException e) { 1230 throw new SignatureException ("doFinal() failed", e); 1231 } catch (BadPaddingException e) { 1232 throw new SignatureException ("doFinal() failed", e); 1233 } 1234 } 1235 1236 protected boolean engineVerify(byte[] sigBytes) 1237 throws SignatureException { 1238 try { 1239 byte[] out = cipher.doFinal(sigBytes); 1240 byte[] dataBytes = data.toByteArray(); 1241 data.reset(); 1242 return Arrays.equals(out, dataBytes); 1243 } catch (BadPaddingException e) { 1244 return false; 1247 } catch (IllegalBlockSizeException e) { 1248 throw new SignatureException ("doFinal() failed", e); 1249 } 1250 } 1251 1252 protected void engineSetParameter(String param, Object value) 1253 throws InvalidParameterException { 1254 throw new InvalidParameterException ("Parameters not supported"); 1255 } 1256 1257 protected Object engineGetParameter(String param) 1258 throws InvalidParameterException { 1259 throw new InvalidParameterException ("Parameters not supported"); 1260 } 1261 1262 } 1263 1264} 1265 1266 | Popular Tags |