22using System . Collections ;
33using System . Diagnostics ;
44using System . IO ;
5+ using crypto . openpgp ;
56using Org . BouncyCastle . Asn1 ;
67using Org . BouncyCastle . Asn1 . Misc ;
78using Org . BouncyCastle . Asn1 . X9 ;
@@ -1116,60 +1117,6 @@ public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[]
11161117 return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false , pubKey ) ;
11171118 }
11181119
1119- internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , PgpPublicKey pubKey )
1120- {
1121- SXprUtilities reader = new SXprUtilities ( inputStream ) ;
1122-
1123- reader . SkipOpenParenthesis ( ) ;
1124-
1125- string type = reader . ReadString ( ) ;
1126- if ( type . Equals ( "protected-private-key" ) )
1127- {
1128- reader . SkipOpenParenthesis ( ) ;
1129-
1130- string curveName ;
1131-
1132- string keyType = reader . ReadString ( ) ;
1133- if ( keyType . Equals ( "ecc" ) )
1134- {
1135- reader . SkipOpenParenthesis ( ) ;
1136-
1137- string curveID = reader . ReadString ( ) ;
1138- curveName = reader . ReadString ( ) ;
1139-
1140- reader . SkipCloseParenthesis ( ) ;
1141- }
1142- else
1143- {
1144- throw new PgpException ( "no curve details found" ) ;
1145- }
1146-
1147- byte [ ] qVal ;
1148-
1149- reader . SkipOpenParenthesis ( ) ;
1150-
1151- type = reader . ReadString ( ) ;
1152- if ( type . Equals ( "q" ) )
1153- {
1154- qVal = reader . ReadBytes ( ) ;
1155- }
1156- else
1157- {
1158- throw new PgpException ( "no q value found" ) ;
1159- }
1160-
1161- reader . SkipCloseParenthesis ( ) ;
1162-
1163- byte [ ] dValue = GetDValue ( reader , rawPassPhrase , clearPassPhrase , curveName ) ;
1164- // TODO: check SHA-1 hash.
1165-
1166- return new PgpSecretKey ( new SecretKeyPacket ( pubKey . PublicKeyPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1167- new ECSecretBcpgKey ( new BigInteger ( 1 , dValue ) ) . GetEncoded ( ) ) , pubKey ) ;
1168- }
1169-
1170- throw new PgpException ( "unknown key type found" ) ;
1171- }
1172-
11731120 /// <summary>
11741121 /// Parse a secret key from one of the GPG S expression keys.
11751122 /// </summary>
@@ -1179,7 +1126,7 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[
11791126 /// </remarks>
11801127 public static PgpSecretKey ParseSecretKeyFromSExpr ( Stream inputStream , char [ ] passPhrase )
11811128 {
1182- return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true ) ;
1129+ return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true , null ) ;
11831130 }
11841131
11851132 /// <summary>
@@ -1190,7 +1137,7 @@ public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] pa
11901137 /// </remarks>
11911138 public static PgpSecretKey ParseSecretKeyFromSExprUtf8 ( Stream inputStream , char [ ] passPhrase )
11921139 {
1193- return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true ) ;
1140+ return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true , null ) ;
11941141 }
11951142
11961143 /// <summary>
@@ -1201,14 +1148,16 @@ public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[
12011148 /// </remarks>
12021149 public static PgpSecretKey ParseSecretKeyFromSExprRaw ( Stream inputStream , byte [ ] rawPassPhrase )
12031150 {
1204- return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , rawPassPhrase , false ) ;
1151+ return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false , null ) ;
12051152 }
12061153
12071154 /// <summary>
12081155 /// Parse a secret key from one of the GPG S expression keys.
12091156 /// </summary>
1210- internal static PgpSecretKey DoParseSecretKeyFromSExpr ( SXprUtilities reader , byte [ ] rawPassPhrase , bool clearPassPhrase )
1157+ internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , PgpPublicKey pubKey )
12111158 {
1159+ SXprReader reader = new SXprReader ( inputStream ) ;
1160+
12121161 reader . SkipOpenParenthesis ( ) ;
12131162
12141163 string type = reader . ReadString ( ) ;
@@ -1272,28 +1221,87 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(SXprUtilities reader, byt
12721221 throw new PgpException ( "no q value found" ) ;
12731222 }
12741223
1275- PublicKeyPacket pubPacket = new PublicKeyPacket (
1276- flags == "eddsa" ? PublicKeyAlgorithmTag . EdDsa : PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1277- new ECDsaPublicBcpgKey ( curveOid , new BigInteger ( 1 , qVal ) ) ) ;
1224+ if ( pubKey == null )
1225+ {
1226+ PublicKeyPacket pubPacket = new PublicKeyPacket (
1227+ flags == "eddsa" ? PublicKeyAlgorithmTag . EdDsa : PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1228+ new ECDsaPublicBcpgKey ( curveOid , new BigInteger ( 1 , qVal ) ) ) ;
1229+ pubKey = new PgpPublicKey ( pubPacket ) ;
1230+ }
12781231
12791232 reader . SkipCloseParenthesis ( ) ;
12801233
1281- byte [ ] dValue = GetDValue ( reader , rawPassPhrase , clearPassPhrase , curveName ) ;
1282- // TODO: check SHA-1 hash.
1234+ byte [ ] dValue = GetDValue ( reader , pubKey . PublicKeyPacket , rawPassPhrase , clearPassPhrase , curveName ) ;
12831235
1284- return new PgpSecretKey ( new SecretKeyPacket ( pubPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1285- new ECSecretBcpgKey ( new BigInteger ( 1 , dValue ) ) . GetEncoded ( ) ) , new PgpPublicKey ( pubPacket ) ) ;
1236+ return new PgpSecretKey ( new SecretKeyPacket ( pubKey . PublicKeyPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1237+ new ECSecretBcpgKey ( new BigInteger ( 1 , dValue ) ) . GetEncoded ( ) ) , pubKey ) ;
12861238 }
12871239
12881240 throw new PgpException ( "unknown key type found" ) ;
12891241 }
12901242
1291- private static byte [ ] GetDValue ( SXprUtilities reader , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
1243+ private static void WriteSExprPublicKey ( SXprWriter writer , PublicKeyPacket pubPacket , string curveName , string protectedAt )
1244+ {
1245+ writer . StartList ( ) ;
1246+ switch ( pubPacket . Algorithm )
1247+ {
1248+ case PublicKeyAlgorithmTag . ECDsa :
1249+ case PublicKeyAlgorithmTag . EdDsa :
1250+ writer . WriteString ( "ecc" ) ;
1251+ writer . StartList ( ) ;
1252+ writer . WriteString ( "curve" ) ;
1253+ writer . WriteString ( curveName ) ;
1254+ writer . EndList ( ) ;
1255+ if ( pubPacket . Algorithm == PublicKeyAlgorithmTag . EdDsa )
1256+ {
1257+ writer . StartList ( ) ;
1258+ writer . WriteString ( "flags" ) ;
1259+ writer . WriteString ( "eddsa" ) ;
1260+ writer . EndList ( ) ;
1261+ }
1262+ writer . StartList ( ) ;
1263+ writer . WriteString ( "q" ) ;
1264+ writer . WriteBytes ( ( ( ECDsaPublicBcpgKey ) pubPacket . Key ) . EncodedPoint . ToByteArrayUnsigned ( ) ) ;
1265+ writer . EndList ( ) ;
1266+ break ;
1267+
1268+ case PublicKeyAlgorithmTag . RsaEncrypt :
1269+ case PublicKeyAlgorithmTag . RsaSign :
1270+ case PublicKeyAlgorithmTag . RsaGeneral :
1271+ RsaPublicBcpgKey rsaK = ( RsaPublicBcpgKey ) pubPacket . Key ;
1272+ writer . WriteString ( "rsa" ) ;
1273+ writer . StartList ( ) ;
1274+ writer . WriteString ( "n" ) ;
1275+ writer . WriteBytes ( rsaK . Modulus . ToByteArrayUnsigned ( ) ) ;
1276+ writer . EndList ( ) ;
1277+ writer . StartList ( ) ;
1278+ writer . WriteString ( "e" ) ;
1279+ writer . WriteBytes ( rsaK . PublicExponent . ToByteArrayUnsigned ( ) ) ;
1280+ writer . EndList ( ) ;
1281+ break ;
1282+
1283+ // TODO: DSA, etc.
1284+ default :
1285+ throw new PgpException ( "unsupported algorithm in S expression" ) ;
1286+ }
1287+
1288+ if ( protectedAt != null )
1289+ {
1290+ writer . StartList ( ) ;
1291+ writer . WriteString ( "protected-at" ) ;
1292+ writer . WriteString ( protectedAt ) ;
1293+ writer . EndList ( ) ;
1294+ }
1295+ writer . EndList ( ) ;
1296+ }
1297+
1298+ private static byte [ ] GetDValue ( SXprReader reader , PublicKeyPacket publicKey , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
12921299 {
12931300 string type ;
12941301 reader . SkipOpenParenthesis ( ) ;
12951302
12961303 string protection ;
1304+ string protectedAt = null ;
12971305 S2k s2k ;
12981306 byte [ ] iv ;
12991307 byte [ ] secKeyData ;
@@ -1312,26 +1320,42 @@ private static byte[] GetDValue(SXprUtilities reader, byte[] rawPassPhrase, bool
13121320 reader . SkipCloseParenthesis ( ) ;
13131321
13141322 secKeyData = reader . ReadBytes ( ) ;
1323+
1324+ reader . SkipCloseParenthesis ( ) ;
1325+
1326+ reader . SkipOpenParenthesis ( ) ;
1327+
1328+ if ( reader . ReadString ( ) . Equals ( "protected-at" ) )
1329+ {
1330+ protectedAt = reader . ReadString ( ) ;
1331+ }
13151332 }
13161333 else
13171334 {
13181335 throw new PgpException ( "protected block not found" ) ;
13191336 }
13201337
1321- // Valid values of protection: openpgp-s2k3-sha1-aes-cbc, openpgp-s2k3-ocb-aes, openpgp-native
13221338 byte [ ] data ;
13231339 KeyParameter key ;
13241340
13251341 switch ( protection )
13261342 {
1343+ case "openpgp-s2k3-sha1-aes256-cbc" :
13271344 case "openpgp-s2k3-sha1-aes-cbc" :
1328- key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1329- data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , "/CBC/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1345+ SymmetricKeyAlgorithmTag symmAlg =
1346+ protection . Equals ( "openpgp-s2k3-sha1-aes256-cbc" ) ? SymmetricKeyAlgorithmTag . Aes256 : SymmetricKeyAlgorithmTag . Aes128 ;
1347+ key = PgpUtilities . DoMakeKeyFromPassPhrase ( symmAlg , s2k , rawPassPhrase , clearPassPhrase ) ;
1348+ data = RecoverKeyData ( symmAlg , "/CBC/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1349+ // TODO: check SHA-1 hash.
13301350 break ;
13311351
13321352 case "openpgp-s2k3-ocb-aes" :
1353+ MemoryStream aad = new MemoryStream ( ) ;
1354+ WriteSExprPublicKey ( new SXprWriter ( aad ) , publicKey , curveName , protectedAt ) ;
13331355 key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1334- data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , "/OCB/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1356+ IBufferedCipher c = CipherUtilities . GetCipher ( "AES/OCB" ) ;
1357+ c . Init ( false , new AeadParameters ( key , 128 , iv , aad . ToArray ( ) ) ) ;
1358+ data = c . DoFinal ( secKeyData , 0 , secKeyData . Length ) ;
13351359 break ;
13361360
13371361 case "openpgp-native" :
@@ -1344,7 +1368,7 @@ private static byte[] GetDValue(SXprUtilities reader, byte[] rawPassPhrase, bool
13441368 //
13451369 Stream keyIn = new MemoryStream ( data , false ) ;
13461370
1347- reader = new SXprUtilities ( keyIn ) ;
1371+ reader = new SXprReader ( keyIn ) ;
13481372 reader . SkipOpenParenthesis ( ) ;
13491373 reader . SkipOpenParenthesis ( ) ;
13501374 reader . SkipOpenParenthesis ( ) ;
0 commit comments