2014-07-19 49 views
3

我想要一個C++版本的下列Java代碼。如何在openssl的BIGNUM中使用負數?

BigInteger x = new BigInteger("00afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d", 16); 
BigInteger y = x.multiply(BigInteger.valueOf(-1)); 

//prints y = ff5028d4a7ca52dd15a297d860053f49ad83e54f04ce0e19b908d728a342c519a3 
System.out.println("y = " + new String(Hex.encode(y.toByteArray()))); 

這裏是我的解決方案的嘗試。

BIGNUM* x = BN_new(); 
BN_CTX* ctx = BN_CTX_new(); 
std::vector<unsigned char> xBytes = hexStringToBytes(「00afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d"); 
BN_bin2bn(&xBytes[0], xBytes.size(), x); 

BIGNUM* negative1 = BN_new(); 
std::vector<unsigned char> negative1Bytes = hexStringToBytes("ff"); 
BN_bin2bn(&negative1Bytes[0], negative1Bytes.size(), negative1); 

BIGNUM* y = BN_new(); 
BN_mul(y, x, negative1, ctx); 

char* yHex = BN_bn2hex(y); 
std::string yStr(yHex); 
//prints y = AF27542CDD7775C7730ABF785AC5F59C299E964A36BFF460B031AE85607DAB76A3 
std::cout <<"y = " << yStr << std::endl; 

(忽略此案。)我在做什麼錯了?如何讓我的C++代碼輸出正確的值「ff5028d4a7ca52dd15a297d860053f49ad83e54f04ce0e19b908d728a342c519a3」。我也嘗試通過做BN_set_word(negative1,-1)來設置negative1,但這也給我錯誤的答案。

+1

'hexStringToBytes(「00' ...有一個奇怪的引號......希望這是一個複製粘貼錯誤,而不是實際上在您的源文件中 –

+1

您嘗試過'BN_set_negative'嗎? –

+0

嗯。 「AFD72B5835AD22EA5D68279FFAC0B6527C1AB0FB31F1E646F728D75CBD3AE65D」 – user299648

回答

4

BN_set_negative函數設置一個負數。

afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d的負值實際上是-afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d,與-2的負值相同,爲2的負值。

ff5028d4a7ca52dd15a297d860053f49ad83e54f04ce0e19b908d728a342c519a3是一個很大的正數。

你在Java中看到這個數字的原因是由於toByteArray調用。 According to its documentation,它選擇整個字節數的最小字段寬度,並且還能夠保持負數的二進制補碼錶示。

換句話說,通過使用數字上的toByteArray函數,電流有1個符號位和256個值位,結果字段寬度爲264位。但是,如果您的負數的第一個半字節是7而不是a,那麼(根據本文檔 - 我沒有真正嘗試過),您將獲得256位的字段寬度(即8028d4...,而不是ff8028d4

您在代碼中使用的主要00在OpenSSL BN中是無關緊要的我不確定它在BigInteger中是否有意義,儘管該構造函數的文檔說「字符串表示由一個可選的減號或加號後跟一個指定基數中一個或多個數字的順序「;因此它接受一個減號的事實表明,如果不存在減號,則即使設置了MSB,輸入也會被視爲一個大的正數。希望Java程序員能夠清除這個段落p對我來說)。

請務必保持清醒的在你的頭腦大的負值,並通過模運算對負值獲得一個大的正數的區別,比如是toByteArray輸出。


所以你的問題是真的:不Openssl的BN有模仿BigInteger.toByteArray的)行爲(功能?

我不知道這樣的函數是否存在(BN庫有相當不好的文檔恕我直言,我從來沒有聽說過它在OpenSSL之外使用,特別是不在C++程序中)。我期望它不會,因爲toByteArray的行爲有點怪異;在任何情況下,所有的BN輸出函數似乎都使用符號幅度格式輸出,而不是二進制補碼格式。

但要複製該輸出,您可以將2^2562^264添加到較大的負數,然後執行BN_bn2hex。在這個特殊情況下,添加2^264,一般來說,你必須測量被存儲的數字的當前比特長度並將指數四捨五入到最接近的8的倍數。

或者你甚至可以輸出符號幅度格式(使用BN_bn2hexBN_bn2mpi),然後通過反轉每個半字節並修復開始來重複!

注意:你想使用OpenSSL BN有什麼特別的理由嗎? There are many alternatives

+0

BN_bn2mpi以符號幅度格式輸出(它只是設置開始,然後調用BN_bn2bin) –

+0

文檔太糟糕了,我必須查看源代碼才能找出實際發生的情況 –