AbstractValue.java 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Password Management Servlets (PWM)
  3. * http://www.pwm-project.org
  4. *
  5. * Copyright (c) 2006-2009 Novell, Inc.
  6. * Copyright (c) 2009-2021 The PWM Project
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. package password.pwm.config.value;
  21. import org.jrivard.xmlchai.XmlChai;
  22. import org.jrivard.xmlchai.XmlDocument;
  23. import org.jrivard.xmlchai.XmlElement;
  24. import password.pwm.PwmConstants;
  25. import password.pwm.config.stored.StoredConfigXmlConstants;
  26. import password.pwm.config.stored.XmlOutputProcessData;
  27. import password.pwm.data.ImmutableByteArray;
  28. import password.pwm.error.PwmUnrecoverableException;
  29. import password.pwm.util.java.JavaHelper;
  30. import password.pwm.util.java.LazySupplier;
  31. import password.pwm.util.java.StringUtil;
  32. import password.pwm.util.json.JsonFactory;
  33. import password.pwm.util.json.JsonProvider;
  34. import password.pwm.util.secure.PwmHashAlgorithm;
  35. import password.pwm.util.secure.PwmSecurityKey;
  36. import java.io.IOException;
  37. import java.io.OutputStream;
  38. import java.security.DigestOutputStream;
  39. import java.util.List;
  40. import java.util.Locale;
  41. public abstract class AbstractValue implements StoredValue
  42. {
  43. private static final PwmSecurityKey HASHING_KEY;
  44. static
  45. {
  46. try
  47. {
  48. HASHING_KEY = new PwmSecurityKey( "hash-key" );
  49. }
  50. catch ( final PwmUnrecoverableException e )
  51. {
  52. throw new IllegalStateException( "unable to create internal HASHING_KEY: " + e.getMessage() );
  53. }
  54. }
  55. private final transient LazySupplier<String> valueHashSupplier = LazySupplier.create( () -> valueHashComputer( AbstractValue.this ) );
  56. public String toString()
  57. {
  58. return toDebugString( null );
  59. }
  60. @Override
  61. public String toDebugString( final Locale locale )
  62. {
  63. return JsonFactory.get().serialize( this.toNativeObject(), JsonProvider.Flag.PrettyPrint );
  64. }
  65. @Override
  66. public Object toDebugJsonObject( final Locale locale )
  67. {
  68. return this.toNativeObject();
  69. }
  70. @Override
  71. public int currentSyntaxVersion()
  72. {
  73. return 0;
  74. }
  75. @Override
  76. public final String valueHash()
  77. {
  78. return valueHashSupplier.get();
  79. }
  80. protected static String b64encode( final ImmutableByteArray immutableByteArray )
  81. {
  82. final String input = StringUtil.base64Encode( immutableByteArray.copyOf(), StringUtil.Base64Options.GZIP );
  83. return "\n" + StringUtil.insertRepeatedLineBreaks( input, PwmConstants.XML_OUTPUT_LINE_WRAP_LENGTH ) + "\n";
  84. }
  85. protected static ImmutableByteArray b64decode( final String b64EncodedContents )
  86. {
  87. try
  88. {
  89. final CharSequence whitespaceStripped = StringUtil.stripAllWhitespace( b64EncodedContents );
  90. final byte[] output = StringUtil.base64Decode( whitespaceStripped, StringUtil.Base64Options.GZIP );
  91. return ImmutableByteArray.of( output );
  92. }
  93. catch ( final Exception e )
  94. {
  95. throw new IllegalStateException( e );
  96. }
  97. }
  98. static String valueHashComputer( final StoredValue storedValue )
  99. {
  100. try
  101. {
  102. final XmlOutputProcessData xmlOutputProcessData = XmlOutputProcessData.builder()
  103. .pwmSecurityKey( HASHING_KEY )
  104. .storedValueEncoderMode( StoredValueEncoder.Mode.PLAIN )
  105. .build();
  106. final List<XmlElement> xmlValues = storedValue.toXmlValues( StoredConfigXmlConstants.XML_ELEMENT_VALUE, xmlOutputProcessData );
  107. final XmlDocument document = XmlChai.getFactory().newDocument( "root" );
  108. document.getRootElement().attachElement( xmlValues );
  109. final DigestOutputStream digestOutputStream = new DigestOutputStream(
  110. OutputStream.nullOutputStream(),
  111. PwmHashAlgorithm.SHA512.newMessageDigest() );
  112. XmlChai.getFactory().output( document, digestOutputStream );
  113. return JavaHelper.binaryArrayToHex( digestOutputStream.getMessageDigest().digest() );
  114. }
  115. catch ( final IOException e )
  116. {
  117. throw new IllegalStateException( e );
  118. }
  119. }
  120. }