40
40
import java .security .NoSuchAlgorithmException ;
41
41
import java .security .PrivateKey ;
42
42
import java .security .PublicKey ;
43
- import java .security .SecureRandom ;
44
43
import java .security .interfaces .RSAPrivateCrtKey ;
44
+ import java .security .interfaces .RSAPrivateKey ;
45
45
import java .security .interfaces .RSAPublicKey ;
46
46
import java .security .spec .InvalidKeySpecException ;
47
47
import java .security .spec .RSAKeyGenParameterSpec ;
48
48
import java .security .spec .RSAPrivateCrtKeySpec ;
49
+ import java .security .spec .RSAPrivateKeySpec ;
49
50
import java .security .spec .RSAPublicKeySpec ;
50
51
51
52
import static javax .crypto .Cipher .*;
@@ -108,7 +109,11 @@ public static RaiseException newRSAError(Ruby runtime, String message) {
108
109
}
109
110
110
111
static RaiseException newRSAError (Ruby runtime , Throwable cause ) {
111
- return Utils .newError (runtime , _PKey (runtime ).getClass ("RSAError" ), cause .getMessage (), cause );
112
+ return newRSAError (runtime , cause .getMessage (), cause );
113
+ }
114
+
115
+ static RaiseException newRSAError (Ruby runtime , String message , Throwable cause ) {
116
+ return Utils .newError (runtime , _PKey (runtime ).getClass ("RSAError" ), message , cause );
112
117
}
113
118
114
119
public PKeyRSA (Ruby runtime , RubyClass type ) {
@@ -126,7 +131,7 @@ public PKeyRSA(Ruby runtime, RubyClass type, RSAPrivateCrtKey privKey, RSAPublic
126
131
}
127
132
128
133
private volatile RSAPublicKey publicKey ;
129
- private volatile transient RSAPrivateCrtKey privateKey ;
134
+ private volatile transient RSAPrivateKey privateKey ;
130
135
131
136
// fields to hold individual RSAPublicKeySpec components. this allows
132
137
// a public key to be constructed incrementally, as required by the
@@ -317,8 +322,9 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
317
322
}
318
323
else if ( key instanceof RSAPrivateCrtKey ) {
319
324
this .privateKey = (RSAPrivateCrtKey ) key ;
325
+ BigInteger exponent = ((RSAPrivateCrtKey ) key ).getPublicExponent ();
320
326
try {
321
- this .publicKey = (RSAPublicKey ) rsaFactory .generatePublic (new RSAPublicKeySpec (privateKey .getModulus (), privateKey . getPublicExponent () ));
327
+ this .publicKey = (RSAPublicKey ) rsaFactory .generatePublic (new RSAPublicKeySpec (privateKey .getModulus (), exponent ));
322
328
} catch (GeneralSecurityException e ) {
323
329
throw newRSAError (runtime , e .getMessage ());
324
330
} catch (RuntimeException e ) {
@@ -355,7 +361,7 @@ public RubyBoolean private_p() {
355
361
public RubyString to_der () {
356
362
final byte [] bytes ;
357
363
try {
358
- bytes = toDerRSAKey (publicKey , privateKey );
364
+ bytes = toDerRSAKey (publicKey , privateKey instanceof RSAPrivateCrtKey ? ( RSAPrivateCrtKey ) privateKey : null );
359
365
}
360
366
catch (NoClassDefFoundError e ) {
361
367
throw newRSAError (getRuntime (), bcExceptionMessage (e ));
@@ -380,7 +386,8 @@ public PKeyRSA public_key() {
380
386
public IRubyObject params (final ThreadContext context ) {
381
387
final Ruby runtime = context .runtime ;
382
388
RubyHash hash = RubyHash .newHash (runtime );
383
- if ( privateKey != null ) {
389
+ if (privateKey instanceof RSAPrivateCrtKey ) {
390
+ RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey ) this .privateKey ;
384
391
hash .op_aset (context , runtime .newString ("iqmp" ), BN .newBN (runtime , privateKey .getCrtCoefficient ()));
385
392
hash .op_aset (context , runtime .newString ("n" ), BN .newBN (runtime , privateKey .getModulus ()));
386
393
hash .op_aset (context , runtime .newString ("d" ), BN .newBN (runtime , privateKey .getPrivateExponent ()));
@@ -406,7 +413,8 @@ public IRubyObject params(final ThreadContext context) {
406
413
@ JRubyMethod
407
414
public RubyString to_text () {
408
415
StringBuilder result = new StringBuilder ();
409
- if (privateKey != null ) {
416
+ if (privateKey instanceof RSAPrivateCrtKey ) {
417
+ RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey ) this .privateKey ;
410
418
int len = privateKey .getModulus ().bitLength ();
411
419
result .append ("Private-Key: (" ).append (len ).append (" bit)" ).append ('\n' );
412
420
result .append ("modulus:" );
@@ -446,8 +454,8 @@ public RubyString to_pem(ThreadContext context, final IRubyObject[] args) {
446
454
447
455
try {
448
456
final StringWriter writer = new StringWriter ();
449
- if ( privateKey != null ) {
450
- PEMInputOutput .writeRSAPrivateKey (writer , privateKey , spec , passwd );
457
+ if (privateKey instanceof RSAPrivateCrtKey ) {
458
+ PEMInputOutput .writeRSAPrivateKey (writer , ( RSAPrivateCrtKey ) privateKey , spec , passwd );
451
459
}
452
460
else {
453
461
PEMInputOutput .writeRSAPublicKey (writer , publicKey );
@@ -603,8 +611,8 @@ public synchronized IRubyObject set_iqmp(final ThreadContext context, IRubyObjec
603
611
@ JRubyMethod (name ="iqmp" )
604
612
public synchronized IRubyObject get_iqmp () {
605
613
BigInteger iqmp ;
606
- if (privateKey != null ) {
607
- iqmp = privateKey .getCrtCoefficient ();
614
+ if (privateKey instanceof RSAPrivateCrtKey ) {
615
+ iqmp = (( RSAPrivateCrtKey ) privateKey ) .getCrtCoefficient ();
608
616
} else {
609
617
iqmp = rsa_iqmp ;
610
618
}
@@ -617,8 +625,8 @@ public synchronized IRubyObject get_iqmp() {
617
625
@ JRubyMethod (name ="dmp1" )
618
626
public synchronized IRubyObject get_dmp1 () {
619
627
BigInteger dmp1 ;
620
- if (privateKey != null ) {
621
- dmp1 = privateKey .getPrimeExponentP ();
628
+ if (privateKey instanceof RSAPrivateCrtKey ) {
629
+ dmp1 = (( RSAPrivateCrtKey ) privateKey ) .getPrimeExponentP ();
622
630
} else {
623
631
dmp1 = rsa_dmp1 ;
624
632
}
@@ -631,8 +639,8 @@ public synchronized IRubyObject get_dmp1() {
631
639
@ JRubyMethod (name ="dmq1" )
632
640
public synchronized IRubyObject get_dmq1 () {
633
641
BigInteger dmq1 ;
634
- if (privateKey != null ) {
635
- dmq1 = privateKey .getPrimeExponentQ ();
642
+ if (privateKey instanceof RSAPrivateCrtKey ) {
643
+ dmq1 = (( RSAPrivateCrtKey ) privateKey ) .getPrimeExponentQ ();
636
644
} else {
637
645
dmq1 = rsa_dmq1 ;
638
646
}
@@ -659,8 +667,8 @@ public synchronized IRubyObject get_d() {
659
667
@ JRubyMethod (name ="p" )
660
668
public synchronized IRubyObject get_p () {
661
669
BigInteger p ;
662
- if (privateKey != null ) {
663
- p = privateKey .getPrimeP ();
670
+ if (privateKey instanceof RSAPrivateCrtKey ) {
671
+ p = (( RSAPrivateCrtKey ) privateKey ) .getPrimeP ();
664
672
} else {
665
673
p = rsa_p ;
666
674
}
@@ -673,8 +681,8 @@ public synchronized IRubyObject get_p() {
673
681
@ JRubyMethod (name ="q" )
674
682
public synchronized IRubyObject get_q () {
675
683
BigInteger q ;
676
- if (privateKey != null ) {
677
- q = privateKey .getPrimeQ ();
684
+ if (privateKey instanceof RSAPrivateCrtKey ) {
685
+ q = (( RSAPrivateCrtKey ) privateKey ) .getPrimeQ ();
678
686
} else {
679
687
q = rsa_q ;
680
688
}
@@ -687,8 +695,8 @@ public synchronized IRubyObject get_q() {
687
695
private BigInteger getPublicExponent () {
688
696
if (publicKey != null ) {
689
697
return publicKey .getPublicExponent ();
690
- } else if (privateKey != null ) {
691
- return privateKey .getPublicExponent ();
698
+ } else if (privateKey instanceof RSAPrivateCrtKey ) {
699
+ return (( RSAPrivateCrtKey ) privateKey ) .getPublicExponent ();
692
700
} else {
693
701
return rsa_e ;
694
702
}
@@ -750,6 +758,32 @@ public synchronized IRubyObject set_n(final ThreadContext context, IRubyObject v
750
758
return value ;
751
759
}
752
760
761
+ @ JRubyMethod
762
+ public IRubyObject set_key (final ThreadContext context , IRubyObject n , IRubyObject e , IRubyObject d ) {
763
+ this .rsa_n = BN .getBigInteger (n );
764
+ this .rsa_e = BN .getBigInteger (e );
765
+ this .rsa_d = BN .getBigInteger (d );
766
+ generatePrivateKeyIfParams (context );
767
+ return this ;
768
+ }
769
+
770
+ @ JRubyMethod
771
+ public IRubyObject set_factors (final ThreadContext context , IRubyObject p , IRubyObject q ) {
772
+ this .rsa_p = BN .getBigInteger (p );
773
+ this .rsa_q = BN .getBigInteger (q );
774
+ generatePrivateKeyIfParams (context );
775
+ return this ;
776
+ }
777
+
778
+ @ JRubyMethod
779
+ public IRubyObject set_crt_params (final ThreadContext context , IRubyObject dmp1 , IRubyObject dmq1 , IRubyObject iqmp ) {
780
+ this .rsa_dmp1 = BN .asBigInteger (dmp1 );
781
+ this .rsa_dmq1 = BN .asBigInteger (dmq1 );
782
+ this .rsa_iqmp = BN .asBigInteger (iqmp );
783
+ generatePrivateKeyIfParams (context );
784
+ return this ;
785
+ }
786
+
753
787
private void generatePublicKeyIfParams (final ThreadContext context ) {
754
788
final Ruby runtime = context .runtime ;
755
789
@@ -783,14 +817,12 @@ private void generatePublicKeyIfParams(final ThreadContext context) {
783
817
private void generatePrivateKeyIfParams (final ThreadContext context ) {
784
818
final Ruby runtime = context .runtime ;
785
819
786
- if ( privateKey != null ) throw newRSAError (runtime , "illegal modification" );
787
-
788
820
// Don't access the rsa_n and rsa_e fields directly. They may have
789
821
// already been consumed and cleared by generatePublicKeyIfParams.
790
822
BigInteger _rsa_n = getModulus ();
791
823
BigInteger _rsa_e = getPublicExponent ();
792
824
793
- if (_rsa_n != null && _rsa_e != null && rsa_p != null && rsa_q != null && rsa_d != null && rsa_dmp1 != null && rsa_dmq1 != null && rsa_iqmp != null ) {
825
+ if (_rsa_n != null && _rsa_e != null && rsa_d != null ) {
794
826
final KeyFactory rsaFactory ;
795
827
try {
796
828
rsaFactory = SecurityHelper .getKeyFactory ("RSA" );
@@ -799,17 +831,24 @@ private void generatePrivateKeyIfParams(final ThreadContext context) {
799
831
throw runtime .newLoadError ("unsupported key algorithm (RSA)" );
800
832
}
801
833
802
- try {
803
- privateKey = (RSAPrivateCrtKey ) rsaFactory .generatePrivate (
804
- new RSAPrivateCrtKeySpec (_rsa_n , _rsa_e , rsa_d , rsa_p , rsa_q , rsa_dmp1 , rsa_dmq1 , rsa_iqmp )
805
- );
806
- }
807
- catch (InvalidKeySpecException e ) {
808
- throw newRSAError (runtime , "invalid parameters" );
834
+ if (rsa_p != null && rsa_q != null && rsa_dmp1 != null && rsa_dmq1 != null && rsa_iqmp != null ) {
835
+ try {
836
+ privateKey = (RSAPrivateCrtKey ) rsaFactory .generatePrivate (
837
+ new RSAPrivateCrtKeySpec (_rsa_n , _rsa_e , rsa_d , rsa_p , rsa_q , rsa_dmp1 , rsa_dmq1 , rsa_iqmp )
838
+ );
839
+ } catch (InvalidKeySpecException e ) {
840
+ throw newRSAError (runtime , "invalid parameters" , e );
841
+ }
842
+ rsa_n = null ; rsa_e = null ; rsa_d = null ;
843
+ rsa_p = null ; rsa_q = null ;
844
+ rsa_dmp1 = null ; rsa_dmq1 = null ; rsa_iqmp = null ;
845
+ } else {
846
+ try {
847
+ privateKey = (RSAPrivateKey ) rsaFactory .generatePrivate (new RSAPrivateKeySpec (_rsa_n , rsa_d ));
848
+ } catch (InvalidKeySpecException e ) {
849
+ throw newRSAError (runtime , "invalid parameters" , e );
850
+ }
809
851
}
810
- rsa_n = null ; rsa_e = null ;
811
- rsa_d = null ; rsa_p = null ; rsa_q = null ;
812
- rsa_dmp1 = null ; rsa_dmq1 = null ; rsa_iqmp = null ;
813
852
}
814
853
}
815
854
0 commit comments