1 21 22 package net.sourceforge.jcetaglib.lib; 23 24 import net.sourceforge.jcetaglib.exceptions.CryptoException; 25 import net.sourceforge.jcetaglib.exceptions.HeaderException; 26 import net.sourceforge.jcetaglib.exceptions.InvalidHMACException; 27 import net.sourceforge.jcetaglib.exceptions.InvalidSignatureException; 28 import net.sourceforge.jcetaglib.tools.*; 29 import org.bouncycastle.jce.provider.BouncyCastleProvider; 30 import org.bouncycastle.util.encoders.Base64; 31 32 import javax.crypto.Cipher; 33 import javax.crypto.KeyGenerator; 34 import javax.crypto.Mac; 35 import javax.crypto.SecretKey; 36 import javax.crypto.spec.IvParameterSpec; 37 import javax.crypto.spec.SecretKeySpec; 38 import java.io.*; 39 import java.security.*; 40 import java.security.cert.CertificateFactory ; 41 import java.security.cert.X509Certificate ; 42 43 51 public class Hybrid { 52 private static int BUFFERSIZE_TEXT = 1204; 54 private static int BUFFERSIZE_FILE = 8192; 55 56 static final int FILE_HEADER = 0x7e01; static final int DATA_BLOCK = 1; static final int FINAL_DATA_BLOCK = 2; static final int HMAC_BLOCK = 3; static final int SIG_BLOCK = 3; static final int CERT_BLOCK = 4; static final int KEY_BLOCK = 16; static final int IV_BLOCK = 17; static final int LOCK_BLOCK = 18; static final int HMAC_KEY_BLOCK = 18; 66 67 80 public static StringBuffer encryptWithHMAC(StringBuffer text 81 , PublicKey receiverKey 82 , String algorithm 83 , byte[] seed 84 , int strength 85 , String mode 86 , String padding) throws CryptoException { 87 88 ByteArrayOutputStream bao = null; 89 DataOutputStream dao = null; 90 91 try { 92 bao = new ByteArrayOutputStream(); 93 dao = new DataOutputStream(bao); 94 95 encryptWithHMAC(new ByteArrayInputStream(text.toString().getBytes()), dao, receiverKey, algorithm, seed, strength, mode, padding, BUFFERSIZE_TEXT); 97 return new StringBuffer (new String (Base64.encode(bao.toByteArray()))); 98 } catch (IOException ioe) { 99 ioe.printStackTrace(); 100 throw new CryptoException(ioe.getMessage()); 101 } finally { 102 if (dao != null) { 103 try { 105 dao.close(); 106 } catch (IOException e) { 107 ; 108 } 109 } 110 } 111 } 112 113 127 public static void encryptFileWithHMAC(String file 128 , String newfile 129 , PublicKey receiverKey 130 , String algorithm 131 , byte[] seed 132 , int strength 133 , String mode 134 , String padding) throws CryptoException, IOException { 135 136 FileInputStream fis = null; 137 FileOutputStream fos = null; 138 DataOutputStream dao = null; 139 140 try { 141 fis = new FileInputStream(file); 142 143 fos = new FileOutputStream(newfile); 144 dao = new DataOutputStream(fos); 145 146 encryptWithHMAC(fis, dao, receiverKey, algorithm, seed, strength, mode, padding, BUFFERSIZE_FILE); 148 149 } catch (IOException ioe) { 150 ioe.printStackTrace(); 151 throw new IOException(ioe.getMessage()); 152 } finally { 153 if (dao != null) { 154 try { 156 dao.close(); 157 } catch (IOException e) { 158 ; 159 } 160 } 161 if (fis != null) { 162 try { 164 fis.close(); 165 } catch (IOException e) { 166 ; 167 } 168 } 169 } 170 } 171 172 187 public static void encryptWithHMAC(InputStream is 188 , DataOutputStream daos 189 , PublicKey receiverKey 190 , String algorithm 191 , byte[] seed 192 , int strength 193 , String mode 194 , String padding 195 , int bufferlength) 196 throws CryptoException, IOException { 197 198 MacOutputStream macStr = null; 199 DataOutputStream dataStr = null; 200 201 try { 202 Security.addProvider(new BouncyCastleProvider()); 203 204 SecureRandom secRand = Seed.getSecureRandom(seed); 205 206 KeyGenerator keyGen = KeyGenerator.getInstance(algorithm, "BC"); 208 keyGen.init(strength, secRand); 209 Key symKey = keyGen.generateKey(); 210 211 Cipher outputCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 213 outputCipher.init(Cipher.ENCRYPT_MODE, symKey, secRand); 214 215 byte[] keyEnc = symKey.getEncoded(); 218 byte[] keyIV = outputCipher.getIV(); 219 220 Mac mac = Mac.getInstance("HMACSHA1", "BC"); 222 223 byte[] macKeyBytes = new byte[20]; secRand.nextBytes(macKeyBytes); 226 Key macKey = new SecretKeySpec(macKeyBytes, "HMACSHA1"); 227 mac.init(macKey); 229 Cipher rsaEng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); 231 rsaEng.init(Cipher.ENCRYPT_MODE, receiverKey, secRand); 232 233 macStr = new MacOutputStream(daos, mac); 235 dataStr = new DataOutputStream(macStr); 236 237 dataStr.writeShort(FILE_HEADER); 240 dataStr.writeShort(KEY_BLOCK); byte[] tmp = rsaEng.doFinal(keyEnc); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); 247 dataStr.writeShort(IV_BLOCK); tmp = rsaEng.doFinal(keyIV); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); 254 dataStr.writeShort(HMAC_KEY_BLOCK); tmp = outputCipher.doFinal(macKey.getEncoded()); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); 261 264 int l = 0; byte[] buf = new byte[bufferlength]; byte[] out = null; 269 while ((l = is.read(buf)) > -1) { 271 out = outputCipher.update(buf, 0, l); if (out != null) { 273 dataStr.writeShort(DATA_BLOCK); dataStr.writeInt(out.length); dataStr.write(out); } 277 } 278 279 out = outputCipher.doFinal(); dataStr.writeShort(FINAL_DATA_BLOCK); dataStr.writeInt(out.length); dataStr.write(out); 285 Clean.blank(buf); buf = null; 288 dataStr.writeShort(HMAC_BLOCK); dataStr.flush(); 292 tmp = mac.doFinal(); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); } catch (IOException ioe) { 297 ioe.printStackTrace(); 298 throw new IOException(ioe.getMessage()); 299 } catch (Exception ex) { 300 ex.printStackTrace(); 301 throw new CryptoException(ex.getMessage()); 302 } finally { 303 if (dataStr != null) { 304 try { 305 dataStr.close(); 306 } catch (IOException ioe) { 307 ; 308 } 309 } 310 } 311 } 312 313 326 public static StringBuffer decryptAndVerifyHMAC(StringBuffer text 327 , PrivateKey privKey 328 , String algorithm 329 , String mode 330 , String padding) throws HeaderException, InvalidHMACException, CryptoException { 331 332 ByteArrayOutputStream bao = null; 333 DataOutputStream dao = null; 334 335 try { 336 bao = new ByteArrayOutputStream(); 337 dao = new DataOutputStream(bao); 338 339 decryptAndVerifyHMAC(new ByteArrayInputStream(Base64.decode(text.toString())), dao, privKey, algorithm, mode, padding, BUFFERSIZE_TEXT); 341 342 return new StringBuffer (new String (bao.toByteArray())); 343 } catch (HeaderException he) { 344 throw new HeaderException(he.getMessage()); 345 } catch (InvalidHMACException ihe) { 346 throw new InvalidHMACException(ihe.getMessage()); 347 } catch (Exception ioe) { 348 ioe.printStackTrace(); 349 throw new CryptoException(ioe.getMessage()); 350 } finally { 351 if (dao != null) { 352 try { 354 dao.close(); 355 } catch (IOException e) { 356 ; 357 } 358 } 359 } 360 } 361 362 376 public static void decryptFileAndVerifyHMAC(String file 377 , String newfile 378 , PrivateKey privKey 379 , String algorithm 380 , String mode 381 , String padding) throws CryptoException, HeaderException, InvalidHMACException, IOException { 382 383 SecureRandom secRand; 384 Mac mac = null; 385 Cipher cipher = null; 386 Cipher decHMAC = null; 387 388 SecretKey symKey = null; SecretKey macKey = null; 391 byte[] keyIV = null; byte[] macCode = null; 394 DataInputStream dataIn = null; 395 MacInputStream macStr = null; 396 DataInputStream dataStr = null; 397 398 FileOutputStream outStr = null; 399 400 try { 401 Security.addProvider(new BouncyCastleProvider()); 402 403 secRand = SecureRandom.getInstance("SHA1PRNG", "SUN"); 404 405 dataIn = new DataInputStream(new FileInputStream(file)); 406 407 int l = 0; boolean ena = false; boolean stop = false; 411 Cipher rsaEng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); 413 rsaEng.init(Cipher.DECRYPT_MODE, privKey, secRand); 415 while (!stop) { 416 try { 417 int cmd = dataIn.readShort(); 419 if (cmd == FILE_HEADER) { 421 ena = true; continue; 423 } 424 425 if (cmd == DATA_BLOCK) { 427 if (!ena) { 428 throw new HeaderException("Broken header"); 429 } 430 431 l = dataIn.readInt(); dataIn.skip(l); continue; 434 } 435 436 if (cmd == FINAL_DATA_BLOCK) { 438 if (!ena) { 439 throw new HeaderException("Broken header"); 440 } 441 l = dataIn.readInt(); dataIn.skip(l); continue; 444 } 445 446 if (cmd == HMAC_BLOCK) { 448 if (!ena) { 449 throw new HeaderException("Broken header"); 450 } 451 l = dataIn.readInt(); macCode = new byte[l]; dataIn.readFully(macCode); continue; 455 } 456 457 if (cmd == KEY_BLOCK) { 459 if (!ena) { 460 throw new HeaderException("Broken header"); 461 } 462 463 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); 467 471 symKey = new SecretKeySpec(rsaEng.doFinal(d), algorithm); 472 continue; 473 } 474 475 if (cmd == IV_BLOCK) { 477 if (!ena) { 478 throw new HeaderException("Broken header"); 479 } 480 l = dataIn.readInt(); keyIV = new byte[l]; dataIn.readFully(keyIV); keyIV = rsaEng.doFinal(keyIV); continue; 485 } 486 487 if (cmd == HMAC_KEY_BLOCK) { 489 if (!ena) { 490 throw new HeaderException("Broken header"); 491 } 492 493 decHMAC = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 495 decHMAC.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 496 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); macKey = new SecretKeySpec(decHMAC.doFinal(d), "HMACSHA1"); 501 continue; 502 } 503 } catch (EOFException eof) { 504 stop = true; 505 } 506 } 507 508 mac = Mac.getInstance("HMACSHA1", "BC"); mac.init(macKey); 511 macStr = new MacInputStream(new FileInputStream(file), mac); 513 dataStr = new DataInputStream(macStr); 514 515 int cmd = 0; byte[] buf = new byte[BUFFERSIZE_FILE]; l = 0; 519 do { 520 cmd = dataStr.readShort(); 522 if (cmd == DATA_BLOCK) { 524 l = dataStr.readInt(); dataStr.read(buf, 0, l); } 527 528 if (cmd == FINAL_DATA_BLOCK) { 530 l = dataStr.readInt(); 531 dataStr.read(buf, 0, l); } 533 534 535 if (cmd == KEY_BLOCK) { 537 l = dataStr.readInt(); 538 dataStr.read(buf, 0, l); } 540 541 if (cmd == IV_BLOCK) { 543 l = dataStr.readInt(); 544 dataStr.read(buf, 0, l); } 546 547 if (cmd == HMAC_KEY_BLOCK) { 549 l = dataStr.readInt(); 550 dataStr.read(buf, 0, l); } 552 } while (cmd != HMAC_BLOCK); 553 554 buf = mac.doFinal(); 555 dataStr.close(); 556 557 if (!MessageDigest.isEqual(buf, macCode)) { 558 throw new InvalidHMACException("Invalid HMAC"); 559 } 560 561 cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 562 cipher.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 563 564 outStr = new FileOutputStream(newfile); 566 dataStr = new DataInputStream(new FileInputStream(file)); 568 569 stop = false; cmd = 0; l = 0; buf = new byte[BUFFERSIZE_FILE]; byte[] out = null; 575 for (; ;) { 576 cmd = dataStr.readShort(); 578 if (cmd == DATA_BLOCK) { 579 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.update(buf, 0, l); 582 if (out != null) outStr.write(out); 583 } 584 585 if (cmd == FINAL_DATA_BLOCK) { 586 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.doFinal(buf, 0, l); 589 if (out != null) outStr.write(out); 590 break; 591 } 592 593 if (cmd == KEY_BLOCK) { 596 l = dataStr.readInt(); 597 dataStr.skip(l); 598 } 599 600 if (cmd == IV_BLOCK) { 602 l = dataStr.readInt(); 603 dataStr.skip(l); 604 } 605 606 if (cmd == HMAC_BLOCK) { 608 l = dataStr.readInt(); 609 dataStr.skip(l); 610 } 611 612 if (cmd == HMAC_KEY_BLOCK) { 614 l = dataStr.readInt(); 615 dataStr.skip(l); 616 } 617 } 618 } catch (IOException ioe) { 619 ioe.printStackTrace(); 620 throw new IOException(ioe.getMessage()); 621 } catch (HeaderException he) { 622 he.printStackTrace(); 623 throw new HeaderException(he.getMessage()); 624 } catch (InvalidHMACException ihe) { 625 ihe.printStackTrace(); 626 throw new InvalidHMACException(ihe.getMessage()); 627 } catch (Exception ex) { 628 ex.printStackTrace(); 629 throw new CryptoException(ex.getMessage()); 630 } finally { 631 if (outStr != null) { 632 try { 634 outStr.close(); 635 } catch (IOException e) { 636 ; 637 } 638 } 639 if (dataStr != null) { 640 try { 642 dataStr.close(); 643 } catch (IOException e) { 644 ; 645 } 646 } 647 } 648 } 649 650 665 public static void decryptAndVerifyHMAC(InputStream is 666 , DataOutputStream daos 667 , PrivateKey privKey 668 , String algorithm 669 , String mode 670 , String padding 671 , int bufferlength) 672 throws IOException, HeaderException, InvalidHMACException, CryptoException { 673 674 SecureRandom secRand; 675 Mac mac = null; 676 Cipher cipher = null; 677 Cipher decHMAC = null; 678 679 SecretKey symKey = null; SecretKey macKey = null; 682 byte[] keyIV = null; byte[] macCode = null; 685 DataInputStream dataIn = null; 686 MacInputStream macStr = null; 687 DataInputStream dataStr = null; 688 689 try { 690 Security.addProvider(new BouncyCastleProvider()); 691 692 secRand = SecureRandom.getInstance("SHA1PRNG", "SUN"); 693 694 dataIn = new DataInputStream(is); 695 696 int l = 0; boolean ena = false; boolean stop = false; 700 Cipher rsaEng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); 702 rsaEng.init(Cipher.DECRYPT_MODE, privKey, secRand); 704 while (!stop) { 705 try { 706 int cmd = dataIn.readShort(); 708 if (cmd == FILE_HEADER) { 710 ena = true; continue; 712 } 713 714 if (cmd == DATA_BLOCK) { 716 if (!ena) { 717 throw new HeaderException("Broken header"); 718 } 719 720 l = dataIn.readInt(); dataIn.skip(l); continue; 723 } 724 725 if (cmd == FINAL_DATA_BLOCK) { 727 if (!ena) { 728 throw new HeaderException("Broken header"); 729 } 730 l = dataIn.readInt(); dataIn.skip(l); continue; 733 } 734 735 if (cmd == HMAC_BLOCK) { 737 if (!ena) { 738 throw new HeaderException("Broken header"); 739 } 740 l = dataIn.readInt(); macCode = new byte[l]; dataIn.readFully(macCode); continue; 744 } 745 746 if (cmd == KEY_BLOCK) { 748 if (!ena) { 749 throw new HeaderException("Broken header"); 750 } 751 752 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); 759 symKey = new SecretKeySpec(rsaEng.doFinal(d), algorithm); 760 continue; 761 } 762 763 if (cmd == IV_BLOCK) { 765 if (!ena) { 766 throw new HeaderException("Broken header"); 767 } 768 l = dataIn.readInt(); keyIV = new byte[l]; dataIn.readFully(keyIV); keyIV = rsaEng.doFinal(keyIV); continue; 773 } 774 775 if (cmd == HMAC_KEY_BLOCK) { 777 if (!ena) { 778 throw new HeaderException("Broken header"); 779 } 780 781 decHMAC = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 783 decHMAC.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 784 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); macKey = new SecretKeySpec(decHMAC.doFinal(d), "HMACSHA1"); 789 continue; 790 } 791 } catch (EOFException eof) { 792 stop = true; 793 } 794 } 795 796 mac = Mac.getInstance("HMACSHA1", "BC"); mac.init(macKey); 799 is.reset(); 801 macStr = new MacInputStream(is, mac); 802 dataStr = new DataInputStream(macStr); 803 804 int cmd = 0; byte[] buf = new byte[bufferlength]; l = 0; 808 do { 809 cmd = dataStr.readShort(); 811 if (cmd == DATA_BLOCK) { 813 l = dataStr.readInt(); dataStr.read(buf, 0, l); } 816 817 if (cmd == FINAL_DATA_BLOCK) { 819 l = dataStr.readInt(); 820 dataStr.read(buf, 0, l); } 822 823 824 if (cmd == KEY_BLOCK) { 826 l = dataStr.readInt(); 827 dataStr.read(buf, 0, l); } 829 830 if (cmd == IV_BLOCK) { 832 l = dataStr.readInt(); 833 dataStr.read(buf, 0, l); } 835 836 if (cmd == HMAC_KEY_BLOCK) { 838 l = dataStr.readInt(); 839 dataStr.read(buf, 0, l); } 841 } while (cmd != HMAC_BLOCK); 842 843 buf = mac.doFinal(); 844 dataStr.close(); 845 846 if (!MessageDigest.isEqual(buf, macCode)) { 847 throw new InvalidHMACException("Invalid HMAC"); 848 } 849 850 cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 851 cipher.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 852 853 is.reset(); 854 dataStr = new DataInputStream(is); 855 856 stop = false; cmd = 0; l = 0; buf = new byte[bufferlength]; byte[] out = null; 862 for (; ;) { 863 cmd = dataStr.readShort(); 865 if (cmd == DATA_BLOCK) { 866 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.update(buf, 0, l); 869 if (out != null) daos.write(out); 870 } 871 872 if (cmd == FINAL_DATA_BLOCK) { 873 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.doFinal(buf, 0, l); 876 if (out != null) daos.write(out); 877 break; 878 } 879 880 if (cmd == KEY_BLOCK) { 883 l = dataStr.readInt(); 884 dataStr.skip(l); 885 } 886 887 if (cmd == IV_BLOCK) { 889 l = dataStr.readInt(); 890 dataStr.skip(l); 891 } 892 893 if (cmd == HMAC_BLOCK) { 895 l = dataStr.readInt(); 896 dataStr.skip(l); 897 } 898 899 if (cmd == HMAC_KEY_BLOCK) { 901 l = dataStr.readInt(); 902 dataStr.skip(l); 903 } 904 } 905 } catch (IOException ioe) { 906 ioe.printStackTrace(); 907 throw new IOException(ioe.getMessage()); 908 } catch (HeaderException he) { 909 he.printStackTrace(); 910 throw new HeaderException(he.getMessage()); 911 } catch (InvalidHMACException ihe) { 912 ihe.printStackTrace(); 913 throw new InvalidHMACException(ihe.getMessage()); 914 } catch (Exception ex) { 915 ex.printStackTrace(); 916 throw new CryptoException(ex.getMessage()); 917 } 918 } 919 920 936 public static StringBuffer encryptAndSign(StringBuffer text 937 , PublicKey receiverKey 938 , PrivateKey signingKey 939 , X509Certificate cert 940 , String signame 941 , String algorithm 942 , byte[] seed 943 , int strength 944 , String mode 945 , String padding) throws CryptoException { 946 947 ByteArrayOutputStream bao = null; 948 DataOutputStream dao = null; 949 950 try { 951 bao = new ByteArrayOutputStream(); 952 dao = new DataOutputStream(bao); 953 954 encryptAndSign(new ByteArrayInputStream(text.toString().getBytes()), dao, receiverKey, signingKey, cert, signame, algorithm, seed, strength, mode, padding, BUFFERSIZE_TEXT); 956 return new StringBuffer (new String (Base64.encode(bao.toByteArray()))); 957 } catch (IOException ioe) { 958 ioe.printStackTrace(); 959 throw new CryptoException(ioe.getMessage()); 960 } finally { 961 if (dao != null) { 962 try { 964 dao.close(); 965 } catch (IOException e) { 966 ; 967 } 968 } 969 } 970 } 971 972 989 public static void encryptFileAndSign(String file 990 , String newfile 991 , PublicKey receiverKey 992 , PrivateKey signingKey 993 , X509Certificate cert 994 , String signame 995 , String algorithm 996 , byte[] seed 997 , int strength 998 , String mode 999 , String padding) 1000 throws CryptoException, IOException { 1001 1002 FileInputStream fis = null; 1003 FileOutputStream fos = null; 1004 DataOutputStream dao = null; 1005 1006 try { 1007 fis = new FileInputStream(file); 1008 1009 fos = new FileOutputStream(newfile); 1010 dao = new DataOutputStream(fos); 1011 1012 encryptAndSign(fis, dao, receiverKey, signingKey, cert, signame, algorithm, seed, strength, mode, padding, BUFFERSIZE_FILE); 1014 1015 } catch (IOException ioe) { 1016 ioe.printStackTrace(); 1017 throw new IOException(ioe.getMessage()); 1018 } finally { 1019 if (dao != null) { 1020 try { 1022 dao.close(); 1023 } catch (IOException e) { 1024 ; 1025 } 1026 } 1027 if (fis != null) { 1028 try { 1030 fis.close(); 1031 } catch (IOException e) { 1032 ; 1033 } 1034 } 1035 } 1036 } 1037 1038 1056 public static void encryptAndSign(InputStream is 1057 , DataOutputStream daos 1058 , PublicKey receiverKey 1059 , PrivateKey signingKey 1060 , X509Certificate cert 1061 , String signame 1062 , String algorithm 1063 , byte[] seed 1064 , int strength 1065 , String mode 1066 , String padding 1067 , int bufferlength) 1068 throws CryptoException, IOException { 1069 1070 SecureRandom secRand = null; 1071 KeyGenerator keyGen = null; 1072 Key symKey = null; 1073 Cipher outputCipher = null; 1074 1075 SignatureOutputStream sigStr = null; 1076 DataOutputStream dataStr = null; 1077 1078 try { 1079 Security.addProvider(new BouncyCastleProvider()); 1080 1081 secRand = Seed.getSecureRandom(seed); 1082 1083 keyGen = KeyGenerator.getInstance(algorithm, "BC"); 1085 keyGen.init(strength, secRand); 1086 symKey = keyGen.generateKey(); 1087 1088 outputCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 1090 outputCipher.init(Cipher.ENCRYPT_MODE, symKey, secRand); 1091 1092 byte[] keyEnc = symKey.getEncoded(); 1095 byte[] keyIV = outputCipher.getIV(); 1096 1097 byte[] lock = new byte[24]; 1098 1099 secRand.nextBytes(lock); 1100 1101 Signature sig = Signature.getInstance(signame, "BC"); 1103 sig.initSign(signingKey, secRand); sig.update(lock); 1106 Cipher rsaEng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); 1108 rsaEng.init(Cipher.ENCRYPT_MODE, receiverKey, secRand); 1109 1110 sigStr = new SignatureOutputStream(daos, sig); 1114 dataStr = new DataOutputStream(sigStr); 1115 1116 dataStr.writeShort(FILE_HEADER); 1119 dataStr.writeShort(KEY_BLOCK); byte[] tmp = rsaEng.doFinal(keyEnc); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); 1126 dataStr.writeShort(IV_BLOCK); tmp = rsaEng.doFinal(keyIV); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); 1133 dataStr.writeShort(LOCK_BLOCK); tmp = outputCipher.doFinal(lock); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); 1140 outputCipher.init(Cipher.ENCRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 1143 int l = 0; byte[] buf = new byte[bufferlength]; byte[] out = null; 1148 1150 while ((l = is.read(buf)) > -1) { 1151 out = outputCipher.update(buf, 0, l); if (out != null) { 1153 dataStr.writeShort(DATA_BLOCK); dataStr.writeInt(out.length); dataStr.write(out); } 1157 } 1158 1159 out = outputCipher.doFinal(); dataStr.writeShort(FINAL_DATA_BLOCK); dataStr.writeInt(out.length); dataStr.write(out); 1165 Clean.blank(buf); buf = null; 1168 dataStr.writeShort(CERT_BLOCK); tmp = cert.getEncoded(); dataStr.writeInt(tmp.length); dataStr.write(tmp); 1174 dataStr.writeShort(SIG_BLOCK); dataStr.flush(); 1178 tmp = sig.sign(); dataStr.writeInt(tmp.length); dataStr.write(tmp); Clean.blank(tmp); 1183 dataStr.flush(); 1185 dataStr.close(); 1186 } catch (IOException ioe) { 1187 ioe.printStackTrace(); 1188 throw new IOException(ioe.getMessage()); 1189 } catch (Exception ex) { 1190 ex.printStackTrace(); 1191 throw new CryptoException(ex.getMessage()); 1192 } finally { 1193 if (dataStr != null) { 1194 try { 1195 dataStr.close(); 1196 } catch (IOException ioe) { 1197 ; 1198 } 1199 } 1200 } 1201 } 1202 1203 1218 public static StringBuffer decryptAndVerify(StringBuffer text 1219 , PrivateKey privKey 1220 , SignerCertificate signercert 1221 , String signame 1222 , String algorithm 1223 , String mode 1224 , String padding) throws HeaderException, InvalidSignatureException, CryptoException { 1225 1226 ByteArrayOutputStream bao = null; 1227 DataOutputStream dao = null; 1228 1229 try { 1230 bao = new ByteArrayOutputStream(); 1231 dao = new DataOutputStream(bao); 1232 1233 decryptAndVerify(new ByteArrayInputStream(Base64.decode(text.toString())), dao, privKey, signercert, signame, algorithm, mode, padding, BUFFERSIZE_TEXT); 1235 1236 return new StringBuffer (new String (bao.toByteArray())); 1237 } catch (HeaderException he) { 1238 throw new HeaderException(he.getMessage()); 1239 } catch (InvalidSignatureException ise) { 1240 throw new InvalidSignatureException(ise.getMessage()); 1241 } catch (Exception ioe) { 1242 ioe.printStackTrace(); 1243 throw new CryptoException(ioe.getMessage()); 1244 } finally { 1245 if (dao != null) { 1246 try { 1248 dao.close(); 1249 } catch (IOException e) { 1250 ; 1251 } 1252 } 1253 } 1254 } 1255 1256 1273 public static void decryptAndVerify(InputStream is 1274 , DataOutputStream daos 1275 , PrivateKey privKey 1276 , SignerCertificate signercert 1277 , String signame 1278 , String algorithm 1279 , String mode 1280 , String padding 1281 , int bufferlength) 1282 throws CryptoException, HeaderException, InvalidSignatureException, IOException { 1283 1284 byte[] lockData = null; X509Certificate cert = null; SecretKey symKey = null; byte[] keyIV = null; byte[] sigCode = null; 1290 DataInputStream dataIn = null; 1291 1292 try { 1293 Security.addProvider(new BouncyCastleProvider()); 1294 1295 SecureRandom secRand = SecureRandom.getInstance("SHA1PRNG", "SUN"); 1296 1297 dataIn = new DataInputStream(is); 1298 1299 int l = 0; boolean ena = false; boolean stop = false; 1303 Cipher rsaEng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); 1305 rsaEng.init(Cipher.DECRYPT_MODE, privKey, secRand); 1307 while (!stop) { 1308 try { 1309 int cmd = dataIn.readShort(); 1311 if (cmd == Hybrid.FILE_HEADER) { 1313 ena = true; continue; 1315 } 1316 1317 if (cmd == Hybrid.DATA_BLOCK) { 1319 if (!ena) { 1320 throw new Exception ("Broken header"); 1321 } 1322 1323 l = dataIn.readInt(); dataIn.skip(l); continue; 1326 } 1327 1328 if (cmd == Hybrid.FINAL_DATA_BLOCK) { 1330 if (!ena) { 1331 throw new Exception ("Broken header"); 1332 } 1333 l = dataIn.readInt(); dataIn.skip(l); continue; 1336 } 1337 1338 if (cmd == Hybrid.SIG_BLOCK) { 1340 if (!ena) { 1341 throw new Exception ("Broken header"); 1342 } 1343 l = dataIn.readInt(); sigCode = new byte[l]; dataIn.readFully(sigCode); continue; 1347 } 1348 1349 if (cmd == Hybrid.KEY_BLOCK) { 1351 if (!ena) { 1352 throw new Exception ("Broken header"); 1353 } 1354 1355 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); 1359 1363 symKey = new SecretKeySpec(rsaEng.doFinal(d), algorithm); 1364 continue; 1365 } 1366 1367 if (cmd == Hybrid.IV_BLOCK) { 1369 if (!ena) { 1370 throw new Exception ("Broken header"); 1371 } 1372 l = dataIn.readInt(); keyIV = new byte[l]; dataIn.readFully(keyIV); keyIV = rsaEng.doFinal(keyIV); continue; 1377 } 1378 1379 if (cmd == Hybrid.LOCK_BLOCK) { 1381 if (!ena) { 1382 throw new Exception ("Broken header"); 1383 } 1384 1385 Cipher decLock = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 1387 decLock.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 1388 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); lockData = decLock.doFinal(d); 1393 decLock = null; 1395 continue; 1396 } 1397 1398 if (cmd == Hybrid.CERT_BLOCK) { 1400 if (!ena) { 1401 throw new Exception ("Broken header"); 1402 } 1403 1404 l = dataIn.readInt(); 1406 byte[] d = new byte[l]; 1408 dataIn.readFully(d); 1410 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 1411 cert = (X509Certificate ) cf.generateCertificate(new ByteArrayInputStream(d)); 1412 continue; 1413 } 1414 } catch (EOFException eof) { 1415 stop = true; 1416 } 1417 } 1418 1419 signercert.setCert(cert); 1421 1422 Signature sig = Signature.getInstance(signame, "BC"); 1424 sig.initVerify(cert); sig.update(lockData); 1427 is.reset(); 1429 SignatureInputStream sigStr = new SignatureInputStream(is, sig); 1430 DataInputStream dataStr = new DataInputStream(sigStr); 1431 1432 int cmd = 0; byte[] buf = new byte[bufferlength]; l = 0; 1436 for (; ;) { 1437 cmd = dataStr.readShort(); 1439 if (cmd == Hybrid.DATA_BLOCK) { 1441 l = dataStr.readInt(); dataStr.read(buf, 0, l); } 1444 1445 if (cmd == Hybrid.FINAL_DATA_BLOCK) { 1447 l = dataStr.readInt(); 1448 dataStr.read(buf, 0, l); } 1450 1451 1452 if (cmd == Hybrid.KEY_BLOCK) { 1454 l = dataStr.readInt(); 1455 dataStr.read(buf, 0, l); } 1457 1458 if (cmd == Hybrid.IV_BLOCK) { 1460 l = dataStr.readInt(); 1461 dataStr.read(buf, 0, l); } 1463 1464 if (cmd == Hybrid.LOCK_BLOCK) { 1466 l = dataStr.readInt(); 1467 dataStr.read(buf, 0, l); } 1469 1470 if (cmd == Hybrid.CERT_BLOCK) { 1472 l = dataStr.readInt(); 1473 dataStr.read(buf, 0, l); } 1475 1476 if (cmd == Hybrid.SIG_BLOCK) { 1477 break; 1478 } 1479 } 1480 1481 dataStr.close(); 1482 1483 if (!sig.verify(sigCode)) { 1485 throw new InvalidSignatureException("Signature is invalid"); 1486 } 1487 1488 Cipher cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 1489 cipher.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 1490 1491 1493 is.reset(); 1495 dataStr = new DataInputStream(is); 1496 1497 stop = false; cmd = 0; l = 0; buf = new byte[bufferlength]; byte[] out = null; 1503 for (; ;) { 1504 cmd = dataStr.readShort(); 1506 if (cmd == Hybrid.DATA_BLOCK) { 1507 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.update(buf, 0, l); 1510 if (out != null) daos.write(out); 1511 } 1512 1513 if (cmd == Hybrid.FINAL_DATA_BLOCK) { 1514 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.doFinal(buf, 0, l); 1517 if (out != null) daos.write(out); 1518 break; 1519 } 1520 1521 if (cmd == Hybrid.KEY_BLOCK) { 1524 l = dataStr.readInt(); 1525 dataStr.skip(l); 1526 } 1527 1528 if (cmd == Hybrid.IV_BLOCK) { 1530 l = dataStr.readInt(); 1531 dataStr.skip(l); 1532 } 1533 1534 if (cmd == Hybrid.LOCK_BLOCK) { 1536 l = dataStr.readInt(); 1537 dataStr.skip(l); 1538 } 1539 1540 if (cmd == Hybrid.CERT_BLOCK) { 1542 l = dataStr.readInt(); 1543 dataStr.skip(l); 1544 } 1545 1546 if (cmd == Hybrid.SIG_BLOCK) { 1547 l = dataStr.readInt(); 1548 dataStr.skip(l); 1549 } 1550 } 1551 1552 Clean.blank(buf); buf = null; 1555 dataStr.close(); 1556 } catch (IOException ioe) { 1557 ioe.printStackTrace(); 1558 throw new IOException(ioe.getMessage()); 1559 } catch (HeaderException he) { 1560 he.printStackTrace(); 1561 throw new HeaderException(he.getMessage()); 1562 } catch (InvalidSignatureException ise) { 1563 ise.printStackTrace(); 1564 throw new InvalidSignatureException(ise.getMessage()); 1565 } catch (Exception ex) { 1566 ex.printStackTrace(); 1567 throw new CryptoException(ex.getMessage()); 1568 } 1569 } 1570 1571 1587 public static void decryptFileAndVerify(String file 1588 , String newfile 1589 , PrivateKey privKey 1590 , SignerCertificate signercert 1591 , String signame 1592 , String algorithm 1593 , String mode 1594 , String padding) 1595 throws CryptoException, HeaderException, InvalidSignatureException, IOException { 1596 1597 byte[] lockData = null; X509Certificate cert = null; SecretKey symKey = null; byte[] keyIV = null; byte[] sigCode = null; 1603 SignatureInputStream sigStr = null; 1604 1605 DataInputStream dataIn = null; 1606 FileOutputStream outStr = null; 1607 DataInputStream dataStr = null; 1608 1609 try { 1610 Security.addProvider(new BouncyCastleProvider()); 1611 1612 SecureRandom secRand = SecureRandom.getInstance("SHA1PRNG", "SUN"); 1613 1614 dataIn = new DataInputStream(new FileInputStream(file)); 1615 1616 int l = 0; boolean ena = false; boolean stop = false; 1620 Cipher rsaEng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); 1622 rsaEng.init(Cipher.DECRYPT_MODE, privKey, secRand); 1624 while (!stop) { 1625 try { 1626 int cmd = dataIn.readShort(); 1628 if (cmd == Hybrid.FILE_HEADER) { 1630 ena = true; continue; 1632 } 1633 1634 if (cmd == Hybrid.DATA_BLOCK) { 1636 if (!ena) { 1637 throw new Exception ("Broken header"); 1638 } 1639 1640 l = dataIn.readInt(); dataIn.skip(l); continue; 1643 } 1644 1645 if (cmd == Hybrid.FINAL_DATA_BLOCK) { 1647 if (!ena) { 1648 throw new Exception ("Broken header"); 1649 } 1650 l = dataIn.readInt(); dataIn.skip(l); continue; 1653 } 1654 1655 if (cmd == Hybrid.SIG_BLOCK) { 1657 if (!ena) { 1658 throw new Exception ("Broken header"); 1659 } 1660 l = dataIn.readInt(); sigCode = new byte[l]; dataIn.readFully(sigCode); continue; 1664 } 1665 1666 if (cmd == Hybrid.KEY_BLOCK) { 1668 if (!ena) { 1669 throw new Exception ("Broken header"); 1670 } 1671 1672 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); 1676 1680 symKey = new SecretKeySpec(rsaEng.doFinal(d), algorithm); 1681 continue; 1682 } 1683 1684 if (cmd == Hybrid.IV_BLOCK) { 1686 if (!ena) { 1687 throw new Exception ("Broken header"); 1688 } 1689 l = dataIn.readInt(); keyIV = new byte[l]; dataIn.readFully(keyIV); keyIV = rsaEng.doFinal(keyIV); continue; 1694 } 1695 1696 if (cmd == Hybrid.LOCK_BLOCK) { 1698 if (!ena) { 1699 throw new Exception ("Broken header"); 1700 } 1701 1702 Cipher decLock = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 1704 decLock.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 1705 l = dataIn.readInt(); byte[] d = new byte[l]; dataIn.readFully(d); lockData = decLock.doFinal(d); 1710 decLock = null; 1712 continue; 1713 } 1714 1715 if (cmd == Hybrid.CERT_BLOCK) { 1717 if (!ena) { 1718 throw new Exception ("Broken header"); 1719 } 1720 1721 l = dataIn.readInt(); 1723 byte[] d = new byte[l]; 1725 dataIn.readFully(d); 1727 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 1728 cert = (X509Certificate ) cf.generateCertificate(new ByteArrayInputStream(d)); 1729 continue; 1730 } 1731 } catch (EOFException eof) { 1732 stop = true; 1733 } 1734 } 1735 1736 signercert.setCert(cert); 1738 1739 Signature sig = Signature.getInstance(signame, "BC"); 1741 sig.initVerify(cert); sig.update(lockData); 1744 sigStr = new SignatureInputStream(new FileInputStream(file), sig); 1746 dataStr = new DataInputStream(sigStr); 1747 1748 int cmd = 0; byte[] buf = new byte[BUFFERSIZE_FILE]; l = 0; 1752 for (; ;) { 1753 cmd = dataStr.readShort(); 1755 if (cmd == Hybrid.DATA_BLOCK) { 1757 l = dataStr.readInt(); dataStr.read(buf, 0, l); } 1760 1761 if (cmd == Hybrid.FINAL_DATA_BLOCK) { 1763 l = dataStr.readInt(); 1764 dataStr.read(buf, 0, l); } 1766 1767 1768 if (cmd == Hybrid.KEY_BLOCK) { 1770 l = dataStr.readInt(); 1771 dataStr.read(buf, 0, l); } 1773 1774 if (cmd == Hybrid.IV_BLOCK) { 1776 l = dataStr.readInt(); 1777 dataStr.read(buf, 0, l); } 1779 1780 if (cmd == Hybrid.LOCK_BLOCK) { 1782 l = dataStr.readInt(); 1783 dataStr.read(buf, 0, l); } 1785 1786 if (cmd == Hybrid.CERT_BLOCK) { 1788 l = dataStr.readInt(); 1789 dataStr.read(buf, 0, l); } 1791 1792 if (cmd == Hybrid.SIG_BLOCK) { 1793 break; 1794 } 1795 } 1796 1797 dataStr.close(); 1798 1799 if (!sig.verify(sigCode)) { 1801 throw new InvalidSignatureException("Signature is invalid"); 1802 } 1803 1804 Cipher cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "BC"); 1805 cipher.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(keyIV)); 1806 1807 outStr = new FileOutputStream(newfile); 1809 dataStr = new DataInputStream(new FileInputStream(file)); 1811 1812 stop = false; cmd = 0; l = 0; buf = new byte[BUFFERSIZE_FILE]; byte[] out = null; 1818 for (; ;) { 1819 cmd = dataStr.readShort(); 1821 if (cmd == Hybrid.DATA_BLOCK) { 1822 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.update(buf, 0, l); 1825 if (out != null) outStr.write(out); 1826 } 1827 1828 if (cmd == Hybrid.FINAL_DATA_BLOCK) { 1829 l = dataStr.readInt(); dataStr.readFully(buf, 0, l); out = cipher.doFinal(buf, 0, l); 1832 if (out != null) outStr.write(out); 1833 break; 1834 } 1835 1836 if (cmd == Hybrid.KEY_BLOCK) { 1839 l = dataStr.readInt(); 1840 dataStr.skip(l); 1841 } 1842 1843 if (cmd == Hybrid.IV_BLOCK) { 1845 l = dataStr.readInt(); 1846 dataStr.skip(l); 1847 } 1848 1849 if (cmd == Hybrid.LOCK_BLOCK) { 1851 l = dataStr.readInt(); 1852 dataStr.skip(l); 1853 } 1854 1855 if (cmd == Hybrid.CERT_BLOCK) { 1857 l = dataStr.readInt(); 1858 dataStr.skip(l); 1859 } 1860 1861 if (cmd == Hybrid.SIG_BLOCK) { 1862 l = dataStr.readInt(); 1863 dataStr.skip(l); 1864 } 1865 } 1866 1867 Clean.blank(buf); buf = null; 1870 } catch (IOException ioe) { 1871 ioe.printStackTrace(); 1872 throw new IOException(ioe.getMessage()); 1873 } catch (HeaderException he) { 1874 he.printStackTrace(); 1875 throw new HeaderException(he.getMessage()); 1876 } catch (InvalidSignatureException ise) { 1877 ise.printStackTrace(); 1878 throw new InvalidSignatureException(ise.getMessage()); 1879 } catch (Exception ex) { 1880 ex.printStackTrace(); 1881 throw new CryptoException(ex.getMessage()); 1882 } finally { 1883 if (outStr != null) { 1884 try { 1886 outStr.close(); 1887 } catch (IOException e) { 1888 ; 1889 } 1890 } 1891 if (dataStr != null) { 1892 try { 1894 dataStr.close(); 1895 } catch (IOException e) { 1896 ; 1897 } 1898 } 1899 } 1900 } 1901} 1902 | Popular Tags |